<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>涂0实验室</title>
	<atom:link href="http://www.sulong.info/feed" rel="self" type="application/rss+xml" />
	<link>http://www.sulong.info</link>
	<description>一个程序员的成长之路</description>
	<lastBuildDate>Sat, 27 Feb 2010 13:42:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Java EE 6 之 Servlet 3.0</title>
		<link>http://www.sulong.info/archives/341</link>
		<comments>http://www.sulong.info/archives/341#comments</comments>
		<pubDate>Sat, 27 Feb 2010 13:42:20 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[java EE]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=341</guid>
		<description><![CDATA[Servlet之所以没有像之前的ejb那样被受到那么多的诟病，是因为servlet的设计确实非常好。在最新的Java EE6版本里，这么多年都没有多少重大改动的Servlet终于添加了很多新的功能。下面我们一个一个来看
1. 基于annotation的配置
自从java 5增加了annotation后，现在annotation已经广范用于各种框架，确实减少了很多的编写配置文件的工作。现在终于可以不用写web.xml，只要通过WebServlet, WebFilter, WebListener这几个annotation就可以轻易的配置Servlet, filter和listener了。而且, web.xml已经是可选的了，就算没有它，也一样运行。
2. 异步请求处理
Servlet 3.0 新添加了一个类AsyncContext，可以通过ServletRequest活得。如果调用了ServletRequest的startAsync()，那么这个请求将会被异步处理，这意味着即使当前的线程执行结束，也不会给发送会响应，而是要等到AsyncContext的complete()方法被调用。通过AsyncContext，一样可以取到ServletRequest，和ServletResponse对象，这意味着即使最初Servlet执行的线程执行结束，也一样可以取到那次请求数据和返回客户端数据。
在通常的Servlet设计中，servlet容器会为每个客户端的请求分配一个线程，如果处理请求的过程中需要等待某种很慢的资源，在访问量大的时候，可能导致servlet容器的线程池耗光，从而无法响应后续的请求。有了异步处理的servlet之后，可以将这些线程解放出来，把它们放到一个队列里等待。比起线程，普通的对象还是要占用较少资源的。
3. Web Fragments
Web容器加载的时候，会扫描WEB-INF/lib下的jar, 如果这个jar的有META-INF/web-fragment.xml，那这这个web-fragment.xml内的配置信息也会被使用。这个功能对做web框架很有用。很多web框架都是通过自定义自己的servlet, filter或listener实现的，现在，框架的开发者可以将默认的配置放到自己的jar里，使用者只要把jar丢到WEB-INF/lib/目录下就可以使用框架了，更加方便。通过web-fragment, 可以更容易的对一个war实现部署上的模块化。
4. 动态注册Web application组件
这个功能的意思是指，应用程序可以在运行时注册servlet, filter和listener。ServletContext里多了addFilter(), addServlet()等方法，来给用户调用。很奇怪的是，我只看到注册组件的，没有看到注销组件的，如果只能加不能减的话，那这一功能估计只能看作是通过xml配置的另一种方法。
5. 容器启动回调
如果WEB-INF/lib下有某个jar文件包含META-INF/services/javax.servlet.ServletContainerInitializer文件，且该文本文件内的类名所对应的类实现了javax.servlet.ServletContainerInitializer接口，那么这个类所实现的该接口方法会在容器启动时被调用。 这个接口方法是onStartup(java.util.Set]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/341/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么GET比POST安全？</title>
		<link>http://www.sulong.info/archives/339</link>
		<comments>http://www.sulong.info/archives/339#comments</comments>
		<pubDate>Wed, 24 Feb 2010 02:17:35 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[程序]]></category>
		<category><![CDATA[http]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=339</guid>
		<description><![CDATA[如果不通过SSL加密，GET和POST方法都会把数据以明文方式发送到服务器上，安全性相差无几。
说POST比GET安全，有如下几点理由：
1， GET请求的数据会被浏览器作为URL的一部分而保存
2， 服务器端的访问日志等一般都会记下URL
3， HTTP头部的referer里会记下URL里请求数据
总之一般人都认为URL里不会包含敏感数据的，所以你最好也不要把敏感数据放到URL里，这种场合自然不适合使用GET。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/339/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用hibernate映射时遇到的问题</title>
		<link>http://www.sulong.info/archives/335</link>
		<comments>http://www.sulong.info/archives/335#comments</comments>
		<pubDate>Thu, 21 Jan 2010 09:35:37 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[hibernate]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=335</guid>
		<description><![CDATA[对象和关系型数据库之间存在着根本不同, ORM（对象/关系映射）试图把对象映射到关系型数据库的表结构上，从而简化存储对象到数据库及从数据库中恢复对象的复杂性，让操作数据库就像操作对象一样简单。Hibernate估计是众多ORM框架中最成熟的了，但是在处理类的继承关系时还是会有一些问题。
延迟加载与继承
先看如下的代码, 演示这一映射关系：

@Entity
@Table&#40;name = &#34;a&#34;&#41;
@Inheritance&#40;strategy = InheritanceType.SINGLE_TABLE&#41;
@DiscriminatorColumn&#40;
		name = &#34;disc&#34;, 
		columnDefinition = &#34;varchar(4)&#34;, 
		discriminatorType = DiscriminatorType.STRING&#41;
public abstract class A &#123;
 @Id
 private int oid;
 private String name;
&#125;
&#160;
@Entity
@DiscriminatorValue&#40;&#34;b&#34;&#41;
public class B extends A &#123;
private String age;
&#125;
&#160;
@Entity
@DiscriminatorValue&#40;&#34;c&#34;&#41;
public class C extends B &#123;
private String sex;
&#125;
&#160;
@Entity
@Table&#40;name = &#34;d&#34;&#41;
public class D &#123;
  @Id
  private int oid;
  @ManyToOne&#40;fetch = FetchType.LAZY&#41;
 [...]]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/335/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>让JAXB生成序列化的类</title>
		<link>http://www.sulong.info/archives/332</link>
		<comments>http://www.sulong.info/archives/332#comments</comments>
		<pubDate>Fri, 20 Nov 2009 13:36:30 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[技巧]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jaxb]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=332</guid>
		<description><![CDATA[默认jaxb生成的类是没有序列化的，但是我们经常需要他们序列化。jaxb ri有生成序列化的类的这样的功能，但由于这不属于标准的功能，所以需要手动的开启。开启的方法是在用来生成java类的xml schema文件头添加如下内容：

&#60;annotation&#62;
	&#60;appinfo&#62;
		&#60;jaxb:globalBindings generateIsSetMethod=&#34;true&#34;&#62;
			&#60;xjc:serializable uid=&#34;1&#34;/&#62;
		&#60;/jaxb:globalBindings&#62;
	&#60;/appinfo&#62;
&#60;/annotation&#62;

另外，在使用jaxb的 xjc 编译器时，要加上 -extension 的参数。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/332/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JAXB中如何利用继承生成XML</title>
		<link>http://www.sulong.info/archives/326</link>
		<comments>http://www.sulong.info/archives/326#comments</comments>
		<pubDate>Sat, 14 Nov 2009 13:39:32 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[jaxb]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=326</guid>
		<description><![CDATA[问题
JAXB是我用过的java处理XML的方法中做方便的一个，在jaxb中如何使用类的集成关系有一个小小的需要注意的地方。看下面的两端XML。
XML 示例1：

&#60;a&#62;
    &#60;b&#62;&#60;/b&#62;
    &#60;c&#62;&#60;/c&#62;
&#60;a&#62;

XML示例2：

&#60;a&#62;
    &#60;b&#62;&#60;/b&#62;
    &#60;d&#62;&#60;/d&#62;
&#60;a&#62;

这两段XML的唯一差别就在c元素与d元素。为了生成这两个XML，有几种方案。
方案一
不利用类的继承来重用代码，写两套Java代码, 如：

@XmlRootElement&#40;name = a&#41;
public class A &#123;
    B b;
    C c:
&#125;
&#160;
@XmlRootElement&#40;name = a&#41;
public class A2 &#123;
    B b;
    D d:
&#125;
&#160;
public class B &#123;&#125;
public class D &#123;&#125;

这一方案不是我们想要的，虽然可以解决问题，但是不能重用两个XML中共有的结构。
方案二
利用一个父类表示两个XML之间的共同的结构，用两个子类扩展这个父类，分别添加 [...]]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/326/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>可恶的乱码问题</title>
		<link>http://www.sulong.info/archives/324</link>
		<comments>http://www.sulong.info/archives/324#comments</comments>
		<pubDate>Thu, 12 Nov 2009 14:41:40 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[技巧]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[乱码]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=324</guid>
		<description><![CDATA[在打印单据的时候，有两个汉字“玥”和“芃”，始终显示为“？”，这一问题困扰了业务人员一段时间了。以前没有空，就没有投入精力去查原因，上次得了空，终于把这个问题解决掉了。
这个乱码的汉字从哪里来的呢？首先是业务人员通过一个遗留的PHP应用，输入到一个mysql 4数据库中，然后我们的java程序从这个mysql 4中读取，再写入到新的mysql5的数据库中，最后通过java程序生成html在用户的浏览器里显示，结果就看到了这两个汉字乱码。那么这个问题如何解决呢？
只有两个汉字乱码，而不是所有的汉字都乱码，所以我们的程序一定使用了一种包含汉字较少的字符集，而这个出错的汉字恰好不在此字符集中，否则，就应当是大部分汉字乱码，而不仅仅是这两个了。很自然的就让人想到了 gb2312, gbk, gb18030, utf8等字符集之间的关系。其中gb2312中只有六千多个汉字，其它几个字符集支持的汉字数相差不多，我们程序一定是在该使用gbk, gb18030或utf8的地方使用了含有汉字较少的gb2312。
经查阅相关文档，果然发现那两个汉字都不在gb2312里，而在gbk, utf8字符集里。我们的mysql5使用的utf8字符集，生成的html也是utf8编码，如果mysql5中的汉字是正确的话，那么就应该能正常显示，因此，数据进入mysql5的时候就应该出错了。java程序在连接mysql5的时候，在jdbc连接中设置了utf8，所以如果从mysql4数据库中读取出来的是正确的，就不应该写入出问题，因此数据在mysql4中可能就错了，也可能是从mysql4中读取的时候出错了。php的兄弟们说mysql的数据库是gb2312字符集的，mysql的配置文件里也是这么配置的。如果果真如此，那么这个两个汉字在mysql4的数据库中就应该不正常了，所有的程序读出之后都应该是乱码，可是php的录入程序那边确实是能正常显示的。我断定这个数据库里放的实际上是gbk字符集的汉字。选用和mysql4相对应的mysql j connector 3.14，并在jdbc连接url里设置了characterEncoding=gbk，读出来的仍旧不正确！查阅了mysql j connector的文档，原来3 版本的mysql connector根本就不支持characterEncoding这个选项。看来只能修改mysql的配置文件了。修改之后，果然这两个汉字可以正常显示了。
如果计算机是中国人发明的，那么计算机也许一开始就得支持汉字，就再也没有乱码的问题。如果世界上只有一种汉字的编码方案，也不会有乱码的问题，可惜汉字偏偏有很多中编码方案。所以在我们的程序中，一定得搞清楚，我们的汉字数据来自于哪里，使用的哪种编码，每个环节都得配置得当，否则就会有乱码问题。
对于一般的web应用来说，需要关心编码的地方有：
1，数据库以什么编码存储数据
2，程序使用什么字符集连接数据库
3，程序内部运行时使用什么字符集
4，程序源码使用什么字符集
5，生成的html文件是什么字符集
6，程序告知浏览器的字符集
如果以上这些地方的字符集有配置不正确的地方，往往就会乱码。
如果可以的话，最好在所有的地方都使用一种编码，比如对于java应用来说，在所有的地方都使用utf8编码，就可以解决问题。需要注意的是，在windows环境下，默认的文件编码是gb18030的，而不是utf8。
另外，极端鄙视故意使用生僻字火星文的脑残族！！
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/324/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>漫谈PHP和Java</title>
		<link>http://www.sulong.info/archives/321</link>
		<comments>http://www.sulong.info/archives/321#comments</comments>
		<pubDate>Sat, 26 Sep 2009 16:31:51 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[程序]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=321</guid>
		<description><![CDATA[我为公司内部交流而写的PPT，谈论PHP和JAVA相关的话题。在这里查看：
漫谈PHP和Java

]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/321/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>GroovyServlet的缺陷</title>
		<link>http://www.sulong.info/archives/319</link>
		<comments>http://www.sulong.info/archives/319#comments</comments>
		<pubDate>Fri, 07 Aug 2009 06:56:32 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=319</guid>
		<description><![CDATA[原本希望groovy能以php那种方式工作，但是现在看来不太可能。Groovy发行包里自带的TemplateServlet太弱，GroovyServlet也有致命的缺陷。
GroovyServlet使用GroovyScriptEngine(后面简称GSE)解析groovy文件，解析过程中GSE会智能的自动的到类路径中寻找被引用到的groovy类文件。如果被用作groovyServlet的文件被更新了，GSE会重新解析它，不需要重启服务器，就可以看到效果。可惜的是，如果被引用到的类路径中的其它的文件被更新了，GSE还在使用原来的文件，必须重启服务器才能看到效果，这是在是太令人失望了。据说groovy 1.7 里GSE会这方面增强，很期待呀。TemplateServlet干脆就连GSE也没有用，所以自动引用其他的groovy文件也不可能了。无论是GroovyServlet还是TemplateServlet都不能够像php那样通过include别的php文件来获得别的文件里定义的类，方法和闭包。
看开，在目前，如果不用grails，是没有什么好办法直接用groovy文件写网络程序的，只好把它编译成class文件，就像java生成的class一样来使用。很可气的是，我试用了几个IDE，eclipse, netbeans和idea，其中只有idea支持得还可以，但都是不算很好。看来groovy还有一段路要走。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/319/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web服务器集群</title>
		<link>http://www.sulong.info/archives/312</link>
		<comments>http://www.sulong.info/archives/312#comments</comments>
		<pubDate>Mon, 03 Aug 2009 06:34:04 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[理论]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=312</guid>
		<description><![CDATA[什么是集群
计算机集群（以下简称集群）在维基百科上被定义为一组相互连接的计算机，紧密的工作在一起，以至于在很多方面看来，它们都像是一台机器。
集群的好处
集群可能能给我们带来很多好处，其中负载均衡(loadbalance)和故障恢复(failover)一般是最常用的。负载均衡是将系统的负载分派到集群内不同的计算机上，让每个节点都不至于太忙或太闲，通过增加集群中计算机的数量，可以提升整体的负载能力。故障恢复是指在集群中某个节点发生故障时，其它的节点代替它们继续工作，这样整个系统依旧能对外提供服务。
web服务器集群的特点
对于web服务器来说，集群就是让一组计算机对外像一台web服务器一样运行。web服务器的特点是它通过http协议与客户端交互，而http协议的工作机制是请求响应模式的。web服务器的集群要能把客户端的http请求发送到集群内各个节点上，实现loadbalance，并能探测到各节点的工作情况，在某个节点失效的时候，不再把http请求发送到该节点上。
有状态与无状态
web程序本身是否有状态对实现集群的方法和难以度有很大的影响。如果web程序和客户端交互的记录下了一些状态信息，并在处理之后的请求时需要知道这样的信息，那么这个程序就是有状态的。比如，登录功能，当用户正确登录后，web程序会记录下用户的登录状态，当用户访问其它的页面时，web程序会参照用户的登录信息做不同的处理。在实现集群的时候，有状态的程序要复杂些，因为必须保证处理请求的节点上能有该用户的状态信息。对于无状态的程序，则没有这个问题，请求被分发到任何节点都是一样的，没有额外的维护状态的工作。
为了保证处理请求的节点上能有状态信息，要么在多个节点上复制程序的状态，要么采用否种策略保证将请求正确的发送到具有相应状态的节点上。如上面的例子，要么把用户登录的信息复制到集群的所有节点上，以保证无论之后请求发送到哪个节点上，都能够找得到登录信息，要么每次都把这个用户的请求发送到同一个节点上，就像mod_jk的sticky_session那样。
多线程与多进程
php,ruby,python等脚本语言往往采用无状态的结构，而java往往采用有状态的结构。并非语言决定了它们的工作方式，更多的是一种习惯。
java web服务在运行时是一个常驻内存的进程，用不同的线程处理用户请求。当处理一个http请求的线程结束后，保留在该进程内的信息并没有消失，因为进程还在。因此，可以很方便的把一些交互信息放到java进程的内存中，在多个线程间共享。在加上又有好用的HttpSession类，这样在java ee里把用户信息保存到session中，是一件非常容易的事，程序员们也自然的就采用的，导致了java web程序成了有状态的。如果完全不用session等，java web程序也能做到无状态。
和java的单进程，多线程工作方式不同，php等脚本语言采用了多进程的工作方式。当有一个http请求到来时，web服务器开启一个新的进程，这个进程调用脚本语言的解释器来运行脚本处理请求，处理结束后进程退出。如果要在多个进程间共享信息，就得采用外部的介质，DB就成了最好的选择。
本质上来说，只要需要记录会话的状态，就肯定有状态，差别只是把状态放到什么地方。java ee里往往把它放到应用程序的内存里，而php等则往往放到db里。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/312/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>groovy+spring全动态web开发方案</title>
		<link>http://www.sulong.info/archives/303</link>
		<comments>http://www.sulong.info/archives/303#comments</comments>
		<pubDate>Tue, 14 Jul 2009 05:02:07 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=303</guid>
		<description><![CDATA[ 为什么java开发没有php容易？，我在那篇文章了提出了三点原因，利用groovy，我们能在一定程度上做到那三点，从而加快了java web的开发。jsp本身以具有不需要重启就可以生效的能力，但是没有好用的map和动态类型的能力，用在前文  用groovyServlet和TemplateServlet快速开发网页中的方法，可以通过groovy让页面具有好用的map和动态类型的能力，但是 TemplateServlet的局限性 还是很难让我们单凭在页面里编程来构建规模稍大些的应用。引入spring，利用spring对动态语言的支持，我们可以将可重用的逻辑封装到由groovy编写的spring的bean里，这样，就可以最终实现从页面到后台全groovy的效果了，让java的web开发可以达到近似于php的易用度。
看看详细的做法。
把最新版的groovy-all.jar和spring.jar以及spring所依赖的相关包放到/WEB-INF/lib/目录下。
首先，在web.xml里配置好对groovyServlet, TemplateServlet和spring的支持
代码如下：

  &#60;context-param&#62;
    &#60;param-name&#62;contextConfigLocation&#60;/param-name&#62;
    &#60;param-value&#62;/WEB-INF/applicationContext.xml&#60;/param-value&#62;
  &#60;/context-param&#62;
&#160;
  &#60;listener&#62;
    &#60;listener-class&#62;org.springframework.web.context.ContextLoaderListener&#60;/listener-class&#62;
  &#60;/listener&#62;
&#160;
  &#60;servlet&#62;
    &#60;servlet-name&#62;groovlet&#60;/servlet-name&#62;
    &#60;servlet-class&#62;groovy.servlet.GroovyServlet&#60;/servlet-class&#62;
  &#60;/servlet&#62;
&#160;
  &#60;servlet&#62;
    &#60;servlet-name&#62;gsp&#60;/servlet-name&#62;
    &#60;servlet-class&#62;groovy.servlet.TemplateServlet&#60;/servlet-class&#62;
  &#60;/servlet&#62;
&#160;
  &#60;servlet-mapping&#62;
  [...]]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/303/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TemplateServlet的局限性</title>
		<link>http://www.sulong.info/archives/299</link>
		<comments>http://www.sulong.info/archives/299#comments</comments>
		<pubDate>Fri, 10 Jul 2009 09:38:09 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=299</guid>
		<description><![CDATA[我想利用TemplateServlet，像使用php那样使用groovy。只要设置好了，就可以在web目录下写gsp文件，就像写php那样，即时写即时看到效果。
但是我错了，目前的TemplateServlet非常简陋，远不能达到要求。问题主要发生在include功能。php的inclue require等功能，可以把页面变成方法库，或类库，但是在TemplateServlet的gsp里不行。我无法访问被包含的页面里的方法，闭包等。想想也很自然，每个gsp文件都有自己的名称空间。
另外，不能在gsp里定义类，这个太伤了～～～
如果能解决以上两个问题，TemplateServlet就可以让groovy像php那样使用了。唉，那些做grails的家伙真的应该先把这块搞好，再搞重量级的东西，毕竟不是所有人都想用spring　hibernate的。
看了看gails的roadmap，今年9月的1.2版本里将有standalone gsp module，那是真正的gsp，而不是现在的简单的TemplateServlet。Grails里的gsp支持页面片段和非常方便的自定义标签，前者便于共享页面展示，后者便于共享页面行为，那么处理页面的是什么呢？还要写controller吗？到时候看吧，还是很令人期待的。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/299/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>groovy及其TemplateServlet的编码问题</title>
		<link>http://www.sulong.info/archives/277</link>
		<comments>http://www.sulong.info/archives/277#comments</comments>
		<pubDate>Thu, 09 Jul 2009 02:09:47 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[技巧]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=277</guid>
		<description><![CDATA[上一篇文章里快速上手使用groovy来写页面了，如果在页面里使用中文的话，可能会遇到中文问题。在1.6.3版本的groovy里，可以设置两个属性来解决：

groovy.source.encoding=UTF-8
file.encoding=UTF-8

groovy在解释脚本时，默认会使用一个叫做groovy.source.encoding的系统属性的值来作为源码的编码，如果这也没有设置的话，就会使用file.encoding这个系统属性，也就是操作系统的默认字符集了。然而TemplateServlet很傻，它只认file.encoding，所以要两个属性都设置上，才能解决问题。而file.encoding属性是在整个jvm下都有效的，可能会带来其他的问题。下个版本中groovy会修正这个问题。如果你等不及了，你可以像我这样，hack一下TemplateServlet，把getTemplate()方法的一段代码改为：

//
// Template not cached or the source file changed - compile new
// template!
//
if &#40;template == null&#41; &#123;
    if &#40;verbose&#41; &#123;
        log&#40;&#34;Creating new template from file &#34; + file + &#34;...&#34;&#41;;
    &#125;
&#160;
    String fileEncoding = System.getProperty&#40;&#34;groovy.source.encoding&#34;&#41;;
&#160;
    Reader [...]]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/277/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>用groovyServlet和TemplateServlet快速开发网页</title>
		<link>http://www.sulong.info/archives/280</link>
		<comments>http://www.sulong.info/archives/280#comments</comments>
		<pubDate>Wed, 08 Jul 2009 07:43:24 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[技巧]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=280</guid>
		<description><![CDATA[Groovy是专门为java设计的脚本语言，可以和java无缝的结合，为java带来了脚本语言的能力。作为一个脚本语言，groovy有丰富的特性，比如动态类型，闭包等。如果能掌握groovy，并用其来开发，可以大大提高java程序员的生产力。Grails是用groovy写的一个类似于rails的web框架，实际上就是spring+hibernate+groovy。我想用groovy来写写页面，但是又不想用grails这种笨重的东西，正好groovy自带的了两个类可以完成这个任务，就是groovy.servlet包下的 GroovyServlet 和 TemplateServlet类。
下载安装好groovy后，在安装目录的embeddabe目录下复制groovy-all-1.6.3.jar到war/WEB-INF/lib/下。然后，在web.xml里添加如下代码：

  &#60;servlet&#62;
    &#60;servlet-name&#62;groovlet&#60;/servlet-name&#62;
    &#60;servlet-class&#62;groovy.servlet.GroovyServlet&#60;/servlet-class&#62;
  &#60;/servlet&#62;
&#160;
  &#60;servlet&#62;
    &#60;servlet-name&#62;gsp&#60;/servlet-name&#62;
    &#60;servlet-class&#62;com.liba.link.groovy.MyTemplateServlet&#60;/servlet-class&#62;
  &#60;/servlet&#62;
&#160;
  &#60;servlet-mapping&#62;
    &#60;servlet-name&#62;groovlet&#60;/servlet-name&#62;
    &#60;url-pattern&#62;*.groovy&#60;/url-pattern&#62;
  &#60;/servlet-mapping&#62;  
&#160;
  &#60;servlet-mapping&#62;
    &#60;servlet-name&#62;gsp&#60;/servlet-name&#62;
    &#60;url-pattern&#62;*.gsp&#60;/url-pattern&#62;
  &#60;/servlet-mapping&#62;

这样，就可以在web目录下用groovy写以.groovy或.gsp结尾的页面代码了。GroovyServlet就是一个普通的servlet，只不过，它会编译执行指定url对应的.groovy文件，来产生html。这和直接用groovy写servlet的区别是，GroovyServlet为你做了一些特殊变量的绑定，在.groovy里可以通过request, out, [...]]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/280/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IO和性能</title>
		<link>http://www.sulong.info/archives/232</link>
		<comments>http://www.sulong.info/archives/232#comments</comments>
		<pubDate>Fri, 03 Jul 2009 08:16:03 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[理论]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[IO]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=232</guid>
		<description><![CDATA[最近几天看了几家互联网公司的和架构有关的PPT，有支付宝，linkedin，douban等。这些公司所使用的具体的技术有差别，但是为了能做到支持大规模访问，他们都在与缓慢的IO做斗争！ 比如说豆瓣网的历次架构变迁，不是因为磁盘IO成为瓶颈，就是因为网络IO成为瓶颈。如果能把IO的问题解决掉，那么对于互联网企业来说，性能问题就解决掉一半了，我想。
与飞速的CPU和内存相比，磁盘和网络的IO慢如蜗牛，这是问题的根源。如果没有大规模廉价而又足够快的存储方案出现的话，这个问题还将继续下去。我们只能期待这一革命性的技术出现来从根本上解决这一问题吧！
那对于现在的我们该怎么办呢？大家的想法可能都是一样的，一是加快IO速度，二是避免不必要的IO。豆瓣曾经通过购买更高性能的硬盘来解决这个问题，如果想要更好的效果，需要投入更多的资金来购买整套的高性能存储方案，但是这成本太高了，很多公司后来都会放弃。于是大部分公司都会极力采用后者，就是避免不必要的IO，缓存就是用来做这样的事的。
将低速介质上的数据放到高速介质上，访问者先访问高速介质，在找不到需要数据时才访问低速介质，以此来提升访问数据的速度，这样的技术就是缓存了。设在一段时间内有m次没有命中缓存，n次命中，而访问一次缓存的时间是t1， 访问慢速介质的时间是t2，那么为了是缓存有效就得满足不等式： m * (t1 + t2) + n * t1 < (m + n) * t2， 于是有 m / n < t2 / t1 -1 。由此可见，在介质的速度比一定的情况下，命中比率要高于一定的值，缓存才有效果。提高命中比率，就是要把那些最常用的数据放到缓存里。另一方面，缓存里数据如果被修改了，就要同步到低速存储介质中，同样的，如果低速存储介质的数据被修改了，也要同步到缓存里。如果加上同步的开销，就需要更高的命中率。提高命中率和保证数据的同步，是使用缓存的两个艰巨的任务。
豆瓣网使用memcache，还使用专门的nigix服务器来提供图片的服务，其实也是cache。linkedin则使用了数十台大内存的服务器作为缓存服务器，运行着用c++写的专门的缓存程序。可见这些网站在使用缓存方面都是不遗余力呀。如果能把缓存用好，那么就把一大半的IO问题解决掉了。
IO往往会成为程序的瓶颈，因此，程序员应当时刻的注意，你写的代码是否在进行IO操作，是否可以减少IO操作，等等。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/232/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>DRY, Don&#8217;t Repeat Yourself!</title>
		<link>http://www.sulong.info/archives/231</link>
		<comments>http://www.sulong.info/archives/231#comments</comments>
		<pubDate>Wed, 01 Jul 2009 08:59:34 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[理论]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=231</guid>
		<description><![CDATA[DRY，就是不要写重复的代码，这也是程序设计的一个黄金准则之一。
1 引申自关注点分离
其实这一条准则，也是从关注点分离引申而来的。如果完成相同或相似功能的代码片段，在一个程序的很多地方出现，那么无疑会使包含它的代码多了一个关注点。把相同或相似的代码抽象出来，放在一个地方，这样就可以使调用者减少一个关注点，同时将所有的对同类问题的关注合并到一个地方。比如说，判断一个用户是否登录，这一功能被很多地方使用，如果把这一功能包装成函数放到一个地方，需要使用的地方只要引用一下函数就可以了，这样引用者就不用关心如何判断一个用户是否登录了。
2 好处
2.1 提高效率
同样的功能，完成一次就可以了，如果每次要使用轮子的时候，都重复发明轮子，那是对人类智慧的浪费。如果发明一个万用轮子不容易，那么发明一个够用的可以反复使用的轮子就可以了。
2.2 更易读
如过你打开一个程序的源代码，发现有大量类似又稍有差别的代码，你还有多少心情读下去吗？要读下去的话，你就得像diff工具一样去比较类似代码间的细微差别，还要揣摩它的含义。这样的代码读起来太痛苦了。因此，如果没有重复的代码，就没有这份痛苦。
2.3 更易维护
如果你用类似的算法，重复写了很多的程序，结果却发现这个算法有个错误，那你不得不小心翼翼的找到所有的这样的程序，并一个一个又一个的修正。那是一个多么无聊的工作呀。如果漏掉了，或者将其中的某些一不小心修改错了，还得回头再重新修改，那台痛苦了！所以充斥着copy&#038;paste的代码，是维护者的噩梦。
3 怎么做
程序语言和编程方法的进步，也就是人们在实践DRY的过程。要做到DRY，就是要不断的通过抽象，把重复的功能抽象并包装起来。我们先是有了函数和子程序，后来有了类和方法，等等。我知道，为了DRY，还会有新的工具和方法论被发明。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/231/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>企业应用与游戏开发的差别</title>
		<link>http://www.sulong.info/archives/234</link>
		<comments>http://www.sulong.info/archives/234#comments</comments>
		<pubDate>Wed, 01 Jul 2009 06:24:47 +0000</pubDate>
		<dc:creator>wuwei</dc:creator>
				<category><![CDATA[程序]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[思考]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=234</guid>
		<description><![CDATA[两个领域完全不一样,包括关注点,技术,运营等..我总结了一下:
1. 企业应用有很多功能属于增删改查的类型.有的是单表操作,有的是多表的JOIN,有的可能需要些逻辑判断,但大致的基本思路是这样,一个企业应用大约逃离不出这些结构.游戏不同.没有增删改查,没有任何的模式套路!做企业应用的思路和做游戏的思路完全不同.我们部门曾经单独为游戏的后台做了机器人脚本,能自动创建对游戏的表的管理功能,而游戏的后台管理功能大体与企业应用类似,这样想来可能企业应用还是有套路可循的.
2.二者的关注点不同.企业应用关注的是功能能否实现,模块,代码写的是否秀雅,当然游戏的开发也肯定关注这个,但游戏更要关注:性能,画面和可玩性&#8230;性能包括游戏的响应速度,能否支撑玩家的巨大的并发量 等.画面也非常重要,一个好的游戏能让人有赏心悦目的感觉.同样可玩性也要挖掘出来.要让玩家玩的爽,有能从中盈利,难度比较高呢&#8230;
3.代码编写的方式不同.企业应用的思路大多可以想到.比如页面列表显示,无法是取数据,然后转换成一个VIEW在页面上显示出来.而游戏呢,逻辑性之复杂令人瞠目.这里不多说了.可能一个简单的功能,需要上千行代码&#8230;还有一系列的算法等等,同时还要考虑到编写代码后游戏的运行速度和性能&#8230;
4.做企业应用很多人习惯用模型的方式设计数据库,比如一个表代码一个对象等.这样会产生可能一个查询有涉及到5张表之多.游戏呢?一个月就会有50万条记录,如何JOIN?JOIN一次要让你必须在1秒内响应,并且线上还有1000个玩家在玩,你能行吗?不行!尽量少JOIN表,这是提高数据库效率的一个非常好的方法.
5.多用缓存.不多说了,优势是:1减少访问数据库的时间和数据库的压力 2.提高请求响应速度.等等&#8230;
还有很多&#8230;呵呵
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/234/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>以字符串为key访问key为整数的数组</title>
		<link>http://www.sulong.info/archives/220</link>
		<comments>http://www.sulong.info/archives/220#comments</comments>
		<pubDate>Mon, 29 Jun 2009 09:19:24 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[程序]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[技巧]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=220</guid>
		<description><![CDATA[题目比较拗口，不多说了，看了程序就明白了：

&#60;?php
$b = array&#40;0=&#62;'bbb'&#41;;
echo $b&#91;'0'&#93;;
&#160;
$v = array&#40;0=&#62;'bbb', '0'=&#62;'ccc'&#41;;
echo $v&#91;'0'&#93;;
?&#62;

程序输出bbbccc。当数组里没有字符串的&#8217;0&#8242;，有0时，php自动把作为key的&#8217;0&#8242;转变成了0。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/220/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>浅谈TOMCAT集群</title>
		<link>http://www.sulong.info/archives/216</link>
		<comments>http://www.sulong.info/archives/216#comments</comments>
		<pubDate>Sat, 27 Jun 2009 05:26:57 +0000</pubDate>
		<dc:creator>wuwei</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[思考]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=216</guid>
		<description><![CDATA[老实说，一开始我也认为没这个必要，因为加大JVM内存就就可以了嘛，干啥要集群很多TOMCAT呢？其实不是这样的。
首先TOMCAT集群需要APACHE和TOCMAT组合在一起。APACHE作为服务端的访问入口，自动地根据TOMCAT的并发数量分配到不同的TOMCAT里。二者缺一不可。并且配置是比较麻烦的。
很多人没用到集群是因为并发数还没达到一定的程度。一般企业应用最多也就50个并发，架一个TOCMAT，内存开大点就够了。但游戏就不一样了，动不动就几百甚至1000多的并发量，一个TOMCAT吃得消吗？吃不消！通过我们的实践证明，一个TOMCAT最多支撑起150个并发数，有次我们将其开发200个，结果到了170左右TOMCAT立马崩溃。所以后来为了支撑起1000都个并发量，我们架了9个TOMCAT集群。150*9=1350，基本能满足最大的用户访问量了。
有人说还不够，加大TOMCAT的内存嘛！这么并发量不就更大了？非也！我们通过实践证明，一个TOMCAT内存到了1G以上，就起不了多大的效果了，也就是说，1G内存的TOMCAT和2G内存的TOMCAT，基本性能是一样的！哈哈
还有一点，TOMCAT是免费的哦！不花钱还能架起这么大的一个应用，够省了吧？呵呵
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/216/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>个人对开发WEB游戏的总结</title>
		<link>http://www.sulong.info/archives/211</link>
		<comments>http://www.sulong.info/archives/211#comments</comments>
		<pubDate>Wed, 24 Jun 2009 09:38:59 +0000</pubDate>
		<dc:creator>wuwei</dc:creator>
				<category><![CDATA[程序]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=211</guid>
		<description><![CDATA[很多人以为WEB游戏的样子就类似开心网,很简单,主要是大家互动.但其实不是这样的.
开心网的WEB游戏比如种菜,大家觉得画面很精美,其实主要是前段采用了FLASH作为页面的展示,而FLASH有优势也有劣势.画面精良,与服务端数据通讯少(只需要提供必要的数据就可以了)是他的强项.当然他也有很大的缺陷,那就是第一次加载SWF文件很慢.不过因为开心网的这个SWF游戏本身比较小,所以并不能体现出他的劣势,这可能只有开心网这个平台才可以这么做,而很多网页游戏(FALSH版本)光下载SWF(第一次)就需要几M的容量,加上后续还需要下载地图&#8230;这不得不感叹有客户端游戏的极大优势啊&#8230;
我们的游戏没有采用FALSH方式,当然也有团队对FLASH的SOCKET通讯方式不熟悉,也有FALSH下载量太大导致服务器流量与并发量吃紧有关.我们采用的是javascript.用了很多扩展包,比如propotype,dwr(ajax),以及JS的特效包.页面采用的是WEB2.0(CSS+DIV)方式.其实效果也是很好的.这里不得不说一下DWR了.速度快,只刷新局部页面是他的最大优势.普通的WEB请求需要请求图片,js,html等等,花费的请求时间与数据下载量巨大.一个JS小的到50毫秒,大的到500毫秒不等.而不起眼的小图片,竟然也会吞噬你20毫秒的时间,而这些请求一累计,请求时间花费无数&#8230;这个时候DWR就发挥出他的威力了,他只有一个请求(只有一个!)在这个游戏里最大的数据库消耗功能(排名统计)也仅仅用了800毫秒,而这个功能竟然包括了数据库的一张表(几万数据量)的 1select,2count,3where 等3次查询,性能之高可想而知.
这里大家可以看出来,WEB游戏除了画面之外,重要的是什么?性能.基本上我们游戏5万个会员,在线人数保持在500人左右(并发量).这可不同于普通网站的在线人数哦.因为普通网站一般访问一下要过好久然后再次请求,没有狂刷页面的.而游戏是实时互动的.一个用户可能一秒就要来一个请求,服务器的压力之大可想而知&#8230;有人说,加大服务器配置嘛,这句有点偏颇.其实是,要先从软件的角度优化性能.比如不必要的数据库查询(大约占性能的30%),比需要的网络请求下载(30%),数据的缓存(20%)以及其他的一些优化.需要综合&#8230;这样的结果就是,我们用3台服务器(1个MYSQL,2台应用)撑起了整个游戏环境(应用服务器还是TOMCAT集群的哦!)
开服只1个月,数据库量大到什么程度?一张表竟然有100万条记录了&#8230;这时候怎么办呢?目前比较好的想法是用年月的方式作为表的名称,但这个就与hibernate的动态映射有关了,网上搜了一下有这个技术,但目前还没用.只能用定时删除历史的方式来实现了..呵呵
做游戏,重要的是你要时刻考虑:性能,游戏的效率,游戏的可玩性.如果你觉得这个功能好玩,就要吧他做到最好,既好玩,又速度快,又要让玩家有刺激感&#8230;很复杂啊..
第一部分先写到这里吧,能写的太多了,这里只是一小部分.呵呵
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/211/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ActiveMQ使用经验</title>
		<link>http://www.sulong.info/archives/207</link>
		<comments>http://www.sulong.info/archives/207#comments</comments>
		<pubDate>Thu, 18 Jun 2009 09:56:41 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[jms]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=207</guid>
		<description><![CDATA[ActiveMQ是apache的一个开源JMS服务器，不仅具备标准JMS的功能，还有很多额外的功能。公司里引入ActiveMQ后，ActiveMQ成里我们公司业务系统中最重要的一个环节。所有应用都通过jms集成，如果ActiveMQ出了故障，整个系统就瘫痪了。因此，头对ActiveMQ的性能，可靠性，以及如何正确使用，是非常的关心的，而我就被指派来做关于ActiveMQ的调研，本文对此做了些总结。
1 使用jms需要注意的问题
一下所述的问题，不仅是对ActiveMQ，对于其他的JMS也一样有效。
1.1 不要频繁的建立和关闭连接
JMS使用长连接方式，一个程序，只要和JMS服务器保持一个连接就可以了，不要频繁的建立和关闭连接。频繁的建立和关闭连接，对程序的性能影响还是很大的。这一点和jdbc还是不太一样的。
1.2 Connection的start()和stop()方法代价很高
JMS的Connection的start()和stop()方法代价很高，不能经常调用。我们试用的时候，写了个jms的connection pool，每次将connection取出pool时调用start()方法，归还时调用stop()方法，然而后来用jprofiler发现，一般的cpu时间都耗在了这两个方法上。
1.3 start()后才能收消息
Connection的start()方法调用后，才能收到jms消息。如果不调用这个方法，能发出消息，但是一直收不到消息。不知道其它的jms服务器也是这样。
1.4 显示关闭Session
如果忘记了最后关闭Connection或Session对象，都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了Connection，由这个Connection生成的Session也会被自动关闭，结果并非如此，Session并没有关闭，导致内存泄漏。所以一定要显示的关闭Connection和Session。
1.5 对Session做对象池
对Session做对象池，而不是Connection。Session也是昂贵的对象，每次使用都新建和关闭，代价也非常高。而且后来我们发现，原来Connection是线程安全的，而Session不是，所以后来改成了对Session做对象池，而只保留一个Connection。
2 集群
ActiveMQ有强大而灵活的集群功能，但是使用起来还是会有很多陷阱。
2.1 broker cluster和 master-slave
ActiveMQ可以做broker的集群，也可以做master-slave方式的集群。前者能在多个broker之前fail-over和load-balance，但是在某个节点出故障时，可能导致消息丢失；而后者能实时备份消息，和fail-over，但是不能load-balance。broker cluser的方式，在一个broker上发送的消息可以在其它的broker上收到。当一个broker失效时，客户端可以自动的转到别的broker上运行，多个broker可以同时提供服务，但是消息只存储在一个broker上，如果那个broker失效了，那么客户端直到它重新启动后才能收到该broker上的消息，假如很不幸，那个broker的存储介质坏了，那么消息就丢失掉了。
Master-slave方式中，只有master提供服务，slave只是实时的备份master的数据，所以消息不会丢失。当master失效时，slave会自动升为master，客户端会自动转到slave上工作，所以能fail-over。由于只有master提供服务，所以不能将负载分到多个broker上。
其实单个broker的性能已经是相当的惊人了，在我们公司的机器上能达到每秒收发4000个消息，没个消息4K字节这样的速度，足够公司目前的需要了，而公司并不希望丢失任何数据，所以我们选择使用master-slave模式。
2.2 多种master-slave模式
master-slave也有多种实现方式。它们的不同只是在共享数据和锁机制上。
2.2.1 Pure master-slave
Pure master-slave，显示的在配置文件中指定一个broker做为另一个broker的slave。运行时，slave同过网络自动从master出复制数据，同时在和master失去连接时自动升级为master。当master失效，slave成为master后，如果要让原先的master重新投入运行，需要停掉运行中的slave(现在升级为master了)，手动复制slave中的数据到master中。再重新启动master和slave。这种方式最简单，效率也不错，但是只能有两台做集群，只能fail-over一次，而且需要停机回复master-slave结构。
2.2.2 JDBC master-slave
这种方式不需要特殊的配置，只要让所有的节点都把数据存储到同一个数据库中。先拿到数据库表的锁的节点成为master，一旦它失效了，其它的节点获得锁，就可以成为master。因为数据通过数据库共享，放在一个地方，不需要停机恢复master-slave。这种方式，需要额外的数据库服务器，如果数据库失效了，那么就全失效了，而且速度不是很快。我们在用mysql测试时，并没有成功，master失效后，其他的节点始终没有升级成slave，可能是数据库配置的问题。
2.2.3 Share file master-slave
这种方式类似于前者，也不需要特别的配置，只是通过共享文件系统来共享数据，靠文件锁实现只有一台成为master。共享文件系统的方式有很多，我们测试了nfs v4 (v3有bug，不行)， 最终在稳定性，效率等方面不是很满意，可能是通过网络太慢了。
测试过众多master-slave模式后发现，pure方式管理起来麻烦，jdbc方式成本高，效率低，share file方式需要高性能的共享文件，都有缺点。鉴于单台activeMQ很可靠，而我们的基础平台组愿意用硬件备份，最终还是决定不用master-slave了，也不用broker cluster，就用单台，通过硬件冗余保证数据不会丢失，并找另外一台刀片机做冷备，在主服务器失效时顶替。
]]></description>
		<wfw:commentRss>http://www.sulong.info/archives/207/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 3.381 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2010-03-12 11:34:41 -->
