阿里云主机推荐码,可以打九折8C0BAY 有效期 11-30号
posted @
2015-10-15 18:13 hellxoul 阅读(185) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2015-01-05 11:52 hellxoul 阅读(296) |
评论 (0) |
编辑 收藏
如果不配置其他参数,大致相当于以下的配置文件(参考自org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser)
1 <!-- 配置路径扩展名映射的媒体类型 -->
2 <bean name="pathExtensionContentNegotiationStrategy"
3 class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
4 <constructor-arg>
5 <props>
6 <!-- if romePresent -->
7 <prop key="atom">application/atom+xml</prop>
8 <prop key="rss">application/rss+xml</prop>
9 <!-- endif -->
10 <!-- if jackson2Present || jacksonPresent -->
11 <prop key="json">application/json</prop>
12 <!-- endif -->
13 <!-- if jaxb2Present -->
14 <prop key="xml">application/xml</prop>
15 <!-- endif -->
16 </props>
17 </constructor-arg>
18 </bean>
19
20 <!-- 配置映射媒体类型的策略 -->
21 <bean name="mvcContentNegotiationManager"
22 class="org.springframework.web.accept.ContentNegotiationManager">
23 <constructor-arg>
24 <list>
25 <ref bean="pathExtensionContentNegotiationStrategy" />
26 </list>
27 </constructor-arg>
28 </bean>
29
30 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
31 <property name="order" value="0"/>
32 <property name="removeSemicolonContent" value="false"/>
33 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager"/>
34 </bean>
35
36 <!-- 配置数据转换服务,默认使用格式化数据转换服务,可以对日期和数字进行格式化 -->
37 <bean name="conversionService"
38 class="org.springframework.format.support.DefaultFormattingConversionService">
39 <constructor-arg index="0">
40 <null/>
41 </constructor-arg>
42 <constructor-arg index="1" value="true"/>
43 </bean>
44
45 <bean name="validator"
46 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
47
48 <!-- 配置数据绑定,通过转换服务实现绑定,如果包含jsr303实现还将进行校验 -->
49 <bean name="webBindingInitializer"
50 class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
51 <property name="conversionService" ref="conversionService" />
52 <!-- if jsr303Present -->
53 <property name="validator" ref="validator" />
54 <!-- endif -->
55 </bean>
56
57 <bean name="byteArrayHttpMessageConverter"
58 class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
59
60 <bean name="stringHttpMessageConverter"
61 class="org.springframework.http.converter.StringHttpMessageConverter">
62 <property name="writeAcceptCharset" value="false" />
63 </bean>
64
65 <bean name="resourceHttpMessageConverter"
66 class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
67 <bean name="sourceHttpMessageConverter"
68 class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
69 <bean name="allEncompassingFormHttpMessageConverter"
70 class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
71 <bean name="atomFeedHttpMessageConverter"
72 class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
73 <bean name="rssChannelHttpMessageConverter"
74 class="org.springframework.http.converter.feed.RssChannelHttpMessageConverter"/>
75 <bean name="jaxb2RootElementHttpMessageConverter"
76 class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
77 <bean name="mappingJacksonHttpMessageConverter"
78 class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
79
80 <!-- 配置@RequestBody,@ResponseBody注解可用的转换器 -->
81 <util:list id="messageConverters"
82 list-class="org.springframework.beans.factory.support.ManagedList">
83 <ref bean="byteArrayHttpMessageConverter" />
84 <ref bean="stringHttpMessageConverter" />
85 <ref bean="resourceHttpMessageConverter" />
86 <ref bean="sourceHttpMessageConverter" />
87 <ref bean="allEncompassingFormHttpMessageConverter" />
88 <!-- if romePresent -->
89 <ref bean="atomFeedHttpMessageConverter" />
90 <ref bean="rssChannelHttpMessageConverter" />
91 <!-- endif -->
92 <!-- if jaxb2Present -->
93 <ref bean="jaxb2RootElementHttpMessageConverter" />
94 <!-- endif -->
95 <!-- if jacksonPresent -->
96 <ref bean="mappingJacksonHttpMessageConverter" />
97 <!-- endif -->
98 </util:list>
99
100 <!-- 将任意类型的Controller适配为Handler -->
101 <bean name="requestMappingHandlerAdapter"
102 class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
103 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
104 <property name="webBindingInitializer" ref="webBindingInitializer" />
105 <property name="messageConverters" ref="messageConverters" />
106 </bean>
107
108 <!-- 这个拦截器暴露转换器服务让spring:bind和spring:eval标签可用 -->
109 <bean name="csInterceptor"
110 class="org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor">
111 <constructor-arg index="0" ref="conversionService"/>
112 </bean>
113
114 <!-- 现在所有拦截器都必须设定响应的路径映射 -->
115 <bean name="mappedCsInterceptor"
116 class="org.springframework.web.servlet.handler.MappedInterceptor">
117 <constructor-arg index="0">
118 <null/>
119 </constructor-arg>
120 <constructor-arg index="1" ref="csInterceptor"/>
121 </bean>
122
123 <!-- 使用@ExceptionHandler注解的方法来处理Exception,优先级为0(最高) -->
124 <bean name="exceptionHandlerExceptionResolver"
125 class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
126 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
127 <property name="messageConverters" ref="messageConverters" />
128 <property name="order" value="0" />
129 </bean>
130
131 <!-- 如果抛出的Exception类带有@ResponseStatus注解,响应返回该注解的Http状态码,优先级为1 -->
132 <bean name="responseStatusExceptionResolver"
133 class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver">
134 <property name="order" value="1" />
135 </bean>
136
137 <!-- SpringMvc内部异常处理 -->
138 <bean name="defaultExceptionResolver"
139 class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver">
140 <property name="order" value="2" />
141 </bean>
142
posted @
2014-08-03 22:35 hellxoul 阅读(2885) |
评论 (1) |
编辑 收藏
HeadFirst Servlet/JSP 学习笔记
1.容器加载类,调用servlet的无参构造方法,并调用servlet的init()方法,从而初始化servlet。
2.init()在servlet一生中只调用一次,往往在servlet为客户请求提供服务之前调用。
3.init()方法使servlet可以访问ServletConfig和ServletContext对象,servlet需要从这些对象得到有关servlet配置和web应用的信息。
4.容器通过调用servlet的destroy()方法来结束servlet的生命
5.servlet一生的大多时间都是在为某个客户端请求运行service()方法
6.对servlet的每个请求都在一个单独的线程中运行,任何特定servlet类都只有一个实例。
posted @
2014-07-05 15:21 hellxoul 阅读(260) |
评论 (0) |
编辑 收藏
转自:
http://www.cnblogs.com/peida/p/Guava_Ordering.html
Ordering是Guava类库提供的一个犀利强大的比较器工具,Guava的Ordering和JDK Comparator相比功能更强。它非常容易扩展,可以轻松构造复杂的comparator,然后用在容器的比较、排序等操作中。
本质上来说,Ordering 实例无非就是一个特殊的Comparator 实例。Ordering只是需要依赖于一个比较器(例如,Collections.max)的方法,并使其可作为实例方法。另外,Ordering提供了链式方法调用和加强现有的比较器。
下面我们看看Ordering中的一些具体方法和简单的使用实例。
常见的静态方法:
natural():使用Comparable类型的自然顺序, 例如:整数从小到大,字符串是按字典顺序;
usingToString() :使用toString()返回的字符串按字典顺序进行排序;
arbitrary() :返回一个所有对象的任意顺序, 即compare(a, b) == 0 就是 a == b (identity equality)。 本身的排序是没有任何含义, 但是在VM的生命周期是一个常量。
简单实例:
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testStaticOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
Ordering<Object> usingToStringOrdering = Ordering.usingToString();
Ordering<Object> arbitraryOrdering = Ordering.arbitrary();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("usingToStringOrdering:"+ usingToStringOrdering.sortedCopy(list));
System.out.println("arbitraryOrdering:"+ arbitraryOrdering.sortedCopy(list));
}
}
输出:
list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
usingToStringOrdering:[eva, harry, jerry, jhon, neron, peida]
arbitraryOrdering:[neron, harry, eva, jerry, peida, jhon]
操作方法:
reverse(): 返回与当前Ordering相反的排序:
nullsFirst(): 返回一个将null放在non-null元素之前的Ordering,其他的和原始的Ordering一样;
nullsLast():返回一个将null放在non-null元素之后的Ordering,其他的和原始的Ordering一样;
compound(Comparator):返回一个使用Comparator的Ordering,Comparator作为第二排序元素,例如对bug列表进行排序,先根据bug的级别,再根据优先级进行排序;
lexicographical():返回一个按照字典元素迭代的Ordering;
onResultOf(Function):将function应用在各个元素上之后, 在使用原始ordering进行排序;
greatestOf(Iterable iterable, int k):返回指定的第k个可迭代的最大的元素,按照这个从最大到最小的顺序。是不稳定的。
leastOf(Iterable<E> iterable,int k):返回指定的第k个可迭代的最小的元素,按照这个从最小到最大的顺序。是不稳定的。
isOrdered(Iterable):是否有序,Iterable不能少于2个元素。
isStrictlyOrdered(Iterable):是否严格有序。请注意,Iterable不能少于两个元素。
sortedCopy(Iterable):返回指定的元素作为一个列表的排序副本。
package com.peidasoft.guava.base;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
List<Integer> listReduce= Lists.newArrayList();
for(int i=9;i>0;i--){
listReduce.add(i);
}
List<Integer> listtest= Lists.newArrayList();
listtest.add(1);
listtest.add(1);
listtest.add(1);
listtest.add(2);
Ordering<Integer> naturalIntReduceOrdering = Ordering.natural();
System.out.println("listtest:"+ listtest);
System.out.println(naturalIntReduceOrdering.isOrdered(listtest));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(listtest));
System.out.println("naturalIntReduceOrdering:"+ naturalIntReduceOrdering.sortedCopy(listReduce));
System.out.println("listReduce:"+ listReduce);
System.out.println(naturalIntReduceOrdering.isOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
Ordering<String> natural = Ordering.natural();
List<String> abc = ImmutableList.of("a", "b", "c");
System.out.println(natural.isOrdered(abc));
System.out.println(natural.isStrictlyOrdered(abc));
System.out.println("isOrdered reverse :"+ natural.reverse().isOrdered(abc));
List<String> cba = ImmutableList.of("c", "b", "a");
System.out.println(natural.isOrdered(cba));
System.out.println(natural.isStrictlyOrdered(cba));
System.out.println(cba = natural.sortedCopy(cba));
System.out.println("max:"+natural.max(cba));
System.out.println("min:"+natural.min(cba));
System.out.println("leastOf:"+natural.leastOf(cba, 2));
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("leastOf list:"+naturalOrdering.leastOf(list, 3));
System.out.println("greatestOf:"+naturalOrdering.greatestOf(list, 3));
System.out.println("reverse list :"+ naturalOrdering.reverse().sortedCopy(list));
System.out.println("isOrdered list :"+ naturalOrdering.isOrdered(list));
System.out.println("isOrdered list :"+ naturalOrdering.reverse().isOrdered(list));
list.add(null);
System.out.println(" add null list:"+list);
System.out.println("nullsFirst list :"+ naturalOrdering.nullsFirst().sortedCopy(list));
System.out.println("nullsLast list :"+ naturalOrdering.nullsLast().sortedCopy(list));
}
}
//============输出==============
list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
listtest:[1, 1, 1, 2]
true
false
naturalIntReduceOrdering:[1, 2, 3, 4, 5, 6, 7, 8, 9]
listReduce:[9, 8, 7, 6, 5, 4, 3, 2, 1]
true
true
true
true
isOrdered reverse :false
false
false
[a, b, c]
max:c
min:a
leastOf:[a, b]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
leastOf list:[eva, harry, jerry]
greatestOf:[peida, neron, jhon]
reverse list :[peida, neron, jhon, jerry, harry, eva]
isOrdered list :false
isOrdered list :false
add null list:[peida, jerry, harry, eva, jhon, neron, null]
nullsFirst list :[null, eva, harry, jerry, jhon, neron, peida]
nullsLast list :[eva, harry, jerry, jhon, neron, peida, null]
posted @
2014-07-03 10:48 hellxoul 阅读(285) |
评论 (0) |
编辑 收藏
摘要: centos 6.5 安装rabbitmq
阅读全文
posted @
2014-06-25 22:23 hellxoul 阅读(2248) |
评论 (0) |
编辑 收藏
转自:http://singo107.iteye.com/blog/1175084
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。
√: 可能出现 ×: 不会出现
| 脏读 | 不可重复读 | 幻读 |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
注意:我们讨论隔离级别的场景,主要是在多个事务并发 的情况下,因此,接下来的讲解都围绕事务并发。
Read uncommitted 读未提交
公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高 兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有 2000元,singo空欢喜一场。
出现上述情况,即我们所说的脏读 ,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。
当隔离级别设置为Read uncommitted 时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。
Read committed 读提交
singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在 singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为 何......
出现上述情况,即我们所说的不可重复读 ,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
当隔离级别设置为Read committed 时,避免了脏读,但是可能会造成不可重复读。
大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。
Repeatable read 重复读
当隔离级别设置为Repeatable read 时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。
虽然Repeatable read避免了不可重复读,但还有可能出现幻读 。
singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额 (select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出 现了幻觉,幻读就这样产生了。
注:Mysql的默认隔离级别就是Repeatable read。
Serializable 序列化
Serializable 是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
posted @
2014-06-15 15:15 hellxoul 阅读(226) |
评论 (0) |
编辑 收藏
在上一篇文章中提到过,我已经不在Google工作了。我还没有想清楚应该去哪里—有两三个非常好的工作机会摆在我面前。因为在这段做决定时间里,我不再受雇于任何人,我想可以写一些专业性的东西,一些很有趣,但也会在同事和管理工作中导致关系紧张的东西。Google是一个非常优秀的公司。他们做出了很多令人称赞的东西—既是公司外部,人们可以看到的东西,也是公司内部。有一些在公司内部并不属于保密的事情,在外部并没有给予足够广泛的讨论。这就是我今天要说的。
让Google的程序如此优秀的一个最重要的事情看起来是非常的简单:代码审查。并不是只有Google做这个事情—代码审查已经被广泛的认可为一种非常好的做法,很多人都在这样做。但我还没有看到第二家这样大的公司能把这种事情运用的如此普遍。在Google,没有程序,任何产品、任何项目的程序代码,可以在没有经过有效的代码审查前提交到代码库里的。
所有人都要经过代码审查。并且很正规的:这种事情应该成为任何重要的软件开发工作中一个基本制度。并不单指产品程序——所有东西。它不需要很多的工作,但它的效果是巨大的。
从代码审查里能得到什么?
很显然:在代码提交前,用第二群眼睛检查一遍,防止bug混入。这是对其最常见的理解,是对代码审查的好处的最广泛的认识。但是,依我的经验来看,这反倒是它最不重要的一点。人们确实在代码审查中找到了bug。可是,这些在代码审查中能发现的绝大部分bug,很显然,都是微不足道的bug,程序的作者花几分钟的时间就能发现它们。真正需要花时间去发现的bug不是在代码审查里能找到的。
代码审查的最大的功用是纯社会性的。如果你在编程,而且知道将会有同事检查你的代码,你编程态度就完全不一样了。你写出的代码将更加整洁,有更好的注释,更好的程序结构——因为你知道,那个你很在意的人将会查看你的程序。没有代码审查,你知道人们最终还是会看你的程序。但这种事情不是立即发生的事,它不会给你带来同等的紧迫感,它不会给你相同的个人评判的那种感受。
还有一个非常重要的好处。代码审查能传播知识。在很多的开发团队里,经常每一个人负责一个核心模块,每个人都只关注他自己的那个模块。除非是同事的模块影响了自己的程序,他们从不相互交流。这种情况的后果是,每个模块只有一个人熟悉里面的代码。如果这个人休假或——但愿不是——辞职了,其他人则束手无策。通过代码审查,至少会有两个人熟悉这些程序——作者,以及审查者。审查者并不能像程序的作者一样对程序十分了解——但他会熟悉程序的设计和架构,这是极其重要的。
当然,没有什么事情能简单的做下来的。依我的经验,在你能正确的进行代码审查前,你需要花时间锻炼学习。我发现人们在代码审查时经常会犯一些错误,导致不少麻烦——尤其在一些缺乏经验的审查者中经常的出现,他们给了人们一个很遭的代码审查的体验,成为了人们接受代码审查制度的一个障碍。
最重要的一个原则:代码审查用意是在代码提交前找到其中的问题——你要发现是它的正确。在代码审查中最常犯的错误——几乎每个新手都会犯的错误——是,审查者根据自己的编程习惯来评判别人的代码。
对于一个问题,通常我们能找出十几种方法去解决。对于一种解决方案,我们能有百万种编码方案来实现它。作为一个审查者,你的任务不是来确保被审查的代码都采用的是你的编码风格——因为它不可能跟你写的一样。作为一段代码的审查者的任务是确保由作者自己写出的代码是正确的。一旦这个原则被打破,你最终将会倍感折磨,深受挫折——这可不是我们想要的结果。
问题在于,这种错误是如此的普遍而易犯。如果你是个程序员,当你遇到一个问题,你能想到一种解决方案——你就把你想到的方案作为标准答案。但事情不是这样的——作为一个好的审查者,你需要明白这个道理。
代码审查的第二个易犯的毛病是,人们觉得有压力,感觉非要说点什么才好。你知道作者用了大量的时间和精力来实现这些程序——不该说点什么吗?
不,你不需要。
只说一句“哇,不错呀”,任何时候都不会不合适。如果你总是力图找出一点什么东西来批评,你这样做的结果只会损害自己的威望。当你不厌其烦的找出一些东西来,只是为了说些什么,被审查人就会知道,你说这些话只是为了填补寂静。你的评论将不再被人重视。
第三是速度。你不能匆匆忙忙的进行一次代码审查——但你也要能迅速的完成。你的同伴在等你。如果你和你的同事并不想花太多时间进行代码复查,你们很快的完成,那被审查者会觉得很沮丧,这种代码审查带来的只有失望的感觉。就好象是打搅了大家,使大家放下手头的工作来进行审查。事情不该是这样。你并不需要推掉手头上的任何事情来做代码审查。但如果中途耽误了几个小时,你中间还要休息一会,喝杯茶,冲个澡,或谈会儿闲话。当你回到审查现场,你可以继续下去,把事情做完。如果你真是这样,我想没有人愿意在那干等着你。
posted @
2014-06-06 10:04 hellxoul 阅读(209) |
评论 (0) |
编辑 收藏
wps只有32位的,因此要安装wps必须安装32位的支持库,按照网上的教程先安装32位的一些依赖库
因为已经安装了libfreetype,网上也说64位的安装32位的libfreetype 会有问题,同时,自己系统也装不上32位的libfreetype 总是提示冲突。
没办法强制安装
sudo dpkg -i --force-all --ignore-depends=libfreetype6:i386 --ignore-depends=libfontconfig1:i386 wps-office_8.1.0.3724~b1p2_i386.deb
搞定
posted @
2014-04-20 21:40 hellxoul 阅读(1486) |
评论 (0) |
编辑 收藏
使用win8.1系统盘启动,进入系统修复-高级-命令行,使用bcdboot 命令复制启动盘的启动到现有系统中去
bcdboot h:\windows \s c:
h:为系统启动盘所在的盘符
posted @
2014-04-19 20:41 hellxoul 阅读(201) |
评论 (0) |
编辑 收藏
基于云的应用与运行在私有数据中心的应用之间最大的差别就是可扩展性。云提供了按需扩展的能力,能够根据负载的波动对应用进行扩展和收缩。但是传统应用要充分发挥云的优势,并不是简单地将应用部署到云上就万事大吉,而是需要根据云的特点围绕可扩展性重新进行架构设计,近日AppDynamics的开发布道者Dustin.Whittle撰文阐述了适合云端部署的应用架构,对我们传统应用往云端部署有很大的启发和借鉴意义。
应用的架构
Dustin.Whittle给出了云应用的示例架构,它具有高度的可扩展性,如下图所示:
在这个图中,应用按照分层的理念进行了拆分,分别介绍如下:
客户端层:客户端层包含了针对目标平台的用户界面,可能会包括基于Web的、移动端的甚至是胖客户端的用户界面。一般来讲,这可能会是Web应用,包含诸如用户管理、会话管理、页面构建等功能,但是其他客户端所发起的交互都需要以RESTful服务的形式调用服务器。
服务:服务器包含了缓存服务以及聚合(aggregate)服务,其中缓存服务中持有记录系统(system of record)中最新的已知状态,而聚集服务会直接与记录系统交互,并且会执行一些破坏性的操作(会改变记录系统中的状态)。
记录系统:记录系统是领域特定的服务端,它会驱动业务功能,可能会包括客户管理系统、采购系统、预定系统等等,这些很可能是遗留系统,你的应用需要与其进行交互。聚集服务要负责将你的应用从这些特有的记录系统中抽象出来,并为你的应用提供一致的前端接口。
ESB:当记录系统发生数据变化的时候,它需要触发到指定主题(topic)的事件,这就是事件驱动架构(event-driven architecture,EDA)能够影响应用的地方了:当记录系统进行了一项其他系统可能感兴趣的变更时,它会触发一个事件,任何关注记录系统的其他系统会监听到这个事件,并作出对应的响应。这也是使用使用主题(topic)而不是队列(queue)的原因:队列支持点对点(point-to-point)的消息,而主题支持发布-订阅(publish-subscribe)的消息或事件。当与遗留系统进行集成时,我们很期望这些遗留的系统能够免遭负载的影响。因此,我们实现了一个缓存系统,这个缓存系统维持了记录系统中所有最新的已知状态。缓存系统会使用EDA的规则监听记录系统的变化,它会更新自己所保存数据的版本,从而保证与记录系统中的数据相匹配。这是一个很强大的策略,不过会将一致性模型变为最终一致性,也就是说如果你在社交媒体上发布一条状态的话,你的朋友可能在几秒钟甚至几分钟之后才能看到,数据最终是一致的,但有时你所看到的与你的朋友所看到的并不一致。如果能接受这种一致性的话,就能在很大程度上实现可扩展性的收益。
NoSQL:在数据存储方面,有很多的可选方案,但如果要存储大量数据的话,使用NoSQL存储能够更容易地扩展。有多种NoSQL存储可供选择,不过这要匹配所存储数据的特点,如MongoDB适合存储可搜索的数据,Neo4j适合存储高度互相关联的数据,而Cassandra适合存储键/值对,像Solr这样的搜索索引有利于加速对经常访问数据的查询。
将应用拆分为多个层的时候,最好的模式就是使用面向服务架构(service-oriented architecture,SOA)。要实现这一点,可以使用SOAP,也可以使用REST,但是REST更为合适,因为它可扩展性更强。作者接下来对REST的理念进行了深入的阐述,InfoQ上关于REST已有很多相关的文章,如这里和这里,甚至包括Roy Fielding经典博士论文的中译本,所以这里不再赘述。不过,作者在这里特别强调了RESTful Web服务能够保持无状态性(stateless)。无状态是实现可扩展性的关键需求,因为无状态,所以请求可以由任何一个服务器响应。如果你在服务层上需要更多的容量时,只需要为该层添加虚拟机即可,而不需关注客户端状态保持的问题,负载可以很容易地重新分配。
部署到云端
前面介绍了基于云的应用架构,接下来作者阐述了这样的应用该如何部署到云端。
RESTful Web服务要部署到Web容器中,并且要位于数据存储之前。这些Web服务是没有状态的,只会反映其暴露的底层数据的状态,因此可以根据需要部署任意数量的服务器。在基于云的部署中,开始时可以开启足够的实例以应对日常的需求,然后配置弹性策略,从而根据负载增加或减少服务器的数量。衡量饱和度的最好指标就是服务的响应时间。另外还需要考虑这些服务所使用的底层数据存储的性能。示例的部署图如下所示:
如果在云部署时有EDA的需求,那么就需要部署ESB,作者给出的建议是根据功能对ESB进行分区(partitioning),这样一个segment的过大负载不会影响到其他的segment。如下图所示:
这种分离使System 1的负载与System 2的负载实现了隔离。如果System 1产生的负载拖慢了ESB,它只会影响到自己的segment,并不会影响到System 2的segment,因为它部署在其他硬件上。如果ESB产品支持的话,我们还可以给指定的segment添加服务器来实现扩展。
基于云的应用与传统应用有着很大的差别,因为它有着不同的扩展性需求。基于云的应用必须有足够的弹性以应对服务器的添加与移除,必须松耦合,必须尽可能的无状态,必须预先规划失败的情况,并且必须能够从几台服务器扩展到成千上万台服务器。
针对云应用并没有唯一正确的架构,但是本文所阐述的RESTful服务以及事件驱动架构却是经过实践检验有效的架构。作者认为REST和EDA是实现云端可扩展应用的基本工具。
目前,国内许多传统的软件厂商正在逐渐往云端迁移,希望本文所阐述的架构理念能够为读者提供一些借鉴。
posted @
2014-03-25 09:18 hellxoul 阅读(350) |
评论 (0) |
编辑 收藏
from:http://www.douban.com/group/topic/35067110/
收集帖: node.js 中文api (开放版) :http://nodeapi.ucdok.com/ node.js 中文api :http://jsfuns.com/ebook/#30d25070-118c-11e3-bc83-47c9e4e1d529 node.js入门中文版: http://nodebeginner.org/index-zh-cn.html express3.*中文API: http://expressjs.jser.us/ koa 中文文档:https://github.com/turingou/koa-guide //Express 原班人马打造的 比express更轻更富有表现力的web框架 深入理解Express: http://xvfeng.me/posts/understanding-expressjs/ meteor中文文档:http://d0cs.meteor.com/ NodeJS 和 Socket.io 中文入门教程:http://t.cn/zOMwxCg jade中文文档: http://expressjs.jser.us/jade.html Juicer 中文文档:http://juicer.name/docs/docs_zh_cn.html Mongoose 基本功能使用:http://t.cn/zOIKPeB 以下是一些blog教程系列: 让我们基于Node.js创建一个Web应用系列(5篇):http://t.cn/z8JnzkA 一周node.js系列(7篇) :http://t.cn/zOKuc9D 从零开始nodejs系列: http://blog.fens.me/series-nodejs/ 一起学node.js (荐): http://t.cn/zHxNXXt Node.js高级编程(荐): http://t.cn/zYmuqaH 深入浅出Node.js http://www.infoq.com/cn/master-nodejs Node.js零起点开发:http://blog.csdn.net/kaosini/article/details/8084268 node.js入门(共13篇)http://www.cnblogs.com/softlover/category/406516.html snoopyxdy的博客(大量node及express api的解读及进阶内容):http://t.cn/zQuKMKH 用node.js写web框架系列:http://my.oschina.net/Jeky/blog?catalog=262655 Luics的node.js系列: http://t.cn/zjATQlf 使用node.js建博客:http://witcheryne.iteye.com/blog/1172069 nodejs相关: 用socket.io 搭建聊天室: https://github.com/nswbmw/N-chat/wiki/_pages nodejs实体中文图书: 了不起的node.js: http://book.douban.com/subject/25767596/ 2014年1月 node.js高级编程: http://book.douban.com/subject/25799431/ 2013年12月 深入浅出nodejs: http://book.douban.com/subject/25768396/ 2013年12月 node.js入门经典: http://book.douban.com/subject/23780706/ 2013年4月 node.js开发指南: http://book.douban.com/subject/10789820/ 2012年7月 Node Web开发: http://book.douban.com/subject/10586326/ 2012年4月
posted @
2014-02-25 15:13 hellxoul 阅读(1088) |
评论 (0) |
编辑 收藏
mosquito 是一个MQTT 服务器。MQTT协议可用来做Android消息推送,服务器端采用mosquito+PhpMQTTClient(这个php用来做实验)
自己不会java,不会Android开发,推送的开发部分是同事做的。使用情况表明,单台服务器能满足几万的稳定的连接数,扩展起来也不难,加机器即可。
下载最新版的mosquitto
cd /usr/local/src
wget http://mosquitto.org/files/source/mosquitto-1.1.2.tar.gz
tar zxvf mosquitto-1.1.2.tar.gz
cd mosquitto-1.1.2
如果当前openssl版本低于1.0,修改config.mk中的WITH_TLS_PSK:=no
make
make install prefix=/usr/local/mosquitto
为方便管理,添加下面至/etc/profile
export PATH=”$PATH:/usr/local/mosquitto/bin”
export PATH=”$PATH:/usr/local/mosquitto/sbin”
source /etc/profile
[root@mysql230 mosquitto]# mosquitto #tab补全,四个命令
mosquitto mosquitto_passwd mosquitto_pub mosquitto_sub
mosquitto服务器主程序,实现了MQTT协议
mosquitto_pub mosquitto发布消息的命令行程序
mosquitto_sub mosquitto订阅消息的命令行程序
默认的配置文件在 /etc/mosquitto/里
将/usr/local/mosquitto/lib/添加至/etc/ld.so.conf
执行 ldconfig -f /etc/ld.so.conf 可能需要等待数秒
启动
mosquitto (-d后台启动)
可能提示没有用户 mosquitto,useradd mosquitto
终端测试
客户端 mosquitto_sub -h 192.168.1.230 -t test
另起命令行mosquitto_pub -t test -m ’123′
PhpMQTTClient安装
去https://github.com/tokudu/PhpMQTTClient 下载程序包,放置到服务器目录
可能需要结合实际情况,要修改的地方
index.php
$result = $conn->connect(SAM_MQTT, array(‘SAM_HOST’ => ’127.0.0.1′, ‘SAM_PORT’ => 1883));
SAM/MQTT/sam_mqtt.php
$this->port = 1883;
启动mosquitto在前台运行,以方便获取连接客户端的信息
mosquitto
在服务器另外一终端上启动订阅消息的进程,订阅所有tokudu开头topic
mosquitto_sub –t tokudu /+
注意,此处之所以要使用tokudu,可以看index.php的182行 var target = ‘tokudu/’ + $(‘#messageTarget’).val();
在mosquitto的终端获得mosquitto_sub客户端的id
1350006978: New client connected from 127.0.0.1 as mosqsub/8491-localhost..
访问http://host:port/ ,push notification target字段填写8491-localhost,push notification text填写需要推送的测试消息
在mosquitto的终端查看是否收到了推送的消息,如果收到,说明phpmqttclient已经安装配置成功
解决mosquitto占有cpu进程过高的问题 https://answers.launchpad.net/mosquitto/+question/189612
ulimit -u 4096
ulimit -n 4096
附:
配置文件
# =================================================================
# General configuration
# =================================================================
# 客户端心跳的间隔时间
#retry_interval 20
# 系统状态的刷新时间
#sys_interval 10
# 系统资源的回收时间,0表示尽快处理
#store_clean_interval 10
# 服务进程的PID
#pid_file /var/run/mosquitto.pid
# 服务进程的系统用户
#user mosquitto
# 客户端心跳消息的最大并发数
#max_inflight_messages 10
# 客户端心跳消息缓存队列
#max_queued_messages 100
# 用于设置客户端长连接的过期时间,默认永不过期
#persistent_client_expiration
# =================================================================
# Default listener
# =================================================================
# 服务绑定的IP地址
#bind_address
# 服务绑定的端口号
#port 1883
# 允许的最大连接数,-1表示没有限制
#max_connections -1
# cafile:CA证书文件
# capath:CA证书目录
# certfile:PEM证书文件
# keyfile:PEM密钥文件
#cafile
#capath
#certfile
#keyfile
# 必须提供证书以保证数据安全性
#require_certificate false
# 若require_certificate值为true,use_identity_as_username也必须为true
#use_identity_as_username false
# 启用PSK(Pre-shared-key)支持
#psk_hint
# SSL/TSL加密算法,可以使用“openssl ciphers”命令获取
# as the output of that command.
#ciphers
# =================================================================
# Persistence
# =================================================================
# 消息自动保存的间隔时间
#autosave_interval 1800
# 消息自动保存功能的开关
#autosave_on_changes false
# 持久化功能的开关
persistence true
# 持久化DB文件
#persistence_file mosquitto.db
# 持久化DB文件目录
#persistence_location /var/lib/mosquitto/
# =================================================================
# Logging
# =================================================================
# 4种日志模式:stdout、stderr、syslog、topic
# none 则表示不记日志,此配置可以提升些许性能
log_dest none
# 选择日志的级别(可设置多项)
#log_type error
#log_type warning
#log_type notice
#log_type information
# 是否记录客户端连接信息
#connection_messages true
# 是否记录日志时间
#log_timestamp true
# =================================================================
# Security
# =================================================================
# 客户端ID的前缀限制,可用于保证安全性
#clientid_prefixes
# 允许匿名用户
#allow_anonymous true
# 用户/密码文件,默认格式:username:password
#password_file
# PSK格式密码文件,默认格式:identity:key
#psk_file
# pattern write sensor/%u/data
# ACL权限配置,常用语法如下:
# 用户限制:user <username>
# 话题限制:topic [read|write] <topic>
# 正则限制:pattern write sensor/%u/data
#acl_file
# =================================================================
# Bridges
# =================================================================
# 允许服务之间使用“桥接”模式(可用于分布式部署)
#connection <name>
#address <host>[:<port>]
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]
# 设置桥接的客户端ID
#clientid
# 桥接断开时,是否清除远程服务器中的消息
#cleansession false
# 是否发布桥接的状态信息
#notifications true
# 设置桥接模式下,消息将会发布到的话题地址
# $SYS/broker/connection/<clientid>/state
#notification_topic
# 设置桥接的keepalive数值
#keepalive_interval 60
# 桥接模式,目前有三种:automatic、lazy、once
#start_type automatic
# 桥接模式automatic的超时时间
#restart_timeout 30
# 桥接模式lazy的超时时间
#idle_timeout 60
# 桥接客户端的用户名
#username
# 桥接客户端的密码
#password
# bridge_cafile:桥接客户端的CA证书文件
# bridge_capath:桥接客户端的CA证书目录
# bridge_certfile:桥接客户端的PEM证书文件
# bridge_keyfile:桥接客户端的PEM密钥文件
#bridge_cafile
#bridge_capath
#bridge_certfile
#bridge_keyfile
# 自己的配置可以放到以下目录中
include_dir /etc/mosquitto/conf.d
本文出自 “Cooke Chen 我爱小贝” 博客,请务必保留此出处http://cswei.blog.51cto.com/3443978/1225617
posted @
2013-12-12 21:54 hellxoul 阅读(8957) |
评论 (0) |
编辑 收藏