??xml version="1.0" encoding="utf-8" standalone="yes"?>性色av一区,9i精品一二三区,www.精品国产 http://www.aygfsteel.com/killme2008/category/19800.html生活、程序、未?/description>zh-cn Wed, 09 May 2012 17:47:56 GMT Wed, 09 May 2012 17:47:56 GMT 60 分布式消息中间gMetaq发布1.4.2 http://www.aygfsteel.com/killme2008/archive/2012/05/09/377748.htmldennis dennis Wed, 09 May 2012 14:47:00 GMT http://www.aygfsteel.com/killme2008/archive/2012/05/09/377748.html http://www.aygfsteel.com/killme2008/comments/377748.html http://www.aygfsteel.com/killme2008/archive/2012/05/09/377748.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/377748.html http://www.aygfsteel.com/killme2008/services/trackbacks/377748.html
我们 在维护的淘宝开源消息中间g?a >metaq的github分支Q今天发布了1.4.2版本Q主要做了如下改q:
1.d了大量的使用和原理文档,参见Wiki ?br /> 2.合ƈtools和server-wrapper工程Q提供统一的脚本来理BrokerQ管理Broker的工作变得非常容易,全部工作都可以通过metaServer.sh的脚本来执行。同时提供了bat启动脚本Q用于在windows上启动Broker做测试?br /> 3.新功能: Q?Q新的客LAPI用来获取topic的分区列?br /> Q?Q新的客LAPI用来获取Broker的统计信?br /> Q?Q异步复制的Slave可以自动获取Master的配|变_例如Master在配|文件中新增或者删除了topicq利reload热加载成功后Qslave可自动复制或者移除变更的topicQ无需重启?br /> Q?Q新的统计项目,可以通过'stats config'协议获取Broker的配|文件?br /> 4.dmeta-python目Q一个python的客LQ暂时仅支持发送消息功能?br /> 5.其他改q,如统计信息的优化、构建工L整合{?br />
更详l的发行日志LRelaseNotes ?br />
下蝲地址Q? https://github.com/killme2008/Metamorphosis/downloads 入门指南Q? ?a >如何开?/a>?br /> 更多文档LWiki ?img src ="http://www.aygfsteel.com/killme2008/aggbug/377748.html" width = "1" height = "1" /> ]]> JavaE序员常用工具集 http://www.aygfsteel.com/killme2008/archive/2012/04/17/374936.htmldennis dennis Tue, 17 Apr 2012 09:05:00 GMT http://www.aygfsteel.com/killme2008/archive/2012/04/17/374936.html http://www.aygfsteel.com/killme2008/comments/374936.html http://www.aygfsteel.com/killme2008/archive/2012/04/17/374936.html#Feedback 13 http://www.aygfsteel.com/killme2008/comments/commentRss/374936.html http://www.aygfsteel.com/killme2008/services/trackbacks/374936.html 我发现很多h没办法高效地解决问题的关键原因是不熟(zhn)工P不熟(zhn)工具也qŞ了,甚至q不知道怎么L工具Q这个问题就大条了。我惛_下我能想到的一个JavaE序员会用到的常用工兗?br />
一、编码工?br />
1.IDEQ?a >Eclipse或?a >IDEAQ熟(zhn)尽可能多的快捷键,?a >Eclipse常见快捷键列?/a>?br />
2.插gQ?nbsp;
(1) Findbugs Q在release之前q行一ơ静态代码检查是必须?br />
(2) Clover Q关心你的单元测试覆盖率
(3) Checkstyle 代码风格?br />
3.构徏和部|工?ant 或?a >mavenQ现在主都是maven了吧Q?a >使用nexus搭徏mavenU服Q再加上持箋集成jenkins 。代码质量不用愁?br />
4.版本理工具Q?svn 或?a >git
5.diff和patch
6.讄你的eclipse或者IDEAQ如formatter,save actions 以及code template{。代码风|直接用google的也可以啊。?a >Google style guide?br />
7.掌握一个文本编辑器QEmacs或者VIMQ熟(zhn)常用快捷键。这在你需要在U编辑代码,或者编写其他语a代码时候特别有用。?a >器圣战?br />
二、JDK相关
1.jstat : 观察GC情况Q如Q?br />
jstat -gcutil pid 2000
2.jmapQ查看heap情况Q如查看存活对象列表Q?br />
jmap -histo:live pid |grep com.company |less
或者dump内存用来分析Q?br />
jmap -dump:file=test.bin pid
3.分析dump的堆文gQ可以用jhat:
jhat test.bin
分析完成后可以用览器查看堆的情c这个工L分析l果q比较原始,你还可以?a >Eclipse MAT插gq行囑Ş化分析,或者IBM?a >Heap Analyzer.
4.jvisualvm和jconsoleQ?JVM自带的性能分析和监控工P怎么用?误q文档?/a>
5.jstackQ分析线E堆栈,?br />
jstack pid > thread_dump
查看CPU最高的U程在干什么的Ҏ(gu)l合top和jstackQ?a >http://www.iteye.com/topic/1114219
6.更多JVM工具Q参见官Ҏ(gu)档:http://docs.oracle.com/javase/6/docs/technotes/tools/
7.学习使用btrace分析javaq行旉题。?a >Btrace使用?/a>?br />
8.GC日志分析工具Q?a >GC viewer?a >GC-console或?a >自己挑吧?/a>
9.性能分析工具Q除了自带的jvisualvm外,q可以用商业?a >jprofiler?br />
10.JVM参数大全
11.?a >JVM调优标准参数陷阱》,iteye脓(chung)?br />
三、Linux工具
1.熟?zhn)常用的shell命oQ?/a>
3.使用 htop 替换top?br />
4.熟?zhn)?a >strace,gdb甚至systemta p来分析问题?br />
5.熟?zhn)vmstat,iostat,sar{性能l计工具?/a>
5.自动化部|脚本, py-fabric 或者自荐下我的clojure-control ?br />
四、其?br />
1.掌握一门脚本语aQ?a >Python或?a >RubyQ高效解决一些需要quick and dirty的Q务:比如d文g、导入导出数据库、网늈虫等。注意不是python.comQ咔咔?br />
2.使用Linux或者Mac ospȝ作ؓ你的开发环境?br />
3.升你的“g工具”Q双屏大屏显C器、SSD?G内存甚至更多?br /> 4.你懂的:https://code.google.com/p/goagent/
五、如何查扑ַP
1.搜烦引擎Qgoogle或者baiduQ?a >搜烦技?/a>?br />
2.万能的stack overflowQ?a >http://stackoverflow.com/
3.虚心问牛人?br /> 六、最重要的是⋯⋯ 一颗永不停止学习的心?img src ="http://www.aygfsteel.com/killme2008/aggbug/374936.html" width = "1" height = "1" /> ]]> 淘宝开源metaq的python客户?/title> http://www.aygfsteel.com/killme2008/archive/2012/03/21/372405.htmldennis dennis Wed, 21 Mar 2012 11:08:00 GMT http://www.aygfsteel.com/killme2008/archive/2012/03/21/372405.html http://www.aygfsteel.com/killme2008/comments/372405.html http://www.aygfsteel.com/killme2008/archive/2012/03/21/372405.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/372405.html http://www.aygfsteel.com/killme2008/services/trackbacks/372405.html metaq分支Q今天下午写了个metaq的python客户端,目前仅支持发送消息功能,不过麻雀虽小Q五脏俱全,客户端和zookeeper的交互和q接理之类都还具备Q不出意外,我们会首先用上。第一ơ正儿八l地写python代码Q写的不好的地方请尽拍砖,多谢?br /> 目叫meta-pythonQ仍然放在github上:https://github.com/killme2008/meta-python 使用需要先安装zkpythonq个库,具体安装q篇博客 Q用很单,发送消息: from metamorphosis import Message,MessageProducer,SendResult p=MessageProducer(" topic " ) message=Message(" topic " ," message body " ) print p.send(message) p.close()
MessageProducer是消息发送者,它的构造函数接受至一个topicQ默认的zk_servers为localhost:2181Q可以通过zk_servers参数指定你的zookeeper集群:
p=MessageProducer(" topic " ,zk_servers=" 192.168.1.100:2191,192.168.1.101:2181 " )
更多参数L接看源码吧。一个本机的性能试Qmeta和客L都跑在我的机器上Q机器是Mac MC700Qosx 10.7Q磁盘没有升U过Q: from metamorphosis import Message,MessageProducerfrom time import time p=MessageProducer(" avos-fetch-tasks " ) message=Message(" avos-fetch-tasks " ," http://www.taobao.com " ) start=time()for i in range(0,10000): sent=p.send(message) if not sent.success: print " send failed " finish=time() secs=finish-startprint " duration:%s seconds " % (secs)print " tps:%s msgs/second " % (10000/secs) p.close()
l果Q?br />duration:1.85962295532 seconds tps:5377.43415749 msgs/second
]]> xmemcached发布1.3.6 http://www.aygfsteel.com/killme2008/archive/2012/03/19/372179.htmldennis dennis Mon, 19 Mar 2012 02:51:00 GMT http://www.aygfsteel.com/killme2008/archive/2012/03/19/372179.html http://www.aygfsteel.com/killme2008/comments/372179.html http://www.aygfsteel.com/killme2008/archive/2012/03/19/372179.html#Feedback 2 http://www.aygfsteel.com/killme2008/comments/commentRss/372179.html http://www.aygfsteel.com/killme2008/services/trackbacks/372179.html 开源的memcached Java客户?#8212;—xmemcached 发布1.3.6版本?/p>
主要改进如下Q?/strong>
1. 为MemcachedClientBuilderd两个新方法用于配|:
public void setConnectTimeout(long connectTimeout);
public void setSanitizeKeys(boolean sanitizeKeys);
2. 用于hibernate的XmemcachedClientFactorydd了connectTimeout属性,感谢|友 Boli.Jiang的A献?/span>
3. d新的枚Dcd net.rubyeye.xmemcached.transcoders.CompressionModeQ用于指定Transcoder的压~类型,默认是ZIP压羃Q可选择GZIP压羃。Transcoder接口dsetCompressionModeҎ(gu)?/p>
4. 修改心蟩规则Q原来是在连接空闲的时候发起心跻I现在变成固定每隔5U发起一ơ心x连接?/p>
5. 修改默认参数Q默认禁用nagle法Q默认将扚wget的合q因子下降到50?/p>
6. 修复bug和改q,包括Q?a target="_blank" style="color: #006699; ">161?a target="_blank" style="color: #006699; ">163?a target="_blank" style="color: #006699; ">165?a target="_blank" style="color: #006699; ">169?a target="_blank" style="color: #006699; ">172?73 ?a target="_blank" style="color: #006699; ">176?a target="_blank" style="color: #006699; ">179?a target="_blank" style="color: #006699; ">180?/p>
目主页Q?a target="_blank" style="color: #006699; ">http://code.google.com/p/xmemcached/
目文档Q?a target="_blank" style="color: #006699; ">http://code.google.com/p/xmemcached/w/list
下蝲Q?a target="_blank" style="color: #006699; ">http://code.google.com/p/xmemcached/downloads/list
源码Q?a target="_blank" style="color: #006699; ">https://github.com/killme2008/xmemcached
Maven依赖Q?/strong>
< dependency >
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>1.3.6</version>
</dependency>
最后感谢所有提出issue和改q意见的朋友们?img src ="http://www.aygfsteel.com/killme2008/aggbug/372179.html" width = "1" height = "1" /> ]]> 淘宝开源MQ——metamorphosis的github分支 http://www.aygfsteel.com/killme2008/archive/2012/03/16/372019.htmldennis dennis Fri, 16 Mar 2012 02:39:00 GMT http://www.aygfsteel.com/killme2008/archive/2012/03/16/372019.html http://www.aygfsteel.com/killme2008/comments/372019.html http://www.aygfsteel.com/killme2008/archive/2012/03/16/372019.html#Feedback 3 http://www.aygfsteel.com/killme2008/comments/commentRss/372019.html http://www.aygfsteel.com/killme2008/services/trackbacks/372019.html
上周我在淘宝的同事开源了一个消息中间gmetamorphosis Q放在了淘蝌?/a>上。我从淘蝌蚪的svn上fork了一个github的分支,攑֜了这里:
1.M工程Q?a >https://github.com/killme2008/Metamorphosis
2.CZ目Q?a >https://github.com/killme2008/metamorphosis-example
3.Twitter storm的spout目Q?a >https://github.com/killme2008/storm-metamorphosis-spout
主要做了一些pom文g的简化,发布1.4.0.2版本到maven central仓库Qƈ且写了几个简单的入门文档Q提供了一个完整打包可q行的下载,有兴的自己看github面吧?Wiki文档攑֜Q?br />
https://github.com/killme2008/Metamorphosis/wiki
客户端Maven依赖包括Q可自行选择dQ?br />
< dependency >
< groupId > com.taobao.metamorphosis</ groupId >
< artifactId > metamorphosis-client</ artifactId >
< version > 1.4.0.2</ version >
</ dependency >
< dependency >
< groupId > com.taobao.metamorphosis</ groupId >
< artifactId > metamorphosis-client-extension</ artifactId >
< version > 1.4.0.2</ version >
</ dependency >
< dependency >
< groupId > com.taobao.metamorphosis</ groupId >
< artifactId > storm-metamorphosis-spout</ artifactId >
< version > 1.0.0</ version >
</ dependency >
ps.我开通了新浪微博Q有兴趣怺x下: http://weibo.com/fnil Q你看,偏见是可以改变的?img src ="http://www.aygfsteel.com/killme2008/aggbug/372019.html" width = "1" height = "1" /> ]]> storm常见问题解答 http://www.aygfsteel.com/killme2008/archive/2011/12/19/366763.htmldennis dennis Mon, 19 Dec 2011 07:25:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/12/19/366763.html http://www.aygfsteel.com/killme2008/comments/366763.html http://www.aygfsteel.com/killme2008/archive/2011/12/19/366763.html#Feedback 5 http://www.aygfsteel.com/killme2008/comments/commentRss/366763.html http://www.aygfsteel.com/killme2008/services/trackbacks/366763.html 一、我有一个数据文Ӟ或者我有一个系l里面有数据Q怎么导入storm做计? 你需要实C个SpoutQSpout负责数据emit到stormpȝ里,交给bolts计算。怎么实现spout可以参考官方的kestrel spout实现Q?br />https://github.com/nathanmarz/storm-kestrel 如果你的数据源不支持事务性消费,那么无法得到storm提供的可靠处理的保证Q也没必要实现ISpout接口中的ack和failҎ(gu)?br />二、StormZ保证tuple的可靠处理,需要保存tuple信息Q这会不会导致内存OOMQ?/strong> StormZ保证tuple的可靠处理,acker会保存该节点创徏的tuple id的xor|q称为ack valueQ那么每ack一ơ,将tuple id和ack value做异?xor)。当所有生的tuple都被ack的时候, ack value一定ؓ0。这是个很简单的{略Q对于每一个tuple也只要占用约20个字节的内存。对?00万tupleQ也?0M左右。关于可靠处理看q个Q?br />https://github.com/nathanmarz/storm/wiki/Guaranteeing-message-processing 三、Storm计算后的l果保存在哪里?可以保存在外部存储吗Q?/strong> Storm不处理计结果的保存Q这是应用代码需要负责的事情Q如果数据不大,你可以简单地保存在内存里Q也可以每次都更新数据库Q也可以采用NoSQL存储。stormq没有像s4那样提供一个Persist APIQ根据时间或者容量来做存储输出。这部分事情完全交给用户?br /> 数据存储之后的展玎ͼ也是你需要自己处理的Qstorm UI只提供对topology的监控和l计?br />四、Storm怎么处理重复的tupleQ?/strong> 因ؓStorm要保证tuple的可靠处理,当tuple处理p|或者超时的时候,spout会failq新发送该tupleQ那么就会有tuple重复计算的问题。这个问题是很难解决的,storm也没有提供机制帮助你解决。一些可行的{略Q?br />Q?Q不处理Q这也算是种{略。因为实时计通常q不要求很高的精度Q后l的批处理计会更正实时计算的误差?br />Q?Q用第三方集中存储来过滤,比如利用mysql,memcached或者redisҎ(gu)逻辑主键来去重?br />Q?Q用bloom filter做过滤,单高效?br />五、Storm的动态增删节?/strong> 我在storm和s4里比较里谈到的动态增删节点,是指storm可以动态地d和减supervisor节点。对于减节Ҏ(gu)_被移除的supervisor上的worker会被nimbus重新负蝲均衡到其他supervisor节点上。在storm 0.6.1以前的版本,增加supervisor节点不会影响现有的topologyQ也是现有的topology不会重新负蝲均衡到新的节点上Q在扩展集群的时候很不方便,需要重新提交topology。因此我在storm的邮件列表里提了q个问题Qstorm的开发者nathanmarz创徏了一个issue 54q在0.6.1提供了rebalance命o来让正在q行的topology重新负蝲均衡Q具体见Q?br />https://github.com/nathanmarz/storm/issues/54 ?.6.1的变_http://groups.google.com/group/storm-user/browse_thread/thread/24a8fce0b2e53246 stormq不提供机制来动态调整worker和task数目?br />六、Storm UI里spoutl计的complete latency的具体含义是什么?Z么emit的数目会是acked的两倍? q个事实上是storm邮g列表里的一个问题。Storm作者marz的解{:The complete latency is the time from the spout emitting a tuple to that tuple being acked on the spout . So it tracks the time for the whole tuple tree to be processed. If you dive into the spout component in the UI, you ' ll see that a lot of the emitted / transferred is on the __ack * stream. This is the spout communicating with the ackers which take care of tracking the tuple trees.
单地_complete latency表示了tuple从emit到被ackedl过的时_可以认ؓ是tuple以及该tuple的后l子孙(形成一|Q整个处理时间。其ơspout的emit和transferedq统计了spout和acker之间内部的通信信息Q比如对于可靠处理的spout来说Q会在emit的时候同时发送一个_ack_initlackerQ记录tuple id到task id的映,以便ack的时候能扑ֈ正确的acker task?br /> ]]> Storm源码析之topology的提?/title> http://www.aygfsteel.com/killme2008/archive/2011/12/01/364112.htmldennis dennis Thu, 01 Dec 2011 13:48:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/12/01/364112.html http://www.aygfsteel.com/killme2008/comments/364112.html http://www.aygfsteel.com/killme2008/archive/2011/12/01/364112.html#Feedback 10 http://www.aygfsteel.com/killme2008/comments/commentRss/364112.html http://www.aygfsteel.com/killme2008/services/trackbacks/364112.html http://www.aygfsteel.com/killme2008/archive/2011/11/17/364112.html 作者:dennis (killme2008@gmail.com) 转蝲h明出处?br /> 最q一直在读twitter开源的q个分布式流计算框架——storm的源码,q是有必要记录下一些比较有意思的地方。我按照storm的主要概念进行组l,q且只分析我x的东西,因此UC为浅析?nbsp; 一、介l?br /> Storm的开发语a主要是Java和ClojureQ其中Java定义骨架Q而Clojure~写核心逻辑。源码统计结果: 180 text files. 177 unique files. 7 files ignored. http: // cloc.sourceforge.net v 1.55 T=1.0 s (171.0 files/s, 46869.0 lines/s) ------------------------------------------------------------------------------- Language files blank comment code------------------------------------------------------------------------------- Java 125 5010 2414 25661 Lisp 33 732 283 4871 Python 7 742 433 4675 CSS 1 12 45 1837 ruby 2 22 0 104 Bourne Shell 1 0 0 6 Javascript 2 1 15 6 ------------------------------------------------------------------------------- SUM: 171 6519 3190 37160 ------------------------------------------------------------------------------- Java代码25000多行Q而Clojure(Lisp)只有4871行,说语a不重要再ơ证明是扯E?br /> 二、Topology和Nimbus Topology是storm的核心理念,spout和boltl织成一个topologyQ运行在storm集群里,完成实时分析和计的d。这里我主要想介l下topology部v到storm集群的大概过E。提交一个topologyd到Storm集群是通过StormSubmitter.submitTopologyҎ(gu)提交Q?br />StormSubmitter.submitTopology(name, conf, builder.createTopology());
我们topology打成jar包后Q利用bin/stormq个python脚本Q执行如下命令:bin / storm jar xxxx.jar com.taobao.MyTopology args
jar包提交给storm集群。storm脚本会启动JVM执行Topology的mainҎ(gu)Q执行submitTopology的过E。而submitTopology会将jar文g上传到nimbusQ上传是通过socket传输。在stormq个python脚本的jarҎ(gu)里可以看刎ͼdef jar(jarfile, klass, * args): exec_storm_class( klass, jvmtype = " -client " , extrajars = [jarfile, CONF_DIR, STORM_DIR + " /bin " ], args = args, prefix = " export STORM_JAR= " + jarfile + " ; " )
jar文g的地址讄为环境变量STORM_JARQ这个环境变量在执行submitTopology的时候用刎ͼ// StormSubmitter.java private static void submitJar(Map conf) { if (submittedJar == null ) { LOG.info( " Jar not uploaded to master yet. Submitting jar " ); String localJar = System.getenv( " STORM_JAR " ) ; submittedJar = submitJar(conf, localJar); } else { LOG.info( " Jar already uploaded to master. Not submitting jar. " ); } } 通过环境变量扑ֈjar包的地址Q然后上传。利用环境变量传参是个小技巧?br /> 其次Qnimbus在接收到jar文g后,存放到数据目录的inbox目录Q?strong>nimbus数据目录的结?/strong>Q?br />- nimbus - inbox - stormjar - 57f1d694 - 2865 - 4b3b - 8a7c - 99104fc0aea3.jar - stormjar - 76b4e316 - b430 - 4215 - 9e26 - 4f33ba4ee520.jar - stormdist - storm - id - stormjar.jar - stormconf.ser - stormcode.ser
其中inbox用于存放提交的jar文gQ每个jar文g都重命名为stormjar加上一?2位的UUID。而stormdist存放的是启动topology后生成的文gQ每个topology都分配一个唯一的idQID的规则是“name-计数-旉?#8221;。启动后的topology的jar文g名命名ؓstorm.jar ,而它的配|经qjava序列化后存放在stormconf.ser文gQ而stormcode.ser是将topology本n序列化后存放的文件?strong>q些文g在部|的时候,supervisor会从q个目录下蝲q些文gQ然后在supervisor本地执行q些代码?/strong> q入重点Qtopologyd的分配过E?zookeeper路径说明忽略root): 1.在zookeeper上创?taskheartbeats/{storm id} 路径Q用于Q务的心蟩。storm对zookeeper的一个重要应用就是利用zk的时节点做存活。task定时刷新节点的旉戻I然后nimbus会检这个时间戳是否过timeout讄?br />2.从topology中获取bolts,spouts讄的ƈ行数目以及全局配置的最大ƈ行数Q然后生task id列表Q如[1 2 3 4] 3.在zookeeper上创?tasks/{strom id}/{task id}路径Qƈ存储task信息 4.开始分配Q务(内部UCؓassignment)Q?具体步骤Q?br /> (1)从zk上获得已有的assignment(新的toplogy当然没有了) (2)查找所有可用的slotQ所谓slot是可用的workerQ在所有supervisor上配|的多个worker的端口?br /> (3)Q务均匀地分配给可用的workerQ这里有两种情况Q?br /> (a)task数目比worker多,例如task是[1 2 3 4],可用的slot只有[host1:port1 host2:port1]Q那么最l是q样分配{ 1 : [host1:port1] 2 : [host2:port1] 3 : [host1:port1] 4 : [host2:port1]}
Q可以看CQ务^均地分配在两个worker上?br />(b)如果task数目比worker,例如task是[1 2]Q而worker有[host1:port1 host1:port2 host2:port1 host2:port2]Q那么首先会woker排序Q?strong>不同host间隔排列Q保证task不会全部分配到同一个worker上,也就是将worker排列?br />[host1:port1 host2:port1 host1:port2 host2:port2]
Q然后分配Q务ؓ{ 1 : host1:port1 , 2 : host2:port2}
(4)记录启动旉 (5)判断现有的assignment是否跟重新分配的assignment相同Q如果相同,不需要变_否则更新assignment到zookeeper?assignments/{storm id}上?br />5.启动topologyQ所谓启动,只是zookeeper?storms/{storm id}对应的数据里的active讄为true?br />6.nimbus会检查task的心跻I如果发现task心蟩过时旉Q那么会重新跛_W?步做re-assignment?br /> ]]> Yahoo! s4和Twitter storm的粗略比?/title> http://www.aygfsteel.com/killme2008/archive/2011/11/08/363238.htmldennis dennis Tue, 08 Nov 2011 14:25:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/11/08/363238.html http://www.aygfsteel.com/killme2008/comments/363238.html http://www.aygfsteel.com/killme2008/archive/2011/11/08/363238.html#Feedback 1 http://www.aygfsteel.com/killme2008/comments/commentRss/363238.html http://www.aygfsteel.com/killme2008/services/trackbacks/363238.html Items\Projects
Yahoo! s4
Twitter Storm
协议
Apache license 2.0
Eclipse Public License 1.0
开发语a
Java
Clojure,Java,Clojure~写了核心代?/td>
l构
M心化的对{结?br />
有中心节点nimbusQ但非关?/td>
通信
可插拔的通讯层,目前是基于UDP的实?/td>
Zfacebook开源的thrift框架
事g/Stream
<K,A>序列Q用户可自定义事件类
提供Tuplec,用户不可自定义事件类Q?br />但是可以命名field和注册序列化?/td>
处理单元
Processing ElementsQ内|PE处理 count,join和aggregate{常见Q?/td>
BoltQ没有内|Q务,提供IBasicBolt处理 自动ack
W三方交?br />
提供API,Client Adapter/DriverQ第三方客户端输入或者输Z?/td>
定义Spout用于产生StreamQ没有标准输出API
持久?/td>
提供Persist API规范Q可Ҏ(gu)频率或者次数做 持久?br />
无特定APIQ用户可自行选择处理 可靠处理 无,可能会丢׃?/td> 提供对事件处理的可靠保证Q可选) 路由 EventType + Keyed attribute + value匚w 内置count,join和aggregate标准d Stream Groupings: Shuffle,Fields,All,Global,None,Direct 非常灉|的\由方?/td> 多语a支持 暂时只支持Java 多语a支持良好Q本w支持Java,ClojureQ?br />其他非JVM语言通过thrift和进E间通讯 Failover 部分支持Q数据无法failover 部分支持Q数据同h法failover Load Balance 不支?/td> 不支?/td> q行处理 取决于节Ҏ(gu)目,不可调节 可配|worker和task数目Qstorm会尽量将worker和task均匀分布 动态增删节?/td> 不支? 支持 动态部|?br /> 不支?/td> 支持 web理 不支?/td> 支持 代码成熟?/td> 半成?/td> 成熟 z跃?/td> ?/td> z跃 ~程 ~程 + XML配置 U编E?br /> 参考文?/td> http://docs.s4.io/ https://github.com/nathanmarz/storm/wiki/ http://xumingming.sinaapp.com/category/storm/ Q非常好的中文翻? ]]> 紧急发布xmemcached 1.3.5 http://www.aygfsteel.com/killme2008/archive/2011/10/01/359898.htmldennis dennis Sat, 01 Oct 2011 07:11:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/10/01/359898.html http://www.aygfsteel.com/killme2008/comments/359898.html http://www.aygfsteel.com/killme2008/archive/2011/10/01/359898.html#Feedback 6 http://www.aygfsteel.com/killme2008/comments/commentRss/359898.html http://www.aygfsteel.com/killme2008/services/trackbacks/359898.html xmemcached紧急发?.3.5版本Q主要是修复两个相对严重的bug:Issue 154 : 在重q本地memcached的时候,有可能出现重q无法成功的情况Q导致连接丢失,详情?a >q里?br />Issue 155: 重连D文g句柄数超q限制的bugQ这是由于重q失败情况下没有合理关闭socket引v的,详情?a >q里?br /> 如果你用mavenQ简单升U版本即可: < dependency > < groupId > com.googlecode.xmemcached </ groupId > < artifactId > xmemcached </ artifactId > < version > 1.3.5 </ version > </ dependency >
下蝲地址Q?a >http://code.google.com/p/xmemcached/downloads/list 此版本推荐升U,最后感谢两位老外开发者的帮助Q?
ilkinulas ?a >MrRubato ]]> UniqTask for android http://www.aygfsteel.com/killme2008/archive/2011/09/20/359033.htmldennis dennis Mon, 19 Sep 2011 20:10:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/09/20/359033.html http://www.aygfsteel.com/killme2008/comments/359033.html http://www.aygfsteel.com/killme2008/archive/2011/09/20/359033.html#Feedback 5 http://www.aygfsteel.com/killme2008/comments/commentRss/359033.html http://www.aygfsteel.com/killme2008/services/trackbacks/359033.html 我一直很不爽android的ESd理器,它的q告讄的地斚w常恶心,放在kill键的下面Q而且每次都突然蟩出来Q让你很Ҏ(gu)错误点击。我很佩服他们能惛_q种提高点击率的办法Q但是又无比鄙视q种做法。今天(哦,不是昨天Q晚上在twitter上说了,我想自己写个d理器,cMESd理器,q且没有q告。那好吧Q说q就qԌ奋斗了一个晚上,l于搞出了成果,q就是隆重登场的UniqTaskQ先看看q行时截图: q是q行在我的GS2上的截图?br /> UniqTask的功能跟ESd理器的功能完全一_可以记录kill的历Ԍ每次启动UniqTask的时候自动标记过去killq的q程。但是UniqTask完全l色无毒Q绝Ҏ(gu)有广告,咔咔?br /> 怹没写androidE序Q拿h来不是很利Q折腑ֈ现在才搞定,我将代码攑ֈ了github上,也提供了APK下蝲Q非常欢q试用啊?br /> 源码地址Q?br /> https://github.com/killme2008/UniqTask APK下蝲Q?br /> https://github.com/killme2008/UniqTask/blob/master/UniqTask.apk 白天q有重要的事情要处理Q睡觉去了?img src ="http://www.aygfsteel.com/killme2008/aggbug/359033.html" width = "1" height = "1" /> ]]>高性能EL——Fel探秘Q兼谈EL http://www.aygfsteel.com/killme2008/archive/2011/09/17/358863.htmldennis dennis Sat, 17 Sep 2011 04:52:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/09/17/358863.html http://www.aygfsteel.com/killme2008/comments/358863.html http://www.aygfsteel.com/killme2008/archive/2011/09/17/358863.html#Feedback 5 http://www.aygfsteel.com/killme2008/comments/commentRss/358863.html http://www.aygfsteel.com/killme2008/services/trackbacks/358863.html lotusyu开发的一个高性能的ELQ从作者给出的数据来看Q性能非常优异Q跟前段旉温少开源的Simple EL 有的一拹{首先要_q是个好现象Q国内的开源项目越来越多,可以看出开发者的水^是越来越高了Q比如我最q还看到有h开源的cMkestel的轻量MQ——fqueue 也非怸错,有兴可以看下我的分析?a href="../archive/2011/09/16/358827.html">fqueue初步分析》?br />
q入正文Q本文是试分析下Fel的实现原理,以及优缺点和aviator ——我自己开源的EL之间的简单比较?/p>
Fel的实现原理跟Simple
EL是类|都是使用template生成中间代码——也就是普通的java代码Q然后利用javac~译成classQ最后运行,当然Q这个过E都是动
态的。JDK6已经引入了编译APIQ在此之前的版本可以调用sun的类来编译,因ؓjavac其实是用java实现的。回到Fel?
面,FelCompiler15是?com.sun.tools.javac.Main 来编译,而FelCompiler16用标准的javax.tools.JavaCompiler 来编译的?/p>
文法和语法解释这块是使用antlrq个parse generator生成的,q块不多_有兴可以看下antlrQ整体一个运行的q程是这P
expression string -> antlr -> AST -> comiple -> java source template -> java class -> Expression
q个思\我在实现aviator 之前想q,但是后来考虑到API需要用的sun独有的类Q而且要求classpath必须有tools.jarq个依赖包,放弃了q个思\Q还是采用ASM生成字节码的方式。题外,velocity的优化可以采用这个思\Q我们有q么一个项目是q么做的Q也准备开源了?/p>
看看Fel生成的中间代码,例如a+bq样的一个简单的表达式,假设我一开始不知道a和b的类型,~译是这P
FelEngine fel = new FelEngineImpl(); Expression exp = fel.compile( " a+b " , null );
我稍微改了下FEL的源码,让它打印中间生成的java代码Qa+b生成的中间结果ؓQ?/p>
package com.greenpineyu.fel.compile; import com.greenpineyu.fel.common.NumberUtil; import com.greenpineyu.fel.Expression; import com.greenpineyu.fel.context.FelContext; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; public class Fel_0 implements Expression{ public Object eval(FelContext context) { java.lang.Object var_1 = (java.lang.Object)context.get( " b " ); // b java.lang.Object var_0 = (java.lang.Object)context.get( " a " ); // a return (ObjectUtils.toString(var_0)) + (ObjectUtils.toString(var_1)); } }
可见QFEL对表辑ּ解析和解释后Q利用template生成q么一个普通的javac,而a和b都从context中获取ƈ转化?strong>ObjectcdQ这里没有做M判断q接认为a和b是要做字W串相加Q然后拼接字W串q返回?/p>
问题出来了,因ؓ没有在编译的时候传入contextQ我们这里是nullQ,FEL会将a和b的类型默认都为java.lang.ObjectQa+b解释为字W串拼接。但是运行的时候,我完全可以传入a和b都ؓ数字Q那么结果就非常诡异了:
FelEngine fel = new FelEngineImpl(); Expression exp = fel.compile( " a+b " , null ); Map < String, Object > env = new HashMap < String, Object > (); env.put( " a " , 1 ); env.put( " b " , 3.14 ); System.out.println(exp.eval( new MapContext(env)));
输出Q?/p>
13.14
1+3.14的结果,作ؓ字符串拼接就?3.14Q而不是我们想要的4.14。如果将表达式换成a*bQ就完全q行不了
com.greenpineyu.fel.exception.CompileException: package com.greenpineyu.fel.compile; import com.greenpineyu.fel.common.NumberUtil; import com.greenpineyu.fel.Expression; import com.greenpineyu.fel.context.FelContext; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; public class Fel_0 implements Expression{ public Object eval(FelContext context) { java.lang.Object var_1 = (java.lang.Object)context.get( " b " ); // b java.lang.Object var_0 = (java.lang.Object)context.get( " a " ); // a return (var_0) * (var_1); } } [Fel_0.java: 14 : q算W?nbsp; * 不能应用?nbsp;java.lang.Object,java.lang.Object] at com.greenpineyu.fel.compile.FelCompiler16.compileToClass(FelCompiler16.java: 113 ) at com.greenpineyu.fel.compile.FelCompiler16.compile(FelCompiler16.java: 87 ) at com.greenpineyu.fel.compile.CompileService.compile(CompileService.java: 66 ) at com.greenpineyu.fel.FelEngineImpl.compile(FelEngineImpl.java: 62 ) at TEst.main(TEst.java: 14 ) Exception in thread " main " java.lang.NullPointerException at TEst.main(TEst.java: 18 )
q个问题对于Simple EL同样存在Q如果没有在~译的时候能定变量cdQ这无法生成正确的中间代码,Dq行时出错,q且有可能造成非常诡异的bug?/p>
q个问题的本质是因ؓFel和Simple EL没有自己的类型系l,他们都是直接使用java的类型的pȝQƈ且必d~译的时候确定变量类型,才能生成高效和正的代码Q我们可以将它们UCؓ“强类型的EL“?/strong>
现在让我们在~译的时候给a和b加上cdQ看看生成的中间代码Q?/p>
FelEngine fel = new FelEngineImpl(); fel.getContext().set( " a " , 1 ); fel.getContext().set( " b " , 3.14 ); Expression exp = fel.compile( " a+b " , null ); Map < String, Object > env = new HashMap < String, Object > (); env.put( " a " , 1 ); env.put( " b " , 3.14 ); System.out.println(exp.eval( new MapContext(env)));
查看中间代码Q?/p>
package com.greenpineyu.fel.compile; import com.greenpineyu.fel.common.NumberUtil; import com.greenpineyu.fel.Expression; import com.greenpineyu.fel.context.FelContext; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; public class Fel_0 implements Expression{ public Object eval(FelContext context) { double var_1 = ((java.lang.Number)context.get( " b " )).doubleValue(); // b double var_0 = ((java.lang.Number)context.get( " a " )).doubleValue(); // a return (var_0) + (var_1); } }
可以看到q次a和b都强制{为doublecd了,做数值相加,l果也正了Q?/p>
4.140000000000001
Simple EL我没看过代码Q这里猜它的实C应该是类似的Q也应该有同L问题?/p>
相比来说Q?a >aviatorq是一个弱cd的EL Q?strong>在编译的时候不对变量类型做M假设Q而是在运行时做类型判断和自动转化。过Lq,我给aviator的定位是一个介于EL和script之间的东西,它有自己的类型系l?/strong>?
例如Q?q个数字Q在java里可能是long,int,short,byteQ而aviatorl一为AviatorLongq个cd。ؓ了在q两个类
型之间做适配Q就需要做很多的判断和box,unbox操作。这些判断和转化都是q行时进行的Q因此aviator没有办法做到Felq样的高效,但是?
l做到至跟groovyq样的弱cd脚本语言一个别,也超q了JXELq样的纯解释ELQ具体可以看q个性能试 ?/p>
强类型还是弱cdQ这是一个选择问题Q如果你能在q行前就定变量的类型,那么使用Fel应该可以辑ֈ或者接q于原生java执行的效率,但是失去了灵zL;如果你无法确定变量类型,则只能采用弱cd的EL?/p>
EL涌现的越来越多,q个现象有点cM消息中间仉域,来多面向特定领域的轻量MQ的出玎ͼ而不是原来那U大而笨重的通用MQ大行光Q一斚w是互
联网应用的发展,需求不是通用pȝ能够满的,另一斚w我认Z是开发者素质的提高Q大安能造适合自己的轮子。从ELq方面来_我也认ؓ会有来多
特定于领域的Q优点和~点一样鲜明的EL出现Q它们包含设计者自q目标和口呻I选择很多Q就看取舍?/p>
]]>
fqueue初步分析 http://www.aygfsteel.com/killme2008/archive/2011/09/16/358827.htmldennis dennis Fri, 16 Sep 2011 12:10:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/09/16/358827.html http://www.aygfsteel.com/killme2008/comments/358827.html http://www.aygfsteel.com/killme2008/archive/2011/09/16/358827.html#Feedback 7 http://www.aygfsteel.com/killme2008/comments/commentRss/358827.html http://www.aygfsteel.com/killme2008/services/trackbacks/358827.html fqueue是国产的一个类似memcacheq,kestrelq样的支持memcached协议的轻量开源MQ。它的项目主:http://code.google.com/p/fqueue/downloads/list Q介l和特点都可以看主页Q我׃废话了?br /> 今天老大提到Q?co了源码看了下Q写个初步分析报告?br /> 首先是它的存储层Q主要是一个FQueueq么一个抽象队列,内部实现是FSQueueQ也是Z文g的FIFO队列。这个队列是多个文gl成的。每个文仉认大在150MQ超q即切换一个新文g来写。读的时候如果读到尾部,则查找下一个文件进行读取。数据文件名以idb为后~Qƈ且从~号1开始递增Q除了数据文件外Q每个队列还有个db为后~的烦引文Ӟ记录当前写和ȝ数据文g~号和偏U量。目录结构大概是q样Q?br /> --fqueue --fqueuedata_1.idb --fqueuedata_2.idb --…… --icqueue.db 文g的存储比较有特色Q采?a >MappedByteBuffer做文件读写,MappedByteBuffer 是java nio引入的文件内存映方案,d性能极高Q但是也有一定的问题Q比如说内存占用Q以及数据刷入设备的不确定性和关闭问题。在fqueue中,每隔10毫秒会强制force一ơbufferQ将修改q的数据刷入讑֤。对于关闭问题,则采用那个技巧,CZ代码Q?br />/** * 关闭索引文g */ public void close() { try { mappedByteBuffer.force(); AccessController.doPrivileged( new PrivilegedAction < Object > () { public Object run() { try { Method getCleanerMethod = mappedByteBuffer.getClass().getMethod( " cleaner " , new Class[ 0 ]); getCleanerMethod.setAccessible( true ); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(mappedByteBuffer, new Object[ 0 ]); cleaner.clean(); } catch (Exception e) { log.error( " close logindexy file error: " , e); } return null ; } }); fc.close(); dbRandFile.close(); mappedByteBuffer = null ; fc = null ; dbRandFile = null ; } catch (IOException e) { log.error( " close logindex file error: " , e); } }
利用反射Qƈ且用了sunҎ(gu)的类Q不h可移植性。MappedByteBufferq有一个问题是map的代h较高Q可能在切换文g的时候fqueue会有一定程度的d现象?br /> 存储的性能Q我在我的机器测试了下,g没有作者宣U的那么高,我的机器?400转的普通SATA盘,写入1K数据的^均QPS?000左右。我估计fqueue的性能跟磁盘有很大关系Q如果?5000转的SAS盘应该能有很大改观?br /> |络层直接用了jmemcached的实玎ͼjmemcached 是一个java实现的memcachedQ通常用于单元试之类。看情况fqueue也支持memcached的二q制协议了。网l框架用了netty3Q这些就不多说了。自q都明白。额外提一下,作者做的单元测试用了xmemcached Q咔咔,q而告之?br /> M来说fqueue是一个整体上很清爽和轻量U的MQ实现Q适合一些特定的场景Q至于性能Q我们下周准备做个压,到时候再谈吧?img src ="http://www.aygfsteel.com/killme2008/aggbug/358827.html" width = "1" height = "1" /> ]]> xmemcached发布1.3.4 http://www.aygfsteel.com/killme2008/archive/2011/09/08/358317.htmldennis dennis Thu, 08 Sep 2011 10:55:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/09/08/358317.html http://www.aygfsteel.com/killme2008/comments/358317.html http://www.aygfsteel.com/killme2008/archive/2011/09/08/358317.html#Feedback 3 http://www.aygfsteel.com/killme2008/comments/commentRss/358317.html http://www.aygfsteel.com/killme2008/services/trackbacks/358317.html
开源的java memcached client—— xmemcached 发布1.3.4版本Q主要改q如下:
1、修复一个相对严重的bugQ在解析二进制协议时如果遇到从服务端q回的错误信息,会导致连接异常断开Q如果你没有使用binary协议Q不会遇到此问题?strong>使用xmemcachedq且使用二进制协议的朋友升到此版本 ?/strong>
2、允许XMemcachedClientFactoryBean配置opTimeout选项?
3、添加RoundRobinMemcachedSessionLocatorQ轮询的q接选择器,仅用于kestrel或者memcacheq集群Q这些应用都不要求同一个key要保存在固定的服务器上,而仅是作为集分担负载?/p>
4?a >KetamaMemcachedSessionLocatord额外选项Q允讔R|是否兼?nginx-upstream-consistent Q这个是|友
wolfg1969 贡献的patch。如果要使得xmc的一致性哈希算法兼?/span>nginx-upstream-consistentQ只要设|cwNginxUpstreamConsistent为true卛_Q示范代码:
MemcachedClientBuilder builder = new XMemcachedClientBuilder( AddrUtil.getAddresses(servers)); builder.setSessionLocator( new KetamaMemcachedSessionLocator( true ));
5、修复bugQ包?a class="closed_ref" title="Typo in INFO message: log.info("Creating " + selectorPoolSize + " rectors...");" >issue 132 , issue 142 , issue 133 , issue 139 , issue 142 , issue 145 ,issue 150 {?/p>
如果你用mavenQ只要简单升U版本即可:
< dependency > < groupId > com.googlecode.xmemcached </ groupId > < artifactId > xmemcached </ artifactId > < version > 1.3.4 </ version > </ dependency >
下蝲地址Q?/p>
http://code.google.com/p/xmemcached/downloads/list
]]> 找bug?2) http://www.aygfsteel.com/killme2008/archive/2011/09/02/357774.htmldennis dennis Thu, 01 Sep 2011 16:02:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/09/02/357774.html http://www.aygfsteel.com/killme2008/comments/357774.html http://www.aygfsteel.com/killme2008/archive/2011/09/02/357774.html#Feedback 5 http://www.aygfsteel.com/killme2008/comments/commentRss/357774.html http://www.aygfsteel.com/killme2008/services/trackbacks/357774.html q篇blogq到了很久,本来是想写另一个跟|络相关bug的查找过E,偷偷懒,写下最q印象比较深ȝbug。这个bug是我的同事水寒最l定位到的?br /> 前几个月同事报告U有一个线上MQ集群会同一旉抛出ArrayIndexOutOfBoundsExceptionq个异常Q也是数组界。查看源码,除去一些无关紧要的l节大概是这样子Q?br />public class ConnectionSelector{ private AtomicInteger sets = new AtomicInteger( 0 ); public void selectConnection(List < Connection > connList){ if (connList == null )?br /> return null ; ?br /> final int size = connList.size(); if (size == 0 ) { return null ; } return connList.get(sets.incrementAndGet() % size); } }
很显Ӟq里的本意是实现一个轮询的q接选择器,q回一个选中的连接。用AtomicInteger递增q对链表大小取模Q返回结果烦引位|的q接。异常抛出的位置是我代码中标红的位|?br /> 昄Q这里有两种可能Q一U情况下是说在执行那一行代码的时候,connList的大羃?yu)了Q也是说连接可能被其他U程UdQ,那么D取模的结果越界。另一U可能是取模的结果本w确实超q了列表范围?br /> W一U情冉|完全可能的,因ؓ服务器的q接可能随时断开或者重q,但是q种情况相对非常见Q因此我们这里ƈ没有对这个选择q程做同步,主要是从性能的角度出发,偶尔的失败可以接受。很遗憾的是Q我被我的思维惯性误gQ从来没有怀疑过W二U情况,L认ؓ是不是真的连接恰巧断开Dq个异常Q但是却无法解释q个异常发生后就一直错误下去,无法自行恢复?br /> Z么说思维惯性误导呢Q这里的问题其实是负数取模的问题Q对一个负数进行取模,l果会是正数q是负数Q答案是l果因语a而异?br /> 我很早以前在使用Ruby的时候做q测试,负数取模l果为正敎ͼ例如在irb里尝试下Q?br />>> - 1000 % 3 => 2 >> - 2001 % 4 => 3
q个印象持箋至今Q在clojure里结果也是这样子Q?br />Clojure 1.2 . 1 user=> (mod - 1000 3 ) 2 user=> (mod - 2001 4 ) 3
可以再试试python:Python 2.7 . 1 (r271: 86832 , Jun 16 2011 , 16 : 59 : 05 ) [GCC 4.2 . 1 (Based on Apple Inc. build 5658 ) (LLVM build 2335.15 . 00 )] on darwin Type " help " , " copyright " , " credits " or " license " for more information. >>> - 10000 % 3 2 >>> - 2001 % 4 3
q三U语a的结果完全一_l果都ؓ正数。这个惯性思维延箋到java却不成立了,可惜我根本没做测试,让我们试下: public static void main( final String[] args) { System.out.println( - 1000 % 3 ); System.out.println( - 2001 % 4 ); }
打印l果为:- 1 - 1
果然Q在java里负数取模的l果敎ͼ而不是我习惯性地认ؓ是正数。因此最l的定位到的原因是setsq个变量递增过Integer.MAX_VALUE后越界变成负CQ取模的l果敎ͼD抛出数组界的异常,q也解释了ؓ什么同一个集都在同一旉出问题,因ؓq个集群内的机器启动旉盔Rq且调用q个Ҏ(gu)ơ数相对q_?strike>修正问题很简单,加个Math.abs好?/strike> Update:加个abs是不够的Q因为Math.abs的javadoc提醒了:Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
也就是说对Integer.MIN_VALUE做absl果仍然是负数。尽在q个场景中失败一ơ可以接受,但是最好的办法q是回复中steven提到的抵消符号位的做法:(sets.incrementAndGet() & 0x7FFFFFFF ) % size
q个问题更详l的讨论后来我找?a >q篇博客Q作者讨论几U语a和计器的这个问题的l果Q给Z一些结论。不q我觉的q个l论可能也不是那么可靠,特别是对c/c++来说Q很大程度上应该q是依赖于实玎ͼ最可靠的办法还是强制结果ؓ正?br /> q个bug的几个教训: 1、首先是W一ơ出现的时候没有引赯够重视,重启解决问题后没有深I。有句玩W话Q?9Q的E序问题都可以通过重启解决。但是事实上问题仍然存在Q该发生的终I还会发生。不你信不信,它就是发生了Q这是一个奇qV?br />2、注意大脑的思维惯性,l验M和教条主义都不可取。最q在M本好书?a >暗时?/a>》,大脑误导我们的手D可是多U多栗?br />3、最后就是这个负数取模的l果因语a而异Q不要依赖于特定实现?br /> ]]> 轻量U高性能的表辑ּ求值器——aviator发布2.0 http://www.aygfsteel.com/killme2008/archive/2011/07/13/354296.htmldennis dennis Wed, 13 Jul 2011 14:34:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/07/13/354296.html http://www.aygfsteel.com/killme2008/comments/354296.html http://www.aygfsteel.com/killme2008/archive/2011/07/13/354296.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/354296.html http://www.aygfsteel.com/killme2008/services/trackbacks/354296.html
aviator 是一个轻量的、高性能的Java表达式求值器Q主要应用在如工作流引擎节点条g判断、MQ中的消息qo以及某些特定的业务场景?/p>
自从上次发布1.0后,q发q?.01版本Q不q都没怎么宣传。这ơ发布一?.0的里E碑版本Q主要改q如下:
1、完整支持位q算W,与java完全一致。位预算W对实现bit set之类的需求还是非常必ȝ?
2、性能优化Q^均性能提升100%Q函数调用性能提升200%Q最新的与groovy和JEXL的性能试看这?/p>
http://code.google.com/p/aviator/wiki/Performance
3、添加了新函敎ͼ包括long、double、str用于cd转换Q添加了string.indexOf函数?/p>
4、完善了用户手册Q更新性能试?/p>
下蝲地址Q?nbsp; http://code.google.com/p/aviator/downloads/list
目主页Q?nbsp; http://code.google.com/p/aviator/
用户指南Q?nbsp; http://code.google.com/p/aviator/w/list
性能报告Q?nbsp; http://code.google.com/p/aviator/wiki/Performance
源码Q?nbsp; https://github.com/killme2008/aviator
Maven引用Q感谢许老大的帮助)Q?/p>
< dependency > < groupId > com.googlecode.aviator </ groupId > < artifactId > aviator </ artifactId > < version > 2.0 </ version > </ dependency >
q个目目前用在我们的MQ产品中做消息qoQ也有几个公司外的用户告诉我他们也在用,不过估计不会很多。有q种需求的场景q是比较?yu)的。这个项目实际上是ؓ我们的MQ定制的,我主要想做到q么几点Q?/p>
Q?Q控制用戯够用的函数Q不允许调用M不受控制的函数?/p>
Q?Q轻量Q不需要嵌入groovyq么大的脚本引擎Q我们只需要一个剪裁过的表辑ּ语法卛_?/p>
Q?Q高性能Q最l的性能在某些场景比groovy略差Q但是已l非常接q?/p>
Q?Q易于扩展,可以Ҏ(gu)地添加函数扩展功能。语法相对固定?/p>
Q?Q函数的调用避免使用反射。因此没使用dotq算W的函数调用方式Q而是更类似c语言和lua语言的函数调用风根{函数是一{公民,seq库的风格很符合我的喜好?/p>
seqq概忉|自clojureQ我实Cjava.util.Collection接口的类和数l都UCؓseq集合Q可以统一使用seq库操作。例如假设我有个list:
Map < String, Object > env = new HashMap < String, Object > ();
ArrayList < Integer > list = new ArrayList < Integer > ();
list.add( 3 );
list.add( 100 );
list.add( - 100 );
env.put( " list " , list);
可以做这么几个事情,度量大小Q?br />count(list)
判断元素是否存在Q?br />include(list, 3 )
qo元素Q返回大?的元素组成的seqQ?br />filter(list,seq.gt( 0 ))
寚w合里的元素求和,应用reduce:reduce(list, + , 0 )
遍历集合元素q打华ͼmap(list,println)
最后,你还可以排序:sort(list)
q些函数cMFP里的高阶函数Q用v来还是非常爽的?br /> 对函数调用的优化Q其实只q了一个事情,原来函数调用我是所有参数收集到一个list里面Q然后再转成数组元素交给AviatorFunction调用。这里创Z两个临时对象Qlist和数l。这其实是没有必要的Q我只要在AviatorFunction里定义一pd重蝲Ҏ(gu)Q如Q?br /> public AviatorObject call(Map < String, Object > env); public AviatorObject call(Map < String, Object > env, AviatorObject arg1); public AviatorObject call(Map < String, Object > env, AviatorObject arg1, AviatorObject arg2); public AviatorObject call(Map < String, Object > env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3); ׃需要收集参敎ͼ而是直接invokeinterface调用AviatorFunction相应的重载方法即可。我看到在JRuby和Clojure里的Ҏ(gu)调用都这样干的。过ȝ思\走岔了。最l也不需要区分内部的method和外部的functionQ统一Z个对象即可,q一步减了对象创徏的开销?img src ="http://www.aygfsteel.com/killme2008/aggbug/354296.html" width = "1" height = "1" /> ]]>找bug讎ͼ1Q?/title> http://www.aygfsteel.com/killme2008/archive/2011/07/10/354062.htmldennis dennis Sun, 10 Jul 2011 15:29:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/07/10/354062.html http://www.aygfsteel.com/killme2008/comments/354062.html http://www.aygfsteel.com/killme2008/archive/2011/07/10/354062.html#Feedback 16 http://www.aygfsteel.com/killme2008/comments/commentRss/354062.html http://www.aygfsteel.com/killme2008/services/trackbacks/354062.html
转蝲h明出?http://www.aygfsteel.com/killme2008/archive/2011/07/10/354062.html
上周在线上系l发C两个bugQ值得记录下查扄q程和原因。以后如果还有查找bug比较有h(hun)值的l历Q我也会l箋分n?br />
W一个bug的v始,是在U上日志发现一个频J打印的异常——java.lang.ArrayIndexOutOfBoundsException。但是却没有堆栈Q只有一行一行的ArrayIndexOutOfBoundsException。没有堆栈,不知道异常是从什么地Ҏ(gu)出来的,也就不能扑ֈ问题的根源,更谈不上解决。题外,工程师在用log4j记录错误异常的时候,我看到很多hq样用(假设e是异常对象)Q?br />
log.error( " 发生错误: " + e);
或者:
log.error( " 发生错误: " + e.getMessage());
q样的写法是不对Q只记录了异常的信息Q而没有将堆栈输出到日志,正确的写法是利用error的重载方法:
log.error( " xxx发生错误 " ,e);
q样才能在日志中完整地输出异常堆栈来。如何写好日志是另一个话题,q里不展开。l我们的找bugl历。刚才提刎ͼ我们U上日志一直出C行错误信息ArrayIndexOutOfBoundsException却没有堆栈,是我们没有正地写日志吗Q检查代码不是的Q这个问题其实是跟JDK5引入的一个新Ҏ(gu)有养I对于一些频J抛出的异常QJDKZ性能会做一个优化,在JIT重新~译后会抛出没有堆栈的异常。在使用server模式的时候,q个优化是开启的Q我们的服务器跑在server模式下ƈ且jdk版本?Q因此在频繁抛出ArrayIndexOutOfBoundsException异常一D|间后优化开始v作用Q只抛出没有堆栈的异怿息了?br />
那么怎么解决q个问题呢?因ؓq个优化是在JIT重新~译后才起作用,因此一开始抛出异常的时候还是有堆栈的,所以可以查看较旧的日志Q寻找有完整堆栈的异怿息。但是由于我们的日志太大Q会定期删除Q我们的服务器也启动了很长时_因此查找日志不是很靠qҎ(gu)?br />
另一个解军_法是暂时用q个优化Q强制要求每ơ都要抛出有堆栈的异常。幸好JDK提供了选项来关闭这个优化,配置JVM参数
- XX: - OmitStackTraceInFastThrow
可以禁止这个优化(注意选项中的减号Q加h启用Q?br />
我们找了台机器,配置了这个参数ƈ重启一下。过了一会就扑ֈ问题所在,堆栈cMq样
Caused by: java.lang.ArrayIndexOutOfBoundsException: - 1831238
at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:436 )
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java: 2081 )
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java: 1996 )
at java.util.Calendar.setTimeInMillis(Calendar.java: 1109 )
at java.util.Calendar.setTime(Calendar.java: 1075 )
at java.text.SimpleDateFormat.format(SimpleDateFormat.java: 876 )
at java.text.SimpleDateFormat.format(SimpleDateFormat.java: 869 )
at java.text.DateFormat.format(DateFormat.java: 316 )
读者肯定猜CQ这个问题是׃SimpleDateFormat的误用引L?a >SimpleDateFormat?a >javadoc中有q么句话Q?br />
Date formats are not synchronized . It is recommended to create separate format instances for each thread.
If multiple threads access a format concurrently, it must be synchronized externally.
但是很?zhn)剧的是这句话是放在整个doc的最后面Q在我看来,q句话应该放在最前面才对。简单来说就是SimpleDateFormat不是U程安全的,你要么每ơ都new一个来用,要么做加锁来同步使用?br />
出问题的代码是׃工程师认为SimpleDateFormat的创Z价很高,然后搞了个map做缓存,所有线E共用这个instance做formatQ同时没有做同步。?zhn)剧就诞生了?br />
q里引出我x到的W二炚w题,在用一个类或者方法的时?strong>Q最好能详细地看下该cȝjavadocQJDK的javadoc是做的非常好?/strong>Qjavadoc除了做说明之外,通常q会l示例,q且会点Z些关键问题,如线E安全性和q_UL性?br />
最后,我将做个试Q到底在使用SimpleDateFormat怎么做才是最好的方式Q假设我们要实现一个formatDateҎ(gu)日期格式化?yyyy-MM-dd"的格式?br />
W一个方法是每次使用都创Z个instanceQƈ调用formatҎ(gu)Q?br />
public static String formatDate1(Date date) {
SimpleDateFormat format = new SimpleDateFormat( " yyyy-MM-dd " );
return format.format(date);
}
W二个方法是只创Z个instanceQ但是在调用Ҏ(gu)的时候做同步Q?br />
private static final SimpleDateFormat formatter = new SimpleDateFormat( " yyyy-MM-dd " );
public static synchronized String formatDate2(Date date) {
return formatter.format(date);
}
W三个方法比较特D,我们为每个线E都~存一个instanceQ存攑֜ThreadLocal里,使用的时候从ThreadLocal里取可以了:
private static ThreadLocal < SimpleDateFormat > formatCache = new ThreadLocal < SimpleDateFormat > () {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat( " yyyy-MM-dd " );
}
};
public static String formatDate3(Date date) {
SimpleDateFormat format = formatCache.get();
return format.format(date);
}
然后我们试下三个方法ƈ发调用下的性能q做一个比较,q发100个线E@环调?000万次Q记录耗时。我们设|了JVM参数Q?br />
- Xmx512m - XX:CompileThreshold = 10000
讄堆最大ؓ512MQ设|当一个方法被调用1万次的时候就被JIT~译。测试的l果如下Q?br />
W?ơ测?br />
W?ơ测?br />
W?ơ测?br />
formatDate1
50545
49365
53532
formatDate2
10895
10761
10673
formatDate3
10386
9919
9527
(单位Q毫U) 从结果来看,Ҏ(gu)1最慢,Ҏ(gu)3最快,但是q是最慢的Ҏ(gu)1也可以达到每U钟200 20万次的调用量Q很有pȝ能达到这个量U。这个点很难成ؓ你系l的瓉所在。从我的角度出发Q我会徏议你用方?或者方?Q如果你q求那么一Ҏ(gu)能提升的话Q可以考虑用方?Q也是用ThreadLocal做缓存?br /> ȝ下本文找bugl历惌辄几点xQ?br />Q?Q正地打印错误日志 Q?Q在server模式下,最好都讄- XX: - OmitStackTraceInFastThrow Q?Q用类或者方法的时候,最好能详细阅读下javadocQ很多问题都能找到答?br />Q?Q用SimpleDateFormat的时候要注意U程安全性,要么每次newQ要么做同步Q两者的性能有差距,但是q个差距很难成ؓ你的性能瓉?br /> 下篇文章我再分n另一个bug的查扄历,也是比较有趣Q可以看C些工L使用?br /> ]]> Java NIO~程的技巧和陷阱 http://www.aygfsteel.com/killme2008/archive/2011/06/30/353422.htmldennis dennis Thu, 30 Jun 2011 03:07:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/06/30/353422.html http://www.aygfsteel.com/killme2008/comments/353422.html http://www.aygfsteel.com/killme2008/archive/2011/06/30/353422.html#Feedback 4 http://www.aygfsteel.com/killme2008/comments/commentRss/353422.html http://www.aygfsteel.com/killme2008/services/trackbacks/353422.html
d做的分nQ一直上传slidesharep|Q今天又试了下,成功了。这个主题主要介lJava NIO~程的技巧和陷阱Q解M一些NIO框架的源码,以及~写高性能NIO|络框架所需要注意的技巧和~陷。关注这斚w的朋友可以看一下。去q写了篇blog提供了pdf版本的下载,?a href="http://www.aygfsteel.com/killme2008/archive/2010/11/22/338420.html">q里?br />
]]> xmemcached发布1.3.3版本——支持touch和GAT http://www.aygfsteel.com/killme2008/archive/2011/06/12/352120.htmldennis dennis Sun, 12 Jun 2011 05:32:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/06/12/352120.html http://www.aygfsteel.com/killme2008/comments/352120.html http://www.aygfsteel.com/killme2008/archive/2011/06/12/352120.html#Feedback 2 http://www.aygfsteel.com/killme2008/comments/commentRss/352120.html http://www.aygfsteel.com/killme2008/services/trackbacks/352120.html xmemcached发布1.3.3Q主要改q如下: 1、memcached 1.6d了不新Ҏ(gu),具体可以参考《what's new in memcached?1 ) (2 )q两个帖子。xmemcached及时跟q这些新Ҏ(gu)?.3.3q个版本实现了二q制协议中新的两个命令touch和GAT Qget and touch)。这两个功能可以说是千呼万唤始出来,l于可以不用get-set来重新设|数据的时旉Q利用touch或者GAT可以单地更新数据的超时时间?.3.3新增加四个方法: public boolean touch( final String key, int exp, long opTimeout) throws TimeoutException, InterruptedException, MemcachedException; public boolean touch( final String key, int exp) throws TimeoutException, InterruptedException, MemcachedException; public < T > T getAndTouch( final String key, int newExp, long opTimeout) throws TimeoutException, InterruptedException, MemcachedException; public < T > T getAndTouch( final String key, int newExp) throws TimeoutException, InterruptedException, MemcachedException;
其中touch用于讄数据新的时旉QgetAndTouch则是在获取数据的同时更新时旉。例如用memcached存储sessionQ可以在每次get的时候更C数据的超时时间来保活?strong>h意,q四个方法仅在用memcached 1.6q且使用二进制协议的时候有?/strong>?br /> 2、setLoggingLevelVerbosityҎ(gu)可以作用于二q制协议?/strong> 3、重构错误处理模块,使得异常信息更友好?/strong>4、将KeyIterator和getKeyIterator声明为deprecatedQ?/strong>因ؓmemached 1.6移除stats cachedump协议Qƈ且stats cachedumpq回数据有大限Ӟ遍历功能不具实用性?br />5、修复Bug Q包?a title="Error getting memcached Detail Statistics" class="closed_ref" >issue 126 ,issue 127 ,issue 128 ,issue 129 ?br /> 下蝲地址Q?a >http://code.google.com/p/xmemcached/downloads/list 源码Q?nbsp; https://github.com/killme2008/xmemcached maven引用Q?br /> < dependency > < groupId > com.googlecode.xmemcached </ groupId > < artifactId > xmemcached </ artifactId > < version > 1.3.3 </ version > </ dependency >
]]> HandlerSocket client for java——hs4j正式发布0.1版本 http://www.aygfsteel.com/killme2008/archive/2011/03/29/347160.htmldennis dennis Mon, 28 Mar 2011 22:55:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/03/29/347160.html http://www.aygfsteel.com/killme2008/comments/347160.html http://www.aygfsteel.com/killme2008/archive/2011/03/29/347160.html#Feedback 3 http://www.aygfsteel.com/killme2008/comments/commentRss/347160.html http://www.aygfsteel.com/killme2008/services/trackbacks/347160.html
HandlerSocket 是一个mysql插gQ可以将mysql作ؓNoSQL来用,具体可以看我q去写的q篇Blog ?a >hs4j是HandlerSocket的一个java客户端,自认为它比日本h写的那个客户端更实用和易用一些。写完好久,l过不少朋友使用和测试,现在正式发一?.1版本Qƈ已同步到maven中心仓库?br />
目主页Q?a title="http://code.google.com/p/hs4j/" >http://code.google.com/p/hs4j/
目描述Qhs4j is a practical java client for HandlerSocket ,it is nio based and turned to get better performance.
使用文档Q?a >http://code.google.com/p/hs4j/w/list
下蝲地址Q?a title="http://code.google.com/p/hs4j/downloads/list" >http://code.google.com/p/hs4j/downloads/list
源码仓库Q?a rel="nofollow">https://github.com/killme2008/hs4j
如果你用maven2Q可以直接引用:
< dependency >
< groupId > com.googlecode.hs4j </ groupId >
< artifactId > hs4j </ artifactId >
< version > 0.1 </ version >
</ dependency >
有疑问和bug误pL?br /> ]]> xmemcached发布1.3.2版本 http://www.aygfsteel.com/killme2008/archive/2011/03/27/347102.htmldennis dennis Sun, 27 Mar 2011 06:06:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/03/27/347102.html http://www.aygfsteel.com/killme2008/comments/347102.html http://www.aygfsteel.com/killme2008/archive/2011/03/27/347102.html#Feedback 1 http://www.aygfsteel.com/killme2008/comments/commentRss/347102.html http://www.aygfsteel.com/killme2008/services/trackbacks/347102.html Xmemcached 是一个开源的java memcached clientQ具有高性能、更易用、功能完善等优点Q距Mơ发?.3.1已经过两个月,现在正式发布1.3.2q个新版本,主要的改q如下:
1、Bug修复 Q从1.3.1版本以来发现的bugq修复,包括Q?
issue 112 :: 新引入的failure模式在启动的时候,如果memcached故障Q运行不W合预期的bug.
issue 113 : 新增加一个deleteҎ(gu)Q可以设|操作超?/p>
public boolean delete( final String key, long opTimeout)
throws TimeoutException, InterruptedException, MemcachedException;
2、性能调优 Q存储操?set/add/replace/prepend/append/cas)的性能提升5%?/p>
3、修复pom.xml Q得xmemcached可以在其他机器上~译?/p>
4、用github作ؓ源码仓库 Q版本管理用git替换svnQ源码{Ud
https://github.com/killme2008/xmemcached
新版本下载地址Q?/p>
http://code.google.com/p/xmemcached/downloads/list
使用maven可以直接引用Q?nbsp;
< dependency >
< groupId > com.googlecode.xmemcached </ groupId >
< artifactId > xmemcached </ artifactId >
< version > 1.3.2 </ version >
</ dependency >
目文档Q?/p>
http://code.google.com/p/xmemcached/w/list
]]>Xmemcached 1.3.0正式发布 http://www.aygfsteel.com/killme2008/archive/2011/01/04/342287.htmldennis dennis Tue, 04 Jan 2011 12:10:00 GMT http://www.aygfsteel.com/killme2008/archive/2011/01/04/342287.html http://www.aygfsteel.com/killme2008/comments/342287.html http://www.aygfsteel.com/killme2008/archive/2011/01/04/342287.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/342287.html http://www.aygfsteel.com/killme2008/services/trackbacks/342287.html Xmemcached是一个开源的memcached的Java客户端,最q引入了一些关键特性,因此版本L接从1.2.6.2升?.3.0。主要的更改如下Q?br />
1、引入了failure模式 Q所谓failure模式是指在当一个memcached׃各种原因不可用的情况下,发往q个节点的请求将直接抛出异常Q而非使用下一个可用的节点。具体可以看memached?a >q个文档。默认不启用Q启用failure模式很简单:
MemcachedClientBuilder builder = ……
// 启用failure模式?/span>
builder.setFailureMode( true );
也可以采用spring配置?br />
2、在启用failure模式的情况下Q允ؓ每个memcached讄一个备份节点, 当主节点挂掉的情况下Q会请求{交给备䆾节点Q主节点恢复后又自动切换C节点。请注意Q要讄备䆾节点的前提是启用failure模式。假设我们已l有两个memcached节点Qhost1:port和host2:portQؓhost1:port讄一个备份节点host3:port可以实现为:
MemcachedClientBuilder builder = new XmemcachedClientBuilder(AddrUtil.getAddressMap( " host1:port,host3:port host2:port " ))
……
d节点之间用逗号隔开Q不同分l之间用I格隔开Q完全兼?.2。ƈ且当备䆾节点q接意外断开的情况下Qxmemcached也会自动修复备䆾节点的连接ƈ加入映射?br />
关于failure模式和standby节点更多内容可以参?a href="http://www.aygfsteel.com/killme2008/archive/2010/12/28/341731.html">q篇blog.
3、修正BUG和新功能 Q包?a >issue 104,issue 105 ,issue 107 {?br />
目主页 http://code.google.com/p/xmemcached/
下蝲地址 http://code.google.com/p/xmemcached/downloads/list
用户指南 http://code.google.com/p/xmemcached/wiki/TableOfContents
如果你用maven构徏Q可以直接引用:
< dependency >
< groupId > com.googlecode.xmemcached </ groupId >
< artifactId > xmemcached </ artifactId >
< version > 1.3.1 </ version >
</ dependency >
更新Q发?.3.1了,如果你还在?.3.0Q徏议升U?.3.0因ؓ改变了memcached地址服务器顺序,可能D原有的缓存失效?br />
]]> Xmemcached 1.3预览Qfailure模式和standby节点 http://www.aygfsteel.com/killme2008/archive/2010/12/28/341731.htmldennis dennis Tue, 28 Dec 2010 02:47:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/12/28/341731.html http://www.aygfsteel.com/killme2008/comments/341731.html http://www.aygfsteel.com/killme2008/archive/2010/12/28/341731.html#Feedback 5 http://www.aygfsteel.com/killme2008/comments/commentRss/341731.html http://www.aygfsteel.com/killme2008/services/trackbacks/341731.html
Xmemcached 在元旦左叛_备发1.3q个版本Q这个版本新增加的一个关键特性就是所谓的failure模式。关于这个,可以看下memcached官方文档的解?br />
XMemcachedClientBuilder builder = ……
// 讄使用failure模式
builder.setFailureMode( true );
在此模式下,某个节点挂掉的情况下Q往q个节点的请求都直接抛出MemcachedException的异常?br />
不仅如此Qxmemcached 1.3q将引入standby node的概念,你可以设|某个memached节点的备份节点,当这个节Ҏ(gu)掉的时候会请求{发给q个备䆾节点Q不会简单地抛出异常Q也不会转发l其他节炏V要使用standby nodeQ必首先设|用failure modeQ一个例子:
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil
.getAddressMap( " 192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211 " ));
builder.setFailureMode( true );
可以看到Q新的服务器字符串格式变化ؓhost:port,host:port host:port,host:port的格式,以空格隔开的是两个节点l成的一个分l,以逗号隔开的是主节点和备䆾节点Q以上面的例子来_我们讄客户端用的节点?92.168.1.99?92.168.1.101Q其?9对应的备份节Ҏ(gu)100Q?01的备份节Ҏ(gu)102。ƈ且我们需要设|用failure mode为true?br />
Failure mode加上standby节点可以比较好的解决新旧数据的问题,q且也可以防止请求穿透缓存到DBQ但是主备两个节点之间的数据同步Qxmemcached不准备帮你做Q我的徏议是可以使用repcachedq个patch做复制?br />
有的朋友可能希望Q在使用备䆾节点之前先flush掉备份节点的数据Q防止用到老的数据Q请求还是可以穿透缓存去DB查找Qƈ存储到备份节点,我仔l考虑了这个方案,衡量之下q是不准备做自动flushQ主要是q发上很隑֤理,q且flush数据q个事情可以手工来搞Q根据我的经验,做的太透明太自动不一定是好事。你可以在主节点恢复之后Q手工flush下备份节点的数据?br />
目前Qxmemcached 1.3已经整装待发Q对q些Ҏ(gu)有兴趣的朋友可以先?a >svn下蝲?/a>码尝鲜,有Q何改q的请发邮gl我。我的邮件地址在博客的右上角?br />
]]> HandlerSocket client for java——MySql as NoSQL http://www.aygfsteel.com/killme2008/archive/2010/11/30/339386.htmldennis dennis Tue, 30 Nov 2010 05:51:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/11/30/339386.html http://www.aygfsteel.com/killme2008/comments/339386.html http://www.aygfsteel.com/killme2008/archive/2010/11/30/339386.html#Feedback 4 http://www.aygfsteel.com/killme2008/comments/commentRss/339386.html http://www.aygfsteel.com/killme2008/services/trackbacks/339386.html
HandlerSocket 是日本h akira higuchi 写的一个MySql的插Ӟ通过q个插gQ你可以直接跟MySql后端的存储引擎做key-value式的交互Q省MMySql上层的SQL解释、打开关闭表、创建查询计划等CPU消耗型的开销Q按照作者给出的数据可以在数据全部在内存的情况下可以辑ֈ75W的QPS查询。具体信息可以看q篇Blog Q中文介l可以看q篇文章?a >HandlerSocket in action》?br />
q个东西Z么让我很Ȁ动呢Q首先性能是程序员的G点,一听高性能你不由地Ȁ动,其次Q这也解决了~存跟数据库的一致性问题,因ؓ~存在数据库里面,W三Q这个东西不仅仅是NoSQLQ简单的CRUD你可以通过HandlerSocketQ但是复杂的查询你仍然可以走MySqlQ完全符合我们应用的场景Qƈ且从实际试来看Q性能实非常优秀。但是呢Q这个东西的代h(hun)也少不了Q例如没有权限检查(未来可能dQ;不能启用MySql的查询缓存,否则会导致数据的不一_协议设计也不合理Q用\t做分隔符Q用\n做换行符Q那么你插入或者更新的字段数据׃能含有这些字W,否则行ؓ不如预期?/strike>
HandlerSocket 有一个日本h的java客户端实玎ͼ我去试了下Q结果发现这玩意完全不具实用性,装的层ơ非常原始。因此我自己写了个新的客LQ这是本文要介l的HandlerSocket Client for JavaQ简U?a >hs4jQ项目放在了googlecode Q代码的|络层复用xmemcachedQ重新实C协议和上层接口,目前的状态完全可用,也希望有需要的朋友参与试?br />
目地址Q?a >http://code.google.com/p/hs4j/
HS4J的用很单,所有的操作都通过HSClientq个接口q行Q如我们创徏一个客L对象Q?br />
import com.google.code.hs4j.HSClient;
import com.google.code.hs4j.impl.HSClientImpl;
HSClient hsClient = new HSClientImpl( new InetSocketAddress( 9999 ));
假设HandlerSocketq行在本地的9999端口Q默认的9998是只ȝQ?999才是允许d写。HSClient是线E安全的?br />
在执行操作前需要先open indexQ?br />
import com.google.code.hs4j.IndexSession;
IndexSession session = hsClient.openIndexSession(db, table,
" PRIMARY " , columns);
其中db是数据库?table是表名,"PRIMARY"表示使用主键索引Qcolumns是一个字W串数组代表你要查询的字D名U。这里没有指定indexidQ默认会产生一个indexidQ你也可以指定indexidQ返回表CZơopen-index会话对象QIndexSession同样是线E安全的?br />
IndexSession session = hsClient.openIndexSession(indexid,db, table,
" PRIMARY " , columns);
查询操作通过findҎ(gu):
import java.sql.ResultSet;
final String[] keys = { " dennis " , " killme2008@gmail.com " };
ResultSet rs = session.find(keys);
while (rs.next()){
String name = rs.getString( 1 );
String mail = rs.getString( 2 );
}
findq回的是java.sql.ResultSetQ你完全可以像用jdbc那样L作结果集。当然我的简单实现ƈ不符合JDBC规范Q只实现了最常见的一些方法,如getStrng、getLong{。find(keys)Ҏ(gu)默认使用的op?="。其他重载方法可以设|其他类型的opQ统一装为枚丄型FindOperator?br />
更新操作Q?br />
import com.google.code.hs4j.FindOperator;
int result = session.update(keys, new String[] { " 1 " , " dennis " ,
" test@163.com " , " 109 " }, FindOperator.EQ);
keys表示索引的字D列表对应的值数l,通过FindOperator.EQ比较q些值和索引Q第二个参数values表示要更新的字段|q些D你在open-index的时候传入的columns一一对应Q最后返回作用的记录数?br />
删除操作Q?br />
int result = session.delete( new String[] { " dennis " },
FindOperator.EQ)
HS4J同样支持q接池,可以在构建客L的时候传入连接池大小Q?br />
// 100-connections pool
HSClient hsClient = new HSClientImpl( new InetSocketAddress( 9999 ), 100 );
在open index的时候,会在q接池里所有的q接上都open。ƈ且在q接因ؓ意外情况Q如|络错误Q断开的时候,HS4J会自动重q,q在重连成功的情况下自动发送已lopen的indexQ保证应用的操作不受重连影响?br />
因ؓHS4J是我在两天内写就的一个东西,可能q有不少隐藏的bugQƈ且HandlerSocket本n也是个新东西Q如果有什么问题或者改q徏议,随时Ƣ迎告诉我,多谢?br />
]]> Java NIO trick and trap http://www.aygfsteel.com/killme2008/archive/2010/11/22/338420.htmldennis dennis Mon, 22 Nov 2010 10:22:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/11/22/338420.html http://www.aygfsteel.com/killme2008/comments/338420.html http://www.aygfsteel.com/killme2008/archive/2010/11/22/338420.html#Feedback 16 http://www.aygfsteel.com/killme2008/comments/commentRss/338420.html http://www.aygfsteel.com/killme2008/services/trackbacks/338420.html
上周在内部做的一个Java NIO框架的实现技巧和陷阱的分享,对编写NIO|络框架有兴的朋友可能有点帮助Q上传slideshare.net一直出错,直接提供下蝲吧?br />
下蝲地址Q?a href="http://www.aygfsteel.com/Files/killme2008/NIO%20trick%20and%20trap.pdf.zip">Nio Trick and Trap.pdf.zip
]]> 对kilim nio模块的改q?/title> http://www.aygfsteel.com/killme2008/archive/2010/11/19/338504.htmldennis dennis Fri, 19 Nov 2010 10:40:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/11/19/338504.html http://www.aygfsteel.com/killme2008/comments/338504.html http://www.aygfsteel.com/killme2008/archive/2010/11/19/338504.html#Feedback 3 http://www.aygfsteel.com/killme2008/comments/commentRss/338504.html http://www.aygfsteel.com/killme2008/services/trackbacks/338504.html
前段旉对kilim的当前版本做了一些改q,集中在nio调度器这一块。Kilim新版本引入了nio调度器,可以跟非dIOl合在一P从这个版本开始,kilim才真正具有实用性。协E只有跟非阻塞IOl合h才能发挥威力啊。但是Kilim的默认的nio调度器还只是使用一个nio worker做调度,q跟现有的NIO框架采用多个nio worker来提升效率比较v来相对落伍。我改进?a >NioSelectorSchedulerQ引入了cMNetty3的boss和woker的概念,boss负责q接接入Q而worker负责q接的IOdQƈ且默认设|worker数目为CPU个数的两倍。经q我的测试,改进后的NIO调度器的效率q远过了现有的调度器,有兴可以用netty的benchmark跑一下example里的EchoServer ?br />
Kilim默认q提供了一个简易Http Server框架Q但是没有提供Http Client的实玎ͼ我的另一个改q是提供了一个简易的Http Client实现Q也是利用Ragel做协议解析,一个简单的使用例子如下Q?br />
package kilim.examples;
import kilim.Pausable;
import kilim.Task;
import kilim.http.HttpClient;
import kilim.http.HttpResponse;
public class SimpleHttpClient {
static class SimpleTask extends Task {
@Override
public void execute() throws Pausable, Exception {
HttpClient client = new HttpClient();
HttpResponse resp = client.get( " http://www.google.com.hk/ " );
System.out.println(resp.status());
System.out.println(resp.content());
}
}
public static void main(String[] args) {
SimpleTask task = new SimpleTask();
task.start();
}
}
q个陋的HttpClient目前只支持GET/POSTQ同时支持Http chunk~码Q得益于kilim原有代码Q,做一些简单的HTTP调用已经_。我试在一个项目里使用q个HttpClientL代java默认的HttpURLConnectionQ效率有部分提升Q但是同时由于大量协E存在占用了很大部分的内存,lGC也带来了不小的压力?br />
我的代码直接从kilim的主qfork出来Q有兴趣可以直接git clone下来玩玩,地址 https://github.com/killme2008/kilim ]]> Kilim的小BUG http://www.aygfsteel.com/killme2008/archive/2010/11/03/337179.htmldennis dennis Wed, 03 Nov 2010 15:22:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/11/03/337179.html http://www.aygfsteel.com/killme2008/comments/337179.html http://www.aygfsteel.com/killme2008/archive/2010/11/03/337179.html#Feedback 2 http://www.aygfsteel.com/killme2008/comments/commentRss/337179.html http://www.aygfsteel.com/killme2008/services/trackbacks/337179.html
我最q在实现一个基于Kilim的HttpClientQ在处理响应body特别大的情Ş下遇Ckilim的一个BUGQ有必要记录下?br />
问题是这PKilim连接封装ؓEndPoint对象QEndPoint有个Ҏ(gu)fill用于从管道读数据到缓冲区Qƈ且可以指定希望至读到多个字节QatLeastN)才返回。那么在q入此方法的时候会判断~冲区是否有_I间容纳atLeastN个字节,如果没有Q则创徏一个更大的~冲区,q将“?#8221;的缓冲区的数据拷贝到新缓冲区Q这部分代码是这样实玎ͼ
public ByteBuffer fill(ByteBuffer buf, int atleastN) throws IOException, Pausable {
if (buf.remaining() < atleastN) {
ByteBuffer newbb = ByteBuffer.allocate(Math.max(buf.capacity() * 3 / 2 , buf.position() + atleastN));
buf.rewind();
newbb.put(buf);
buf = newbb;
}
……
}
后面的代码我省略了,q个BUG出现在q段代码里。这D代码的逻辑很简单,先是创徏一个新的更大的~冲区,然后老的~冲区的数据put到新的缓冲区Q在put之前调用rewindҎ(gu)老的~冲区的position讄?。查看rewindq了什么:
public final Buffer rewind() {
position = 0 ;
mark = - 1 ;
return this ;
}
仅仅是将position讄?Qƈ让mark失效。position指向下一个读或者写的位|,q里在写入到新缓冲区之前实需要将position讄?Q以便写入从老的~冲区第一个位|开始。问题是什么?问题是position仅仅指定了下一个读取数据的位置Q却没有指定有效数据的大,换句话说Q没有指定老的~冲区的limit。因此这里造成的后果是老的~冲区整个被写入到新的老缓冲区Q包括有效数据和无效数据Q默认情况下~冲区的limit{于capacity?br />
q个bug可以通过下面E序看出来:
ByteBuffer old = ByteBuffer.allocate( 8 );
old.putInt( 99 );
ByteBuffer newBuf = ByteBuffer.allocate( 16 );
old.rewind();
newBuf.put(old);
newBuf.putInt( 100 );
newBuf.flip();
System.out.println(newBuf.remaining());
System.out.println(newBuf.getInt());
System.out.println(newBuf.getInt());
System.out.println(newBuf.getInt());
先往old写入一个整?9Q然后创建newBufq写入old数据Qƈ再写入一个整?00Q最后从newBufL据。本来我们预期只应该d两个整数99?00Q但是中间却插入一?,输出如下Q?br />
12
99
0
100
12表示~冲区可ȝ数据Q本来应该是8个字节,却多?个字节的无效数据?br />
q个BUG解决很简单,rewind修改为flipҎ(gu)卛_Qflip不仅position讄?Q也limit讄为当前位|:
public final Buffer flip() {
limit = position;
position = 0 ;
mark = - 1 ;
return this ;
}
修改上面的测试程序,W合我们的预期了Q?br />
ByteBuffer old = ByteBuffer.allocate( 8 );
old.putInt( 99 );
ByteBuffer newBuf = ByteBuffer.allocate( 16 );
old.flip();
newBuf.put(old);
newBuf.putInt( 100 );
newBuf.flip();
System.out.println(newBuf.remaining());
System.out.println(newBuf.getInt());
System.out.println(newBuf.getInt());;
输出Q?br />
8
99
100
ȝQ用rewind的前提是limit已经正确讄Q例如你buffer写入成功q想记录q个bufferQ可以用rewind:
while (buffer.hasRemaining()) // 发送数?/span>
networkChannel.write(buffer);
buffer.rewind(); // 重置bufferQ准备写入日志管?/span>
while (buffer.hasRemaining()) // 写入日志
loggerChannel.write(buffer);
而flip用于~冲区发送或者读取之前,也就是将~冲|ؓ{待传出状态?br /> ]]> xmemcached 1.2.6.2紧急发布(升?.2.6.1的朋友注意) http://www.aygfsteel.com/killme2008/archive/2010/10/22/335897.htmldennis dennis Fri, 22 Oct 2010 07:52:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/10/22/335897.html http://www.aygfsteel.com/killme2008/comments/335897.html http://www.aygfsteel.com/killme2008/archive/2010/10/22/335897.html#Feedback 4 http://www.aygfsteel.com/killme2008/comments/commentRss/335897.html http://www.aygfsteel.com/killme2008/services/trackbacks/335897.html
今年在阅L个项目源码的时候看到DelayQueue的用,xmemcached 1.2.6.1的重qQ务也是采用DelayQueue理QReconnectRequest实现Delayed接口Q我H然惌v去review下xmc的源码,发现一个严重的BUGQ原始代码如下:
public final class ReconnectRequest implements Delayed {
public long getDelay(TimeUnit unit) {
return nextReconnectTimestamp - System.currentTimeMillis();
}
}
getDelayq回该Q务还剩下多少旉可以被执行,下ơ执行的旉戛_d前时间即可,问题在于q里q回的是毫秒Q而没有调用getDelay传入的TimeUnit做{换,在DelayQueue内部其实是用U秒做单位交lCondition对象ȝ?br />
for (;;) {
E first = q.peek();
if (first == null ) {
available.await();
} else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay > 0 ) {
long tl = available.awaitNanos(delay);
} else {
E x = q.poll();
assert x != null ;
if (q.size() != 0 )
available.signalAll(); // wake up other takers
return x;
}
}
}
最l导致的问题是,awaitNanos很快q回Q?/span>awaitNanos接受的是U秒Q这里却传入毫秒Q?/span>Q@环执行发现重新计的delay仍然大于0Q@环等到getDelayq回的越来越直?才执行相应的Task,Q造成的现象是在重q的时候cpu占用率很高?br />
单元试的时候没有发现这个问题,主要是因为功能正常,没有x资源消耗情况,因此惭愧地忽略了?br />
解决的办法很单,修改getDelayҎ(gu)卛_Q?br />
public long getDelay(TimeUnit unit) {
return unit.convert(
nextReconnectTimestamp - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
}
q个BUG比较严重Q已l升U?.2.6.1的朋友徏议马上升U到1.2.6.2Q用maven的朋友只要修改版本即可,没有使用maven的请?a >q里下蝲?br />
]]> Selector.wakeup实现注记 http://www.aygfsteel.com/killme2008/archive/2010/10/22/335861.htmldennis dennis Fri, 22 Oct 2010 02:35:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/10/22/335861.html http://www.aygfsteel.com/killme2008/comments/335861.html http://www.aygfsteel.com/killme2008/archive/2010/10/22/335861.html#Feedback 3 http://www.aygfsteel.com/killme2008/comments/commentRss/335861.html http://www.aygfsteel.com/killme2008/services/trackbacks/335861.html
NIO中的Selector装了底层的pȝ调用Q其中wakeup用于唤醒d在selectҎ(gu)上的U程Q它的实现很单,在linux上就是创Z个管道ƈ加入poll的fd集合Qwakeup是往道里写一个字节,那么d的pollҎ(gu)有数据可d立即q回。证明这一点很单,strace卛_知道Q?br />
public class SelectorTest {
public static void main(String[] args) throws Exception {
Selector selector = Selector.open();
selector.wakeup();
}
}
使用strace调用,只关心write的系l调?br />
sudo strace - f - e write java SelectorTest
输出Q?br />
Process 29181 attached
Process 29182 attached
Process 29183 attached
Process 29184 attached
Process 29185 attached
Process 29186 attached
Process 29187 attached
Process 29188 attached
Process 29189 attached
Process 29190 attached
Process 29191 attached
[pid 29181 ] write( 36 , " \1 " , 1 ) = 1
Process 29191 detached
Process 29184 detached
Process 29181 detached
有的同学说了Q怎么证明q个write是wakeupҎ(gu)调用的,而不是其他方法呢Q这个很好证明,我们多调用几ơ:
public class SelectorTest {
public static void main(String[] args) throws Exception {
Selector selector = Selector.open();
selector.wakeup();
selector.selectNow();
selector.wakeup();
selector.selectNow();
selector.wakeup();
}
}
修改E序调用三次wakeupQ心l的朋友肯定注意到我们还调用了两ơselectNowQ这是因为在两次成功的selectҎ(gu)之间调用wakeup多次都只做一ơ,Z昄3ơwriteQ这里就每次调用前select一下将前一ơ写入的字节dQ同h行上面的strace调用Q输出:
Process 29303 attached
Process 29304 attached
Process 29305 attached
Process 29306 attached
Process 29307 attached
Process 29308 attached
Process 29309 attached
Process 29310 attached
Process 29311 attached
Process 29312 attached
Process 29313 attached
[pid 29303 ] write( 36 , " \1 " , 1 ) = 1
[pid 29303 ] write( 36 , " \1 " , 1 ) = 1
[pid 29303 ] write( 36 , " \1 " , 1 ) = 1
Process 29313 detached
Process 29309 detached
Process 29306 detached
Process 29303 detached
果然?ơwrite的系l调用,都是写入一个字节,如果我们LselectNowQ那么三ơwakeupq是{于一ơ:
public class SelectorTest {
public static void main(String[] args) throws Exception {
Selector selector = Selector.open();
selector.wakeup();
selector.wakeup();
selector.wakeup();
}
}
输出Q?br />
Process 29331 attached
Process 29332 attached
Process 29333 attached
Process 29334 attached
Process 29335 attached
Process 29336 attached
Process 29337 attached
Process 29338 attached
Process 29339 attached
Process 29340 attached
Process 29341 attached
[pid 29331 ] write( 36 , " \1 " , 1 ) = 1
Process 29341 detached
Process 29337 detached
Process 29334 detached
Process 29331 detached
wakeupҎ(gu)的API说明没有ƺ骗我们。wakeupҎ(gu)的APIq告诉我们,如果当前Selector没有d在selectҎ(gu)上,那么本次wakeup调用会在下一ơselectd的时候生效,q个道理很简单,wakeupҎ(gu)写入一个字节,下次poll{待的时候立卛_现可dƈq回Q因此不会阻塞?br />
具体到源码别,在linuxq_上的wakeupҎ(gu)其实调用了pipe创徏了管道,wakeup调用?span id="cls">EPollArrayWrapper ?/span>interruptҎ(gu)Q?br />
public void interrupt()
{
interrupt(outgoingInterruptFD);
}
实际调用的是interrupt(fd)的nativeҎ(gu)Q查看EPollArrayWrapper.c可见清晰的writepȝ调用Q?br />
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv * env, jobject this , jint fd)
{
int fakebuf[ 1 ];
fakebuf[ 0 ] = 1 ;
if (write(fd, fakebuf, 1 ) < 0 ) {
JNU_ThrowIOExceptionWithLastError(env, " write to interrupt fd failed " );
}
}
写入一个字节的fakebuf。有朋友问vq个问题Q写个注记在此。strace充分利用对了解这些细节很有帮助?br />
]]> Xmemcached发布1.2.6.1Q推荐升U? http://www.aygfsteel.com/killme2008/archive/2010/10/17/335356.htmldennis dennis Sun, 17 Oct 2010 06:06:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/10/17/335356.html http://www.aygfsteel.com/killme2008/comments/335356.html http://www.aygfsteel.com/killme2008/archive/2010/10/17/335356.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/335356.html http://www.aygfsteel.com/killme2008/services/trackbacks/335356.html
Xmemcached 1.2.6.1正式发布Q这个版本的主要是做bug fix以及一些细节改q,主要变动如下Q?br />
1、修复BUGQ包括:
Issue 85 :
当存在多个MemcachedClient的时候,JMX的统计只昄其中一?br />
Issue 87 : 当用一致性哈希的时候,q接池不起作?br />
Issue 90 :
用户U程中断引v的连接关?/span>
Issue 94 :BinaryMemcachedClientUnitTest试p|
Issue 95 :
JMX addServer,removeServer存在~陷
Issue 96 :
OOM Error while decompressing 60 KB of actuall data
Issue 97 :
使得关闭q接更友?br />
2、改q重q机Ӟ重连不再是以固定间隔Q默?U)做重试连接,而是以一个等差数列递增间隔旉Q第一?U,W二?U,W三?U?#8230;…直到最大间隔时?分钟做重q尝试?br />
3、改善关闭机Ӟ关闭q接前发送quit命oQ尽量做到友好关闭,{待服务器主动断开q接?br />
4、添加新的方法用于设|XmemcachedClient实例名称Q用于区分不同的~存集群Q方便统计显C:
public interface MemcachedClient{
/**
* Return the cache instance name
*
* @return
*/
public String getName();
/**
* Set cache instance name
*
* @param name
*/
public void setName(String name);
}
名称也可通过spring配置?br />
5、提?a >英文的用h?/a>Q非常感?a >cnscud的帮助,q䆾文档是他一人搞定的?br />
6、更CJava Memcached Client Benchmark Q跟最新版本的spymemcached ,Java-Memcached-Client 做对比测试,提供l需要的朋友参考?br />
目首页 http://code.google.com/p/xmemcached/
下蝲地址 http://code.google.com/p/xmemcached/downloads/list
wiki地址 http://code.google.com/p/xmemcached/w/list
]]> Java Memcached Client Benchmark http://www.aygfsteel.com/killme2008/archive/2010/10/17/335351.htmldennis dennis Sun, 17 Oct 2010 05:44:00 GMT http://www.aygfsteel.com/killme2008/archive/2010/10/17/335351.html http://www.aygfsteel.com/killme2008/comments/335351.html http://www.aygfsteel.com/killme2008/archive/2010/10/17/335351.html#Feedback 0 http://www.aygfsteel.com/killme2008/comments/commentRss/335351.html http://www.aygfsteel.com/killme2008/services/trackbacks/335351.html
Xmemcached 1.2.6.1 releasedQ所以更C一?a >Java Memcached Client Benchmark。对比下Xmemached ,Spymemcached ?a >Java-Memcached-Clientq三个开源客L的性能Q具体的试信息可以看这?a >链接?br />
试源码
svn co http: // xmemcached.googlecode.com/svn/trunk/benchmark/
试l果Q?br />
svn co http: // xmemcached.googlecode.com/svn/trunk/benchmark/result
ȝ下测试结果,在选择和考察java memcached client 的朋友提供参考:
1?a >Java-Memcached-Client 2.5.1q个版本果然有很大改q,性能上有非常大的提升Q从试l果来看在小?00q发下有非常明显的优势,同时耗费资源也相对较多。但是在300q发讉K下,Java-Memcached-Client会不断地报错Q?br />
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11 : 09 : 05 GMT + 08 : 00 2010 - ++++ failed to get SockIO obj for : 10.232 . 36.82 : 12000
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11:09:05 GMT+08:00 2010 - ++++ failed to get SockIO obj for: 10.232.36.82:12000
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11:09:05 GMT+08:00 2010 - ++++ failed to get SockIO obj for: 10.232.36.90:12000
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11:09:05 GMT+08:00 2010 - ++++ failed to get SockIO obj for: 10.232.36.82:12000
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11:09:05 GMT+08:00 2010 - ++++ failed to get SockIO obj for: 10.232.36.90:12000
com.schooner.MemCached.SchoonerSockIOPool Sun Oct 17 11:09:05 GMT+08:00 2010 - ++++ failed to get SockIO obj for: 10.232.36.82:12000
q且无法正常地存取数据, 而xmc和spy却可以正常应对这一场景。因此可以看到在300q发下,Java-Memcached-Client试的结果直接ؓ0Q因为测试无法完成。尽我试最大连接数调到2000Q仍然是无法完成试?br />
2?a >Xmemcached无论在低q发q是高ƈ发访问的情况下,都可以保持一个比较优U的性能表现Q从xmc和spy的对比来看,xmc的优势相当大?br />
3?strong>从用户选择角度来说Q如果你的应用对memached的访问负载ƈ不高QJava-Memcached-Client是一个不错的选择Q但是在高峰讉K的时候可能命中率会有个急剧的L动;如果你的应用讉Kmemached的负载较高,此时我推荐你选择xmemcached Q如果你需要异步的扚w处理(future模式Q,可以选择spymemcached Q如果你不知道你的应用是什么状况,我推荐你?a >xmemcachedQ可以在M情况下获得一个比较好的性能表现?br />
]]>
վ֩ģ壺
ˮ |
|
Ϫ |
|
ͤ |
|
|
|
|
|
|
ʡ |
ԣ |
¬ |
ɽ |
|
ɽ |
|
˳ |
|
|
|
˫ |
|
Ȫ |
̨ |
|
ͷ |
|
|
|
Զ |
ɽ |
|
|
Ȫ |
|
|
|
· |
|