??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-庄周梦蝶http://www.ymeg.top/killme2008/生活、程序、未?/description>zh-cnMon, 19 Aug 2019 12:24:53 GMTMon, 19 Aug 2019 12:24:53 GMT60博客搬迁http://www.ymeg.top/killme2008/archive/2012/12/10/392701.htmldennisdennisSun, 09 Dec 2012 17:24:00 GMThttp://www.ymeg.top/killme2008/archive/2012/12/10/392701.htmlhttp://www.ymeg.top/killme2008/comments/392701.htmlhttp://www.ymeg.top/killme2008/archive/2012/12/10/392701.html#Feedback6http://www.ymeg.top/killme2008/comments/commentRss/392701.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/392701.html很久没有更新博客Q没惛_更新是搬q公告。这个博客篏计的讉K量突破百万,是我建立的时候完全没有想q的事情。博客对我来说更多是记录、记忆的地方Q我时常因ؓ想不h个东西,来翻自己的博客,查找旧知Q发现新知。阅d多h的博客,也是我跟t、学习新知的主要方式。虽然微博兴P不过博客作ؓ更系l性的记录的地方,不会q时?br />
非常感谢blogjava提供q么优秀的^台。只是我今年l自q一个目标是建立自己的博客,因此现在要搬q,加上其实现在也写的少Q其实搬q不搬迁Q意义也不大了。算是一个通告Q有兴趣的可以订阅我的新博客Q没兴趣的请自行略过Q谢谢大家?br />
新博客地址Q?a href="http://blog.fnil.net/">http://blog.fnil.net/
RSS地址Q?a href="http://blog.fnil.net/index.php/feed">http://blog.fnil.net/index.php/feed

新博客的W一记忆是?a href="http://blog.fnil.net/index.php/archives/14">Leiningen教程中文?/a>》,从现在开始,q个博客不再发布Q何新的文章,已有的也不会删除Q部分可能会导到我的知识库上厅R?br />
最后,福blogjava办好?br />

dennis 2012-12-10 01:24 发表评论
]]>
Another URL Shortener using NodeJShttp://www.ymeg.top/killme2008/archive/2012/11/25/391936.htmldennisdennisSun, 25 Nov 2012 12:31:00 GMThttp://www.ymeg.top/killme2008/archive/2012/11/25/391936.html
Is is written in NodeJS,using express.js for MVC framework,and using MySQL for storage and Redis for caching.

A demo online: http://fnil.me/

The project is at https://github.com/killme2008/node-shorten

Feel free to modify and use it.Have fun.

dennis 2012-11-25 20:31 发表评论
]]>
Clojure中文专业技术社?/title><link>http://www.ymeg.top/killme2008/archive/2012/09/25/388498.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 25 Sep 2012 04:51:00 GMT</pubDate><guid>http://www.ymeg.top/killme2008/archive/2012/09/25/388498.html</guid><wfw:comment>http://www.ymeg.top/killme2008/comments/388498.html</wfw:comment><comments>http://www.ymeg.top/killme2008/archive/2012/09/25/388498.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.ymeg.top/killme2008/comments/commentRss/388498.html</wfw:commentRss><trackback:ping>http://www.ymeg.top/killme2008/services/trackbacks/388498.html</trackback:ping><description><![CDATA[很久没写博客Q一是工作忙Q二是没有太多的事情可说?br /><br />最q在公司大{的支持下Q徏立了一个Clojure语言中文斚w的博客和问答|站Q欢qQ何对Clojureq门ZJVM之上的函数式语言感兴的童鞋贡献原创文章或者资料,甌帐号L<a href="http://blog.clojure.cn/?page_id=8">q里</a>?br /><br />博客地址Q? <a href="http://blog.clojure.cn/">http://blog.clojure.cn/</a><br />问答|站Q? <a href="http://ask.clojure.cn/" title="http://ask.clojure.cn/">http://ask.clojure.cn/</a><br /><br />Ƣ迎转发和注册用,谢谢?br /><br />邮g列表仍然使用google groupQ?a href="https://groups.google.com/group/cn-clojure/">https://groups.google.com/group/cn-clojure/</a><img src ="http://www.ymeg.top/killme2008/aggbug/388498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.ymeg.top/killme2008/" target="_blank">dennis</a> 2012-09-25 12:51 <a href="http://www.ymeg.top/killme2008/archive/2012/09/25/388498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ring.velocity:render velocity templates for ring in clojurehttp://www.ymeg.top/killme2008/archive/2012/07/18/383354.htmldennisdennisTue, 17 Jul 2012 16:07:00 GMThttp://www.ymeg.top/killme2008/archive/2012/07/18/383354.htmlhttp://www.ymeg.top/killme2008/comments/383354.htmlhttp://www.ymeg.top/killme2008/archive/2012/07/18/383354.html#Feedback0http://www.ymeg.top/killme2008/comments/commentRss/383354.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/383354.htmlHome: https://github.com/killme2008/ring.velocity

A Clojure library designed to render velocity template for ring in clojure.

Usage

Adds dependency in leiningen project.clj:

  [ring.velocity "0.1.0-SNAPSHOT"] 

Create a directory named templates in your project directory to keep all velocity templates.

Create a template templates/test.vm:

  hello,$name,your age is $age. 

Use ring.velocity in your namespace:

  (use '[ring.velocity.core :only [render]]) 

Use render function to render template with vars:

  (render "test.vm" :name "dennis" :age 29) 

The test.vm will be interpreted equals to:

  hello,dennis,your age is 29. 

Use ring.velocity in compojure:

  (defroutes app-routes      
(GET "/" [] (render "test.vm" :name "dennis" :age 29))
(route/not-found "Not Found"))

Use ring.velocity in ring:

  (use '[ring.util.response])   
(response (render "test.vm" :name "dennis" :age 29))

Custom velocity properties,just put a file named ring-velocity.properties to your classpath or resource paths.The default velocity properties is in src/default/velocity.properties.

License

Copyright © 2012 dennis zhuang[killme2008@gmail.com]

Distributed under the Eclipse Public License, the same as Clojure.

Home: https://github.com/killme2008/ring.velocity



dennis 2012-07-18 00:07 发表评论
]]>
ClojureW记Q用好type hinthttp://www.ymeg.top/killme2008/archive/2012/07/10/382738.htmldennisdennisTue, 10 Jul 2012 12:37:00 GMThttp://www.ymeg.top/killme2008/archive/2012/07/10/382738.htmlhttp://www.ymeg.top/killme2008/comments/382738.htmlhttp://www.ymeg.top/killme2008/archive/2012/07/10/382738.html#Feedback1http://www.ymeg.top/killme2008/comments/commentRss/382738.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/382738.html     Clojure的一大优点就是跟Java语言的完配合,Clojure和Java之间可以怺调用QClojure可以天然C用Javaq_上的丰富资源。在Clojure里调用一个类的方法很单,利用dot操作W:

user=> (.substring "hello" 3)
"lo"
user=> (.substring "hello" 0 3)
"hel"

    上面的例子是在clojure里调用String的substringҎ做字W串截取。Clojure虽然是一门弱cd的语aQ但是它的Lisp Readerq是能识别大多数常见的类型,比如q里hello是一个字W串可以识别出?3是一个整C可以Q通过q些cd信息可以扑ֈ最匚w的substringҎQ在生成字节码的时候避免用反,而是直接调用substringҎQINVOKEVIRTUAL指oQ?br />
    但是当你在函数里调用cL法的时候,情况变了,例如Q定义substr函数Q?br />
(defn substr [s begin end] (.substring s begin end))

    我们打开*warn-on-reflection*选项Q当有反的时候告警:

user=> (set! *warn-on-reflection* true)
true
user=> (defn substr [s begin end] (.substring s begin end))
Reflection warning, NO_SOURCE_PATH:22 - call to substring can't be resolved.
#'user/substr
   
    问题出现了,׃函数substr里没有Q何关于参数s的类型信息,Z调用s的substringҎQ必M用反来调用Qclojure~译器也警告我们调用substring没办法解析,只能通过反射调用。众所周知Q反调用是个相Ҏ늚操作Q对比于普通的Ҏ调用有)。这一切都是因为clojure本n是弱cd的语aQ对参数或者返回g不需要声明类型而直接?Clojure会自动处理类型的转换和调用。ps.?a href="https://github.com/technomancy/leiningen">leiningen里启用反警告很单,在project.clj里设|:

;; Emit warnings on all reflection calls.
  :warn-on-reflection true
   
q多的反调用会影响效率Q有没有办法避免q种情况呢?有的QClojure提供了type hint机制Q允许我们帮助编译器来生成更高效的字节码。所谓type hint是l参数或者返回值添加一个提C:hi,clojure~译器,q是xxxcdQ我惌用它的yyyҎQ请生成最高效的调用代码,谢谢合作Q?br />
user=> (defn substr [^String s begin end] (.substring s begin end))
#'user/substr
     
    q次没有警告Q^String是参数s的type hintQ提Cclojure~译器说s的类型是字符Ԍ那么clojure~译器会从java.lang.Stringc里查找名称为substringq且接收两个参数的方?/strong>Qƈ利用invokevirtual指o直接调用此方法,避免了反调用。除了target对象Q这里的s)可以dtype hintQ方法参数和q回g可以dtype hintQ?br />
user=> (defn ^{:tag String} substr [^String s ^Integer begin ^Integer end] (.substring s begin end))
#'user/substr
    
    q回值添加type hint是利用tag元数据,提示substr的返回类型是StringQ其他函数在使用substr的时候可以利用这个类型信息来避免反射Q而参数的type hint跟target object的type hint一样以^开头加上类型,例如q里begin和end都提C是Integercd?br />
    问题1Q什么时候应该ؓ参数dtype hint呢?我的观点是,在Q何ؓtarget objectdtype hint的地方,都应该相应地为参数添加type hintQ除非你事先不知道参数的cd?/strong>Z么呢Q因为clojure查找cL法的序是这P

1.从Stringc里查找出所有参CCؓ2q且名称为substringҎ
2.遍历W一步里查找出来的MethodQ如果你有设|参数的type hint,?
查找最匚w参数cd的MethodQ否则,如果W一步查扑և来的Method׃个,直接使用q个MethodQ相反就认ؓ没有扑ֈ对应的Method?br /> 3.如果W二步没有找到MethodQ用反调用;否则Ҏ该Method元信息生成调用字节码?br />
   因此Q如果substringҎ的两个参数版本刚好就一个,Ҏ参数有没有type hint都没有关p(有了错误的type hint反而促使反的发生Q,我们都会扑ֈq个唯一的方法;但是如果目标Ҏ的有多个重蝲Ҏq且参数相同Q而只是参数类型不同(Java里是允许Ҏ的参数类型重载的QClojure只允许函数的参数个数重蝲Q,那么如果没有Ҏ参数的type hintQClojure~译器仍然无法找到合适的调用ҎQ而只能通过反射?br />    
   看一个例?定义get-bytesҎ调用String.getBytesQ?br />
user=> (defn get-bytes [s charset] (.getBytes s charset))
Reflection warning, NO_SOURCE_PATH:26 - call to getBytes can't be resolved.
#'user/get-bytes
user=> (defn get-bytes [^String s charset] (.getBytes s charset))
Reflection warning, NO_SOURCE_PATH:27 - call to getBytes can't be resolved.
#'user/get-bytes

    W一ơ定义,s和charset都没有设|type hintQ有反射警告Q第二次Qs讄了type hintQ但是还是有反射警告。原因就在于String.getBytes有两个重载方法,参数个数都是一个,但是接收不同的参数类型,一个是String的charset名称Q一个Charset对象。如果我们明地知道q里charset是字W串Q那么还可以为charsetdtype hint:
user=> (defn get-bytes [^String s ^String charset] (.getBytes s charset))
#'user/get-bytes
   
    q次才真正的没有警告了。ȝQ在讄type hint的时候,不要只考虑被调用的target objectQ也要考虑调用的方法参数?br />
    问题2Q什么时候应该添加tag元数据呢Q理ZQ在M你明知道返回类型的地方都应该添加tagQ但是这不是教条Q如果一个偶被调用的方法是无需q样做的。这一点只对写库的童鞋要特别注意?br />
    Type hint的原理在上文已经大概描述了下Q具体到clojure源码U别Q请参考clojure.lang.Compiler.InstanceMethodExprcȝ构造函数和emitҎ。最后,附送是否用type hint生成substr函数的字节码之间的差异对比:
未用type hint 使用type hint

  // access flags 1

  public invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

   L0

    LINENUMBER 14 L0

   L1

    LINENUMBER 14 L1

    ALOAD 1

    ACONST_NULL

    ASTORE 1

    LDC "substring"

    ICONST_2

    ANEWARRAY java/lang/Object

    DUP

    ICONST_0

    ALOAD 2

    ACONST_NULL

    ASTORE 2

    AASTORE

    DUP

    ICONST_1

    ALOAD 3

    ACONST_NULL

    ASTORE 3

    AASTORE

    INVOKESTATIC clojure/lang/Reflector.invokeInstanceMethod (Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;

   L2

    LOCALVARIABLE this Ljava/lang/Object; L0 L2 0

    LOCALVARIABLE s Ljava/lang/Object; L0 L2 1

    LOCALVARIABLE begin Ljava/lang/Object; L0 L2 2

    LOCALVARIABLE end Ljava/lang/Object; L0 L2 3

    ARETURN

    MAXSTACK = 0

    MAXLOCALS = 0

public invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

   L0

    LINENUMBER 15 L0

   L1

    LINENUMBER 15 L1

    ALOAD 1

    ACONST_NULL

    ASTORE 1

    CHECKCAST java/lang/String

    ALOAD 2

    ACONST_NULL

    ASTORE 2

    CHECKCAST java/lang/Number

    INVOKESTATIC clojure/lang/RT.intCast (Ljava/lang/Object;)I

    ALOAD 3

    ACONST_NULL

    ASTORE 3

    CHECKCAST java/lang/Number

    INVOKESTATIC clojure/lang/RT.intCast (Ljava/lang/Object;)I

    INVOKEVIRTUAL java/lang/String.substring (II)Ljava/lang/String;

   L2

    LOCALVARIABLE this Ljava/lang/Object; L0 L2 0

    LOCALVARIABLE s Ljava/lang/Object; L0 L2 1

    LOCALVARIABLE begin Ljava/lang/Object; L0 L2 2

    LOCALVARIABLE end Ljava/lang/Object; L0 L2 3

    ARETURN

    MAXSTACK = 0

    MAXLOCALS = 0


    
    Ҏ很明显,没有使用type hintQ调用clojure.lang.Reflector的invokeInstanceMethodҎQ用反调用(具体见clojure.lang.Reflector.java)Q而用了type hint之后Q则直接使用invokevirtual指oQ其他方法可能是invokestatic或者invokeinterface{指令)调用该方法,避免了反?br />       

    参考:


dennis 2012-07-10 20:37 发表评论
]]>
Clojure世界Q利用HouseMD诊断clojurehttp://www.ymeg.top/killme2008/archive/2012/06/15/380822.htmldennisdennisThu, 14 Jun 2012 18:52:00 GMThttp://www.ymeg.top/killme2008/archive/2012/06/15/380822.htmlhttp://www.ymeg.top/killme2008/comments/380822.htmlhttp://www.ymeg.top/killme2008/archive/2012/06/15/380822.html#Feedback2http://www.ymeg.top/killme2008/comments/commentRss/380822.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/380822.html     HouseMD是淘宝的聚石写的一个非怼U的Javaq程q行时诊断和调试工具Q如果你接触qbtraceQ那么HouseMD也许你应该尝试下Q它比btrace更易用,不需要写脚本Q类似strace的方式attach到jvmq程做跟t调试?br />
    基本的安装和使用Lq篇文档?a href="https://github.com/zhongl/HouseMD/wiki/UserGuideCN">UserGuide》,恕不重复。以下内定w假设你正安装了housemd?br />
    本文主要介绍下怎么用housemd诊断跟踪clojureq程。Clojure的java实现也是跑在JVM里,当然也可以用housemd?br />
    我们以一个简单的例子开始,假设我们有如下clojure代码Q?br />
(loop [x 1]
  (Thread/sleep 1000)
  (prn x)
  (recur (inc x)))

    q段很简单,只是间隔一U不断地打印递增的数字x。我们准备用housemd跟踪q个E序的运行,首先q行q个E序Q你可以用leinQ也可以直接java命oq行Q?br />
java -cp clojure.jar clojure.main test.clj

    q行时不断地在控制台打印数字Q通过jps或者ps查询到该q程的idQ假设ؓpidQ用housemdq接到该q程Q?br />
housemd <pid>
    利q入housemd的交互控制台Q通过help命o可以查询支持的命令:

housemd> help

quit      terminate the process.
help      display this infomation.
trace     display or output infomation of method invocaton.
loaded    display loaded classes information.

    要用housemd调试clojureQ你需要对clojure的实现有一点点了解Q有兴趣可以看过ȝ一blog?a href="http://www.ymeg.top/killme2008/archive/2010/07/11/325775.html">clojure hacking guide》,单来_clojure的编译器会将clojure代码~译成javacdƈq行。对于JVM来说Qclojure生成的类Q跟java~译器生成类没有什么不同?br />     具体C面的clojure代码Q会生成一个名?strong>user$eval1
的类Quser是默认的namespaceQ而eval1是clojure~译器自动生成的一个标C类名,通过loaded命o查询cȝ加蝲情况Q?br />
housemd> loaded user$eval1 -h
user$eval1 -> null
    - clojure.lang.DynamicClassLoader@1d25d06e
        - clojure.lang.DynamicClassLoader@1d96f4b5
            - sun.misc.Launcher$AppClassLoader@a6eb38a
                - sun.misc.Launcher$ExtClassLoader@69cd2e5f

    通过-h选项打印了加载user$eval1的类加蝲器的层次关系Q因为user$eval1是动态生成的Qclojure启动q程中)Q因此它不在M一个class或者jar文g中。除了查询user namespace的类之外Q你q可以查询clojure.core,clojure.lang,clojure.java{Q何被加蝲q来的类Q例如查询clojure.core.prn的类,在clojure里这是一个函敎ͼ在jvm看来q只是一个类Q?br />
housemd> loaded -h core$prn
clojure.core$prn -> /Volumes/HDD/Users/apple/clojure/clojure.jar
    - sun.misc.Launcher$AppClassLoader@a6eb38a
        - sun.misc.Launcher$ExtClassLoader@69cd2e5f
   注意Q不需要完整的namespace——clojure.coreQ直接core$prn卛_。其他也是类伹{?strong>技巧:如果你实在不知道clojure~译器生成的cdQ你可以利用jvm自带的jmap命o来查询?/strong>

   接下来,我们试用trace命o跟踪Ҏ的运行,例如例子中的clojure代码用到了loop和recur两个sepcial formQ我们跟t下loop:
housemd> trace -t 5 core$loop
INFO : probe class clojure.core$loop
core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

INFO : Ended by timeout
INFO : reset class clojure.core$loop

    ?U内Qclojure.core$loopcL两个Ҏ各被调用?ơ,doInvoke是实际的调用Q而getRequiredArity用来查询loop所需要的参数个数。traceq可以跟t到具体的方法,例如我们跟踪prn函数的调用情况:
housemd> trace -t 5 core$prn.doInvoke
INFO : probe class clojure.core$prn
core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            1            1ms    clojure.core$prn@3e4ac866

core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            2           <1ms    clojure.core$prn@3e4ac866

core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            3           <1ms    clojure.core$prn@3e4ac866

core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            4           <1ms    clojure.core$prn@3e4ac866

core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            5           <1ms    clojure.core$prn@3e4ac866

INFO : Ended by timeout
INFO : reset class clojure.core$prn
  
   trace打印了方法的调用ơ数Q?U内Q和每次调用的时_毫秒U别Q,以及调用的target object。小技巧:没有可变参数的函数生成类最l调用的是invokeҎQ参C数可能重载)Q有可变参数的函数调用的是doInvokeҎ?br />
   trace命oq支持打印调用堆栈到文gQ例如:
trace -t 5 -d -s  core$prn.doInvoke

   利用-s?d命o会将详细的调用信息输出到临时目录Q时目录的路径可以通过trace help命o查询刎ͼ在我的机器上?tmp/trace/<pid>@host目录下。调用堆栈的输出cMQ?br />
example$square.invoke(Long) call by thread [main]
    example$eval9.invoke(test.clj:11)
    clojure.lang.Compiler.eval(Compiler.java:6465)
    clojure.lang.Compiler.load(Compiler.java:6902)
    clojure.lang.Compiler.loadFile(Compiler.java:6863)
    clojure.main$load_script.invoke(main.clj:282)
    clojure.main$script_opt.invoke(main.clj:342)
    clojure.main$main.doInvoke(main.clj:426)
    clojure.lang.RestFn.invoke(RestFn.java:421)
    clojure.lang.Var.invoke(Var.java:405)
    clojure.lang.AFn.applyToHelper(AFn.java:163)
    clojure.lang.Var.applyTo(Var.java:518)
    clojure.main.main(main.java:37)

   上面q个单的例子展示了用housemd跟踪诊断clojureq程的方法?br />
   自定义ns和函数的调试与此cMQ假设我们有下面的clojure代码Q?br />
(ns example)
(defn square [x]
  (* x x))

(loop [x 1]
  (Thread/sleep 1000)
  (square x)
  (recur (inc x)))
 
   ns为exampleQ自定义函数squareq定期@环调用。用housemd诊断q段代码Q?br />
loaded -h example$square     #查询square的加载情?br />trace -t 10 -d -s example$square.invoke  #跟踪10U内square的调用情?/div>

dennis 2012-06-15 02:52 发表评论
]]>分布式消息中间gMetaq发布1.4.3http://www.ymeg.top/killme2008/archive/2012/06/04/379895.htmldennisdennisMon, 04 Jun 2012 02:03:00 GMThttp://www.ymeg.top/killme2008/archive/2012/06/04/379895.htmlhttp://www.ymeg.top/killme2008/comments/379895.htmlhttp://www.ymeg.top/killme2008/archive/2012/06/04/379895.html#Feedback1http://www.ymeg.top/killme2008/comments/commentRss/379895.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/379895.html我们在维护的淘宝开源消息中间g?a href="http://metaq.taobao.org/" style="color: #006699; ">metaq?a href="https://github.com/killme2008/Metamorphosis" style="color: #006699; ">github分支Q今天发布了1.4.2版本Q主要做了如下改q:

1.支持发送和订阅分离Q可以细_度地控制Broker或者某个Topic是否接收消息和接受订阅。服务端d新选项acceptPublish和acceptSubscribe?br />
2.更友好地关闭BrokerQ梳理关闭流Eƈ通过JMX调用Ҏ关闭替代原来单的kill?br />
3.更新python客户?/a>?.2版本Q可以通过pip安装:  pip install metaq

4.发布ruby语言客户?a href="https://github.com/killme2008/Metamorphosis/tree/master/contrib/ruby/meta-ruby" style="color: #006699; ">meta-ruby
 0.1版本?br />
5.其他改q:升gecko?.1.1版本Q升Uquartz?.1.4版本Q添加集成测试工E和内部重构{?br />
6.新文?a href="https://github.com/killme2008/Metamorphosis/wiki/%E4%BD%BF%E7%94%A8Log4j%E6%89%A9%E5%B1%95%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF">《用log4j扩展发送消息?/a>

介:https://github.com/killme2008/Metamorphosis/wiki/介绍
下蝲Q?a href="https://github.com/killme2008/Metamorphosis/downloads" style="color: #006699; ">https://github.com/killme2008/Metamorphosis/downloads

文档Q?a href="https://github.com/killme2008/Metamorphosis/wiki" style="color: #006699; ">https://github.com/killme2008/Metamorphosis/wiki



dennis 2012-06-04 10:03 发表评论
]]>
如何熟悉一个开源项目?http://www.ymeg.top/killme2008/archive/2012/05/22/378885.htmldennisdennisTue, 22 May 2012 15:12:00 GMThttp://www.ymeg.top/killme2008/archive/2012/05/22/378885.htmlhttp://www.ymeg.top/killme2008/comments/378885.htmlhttp://www.ymeg.top/killme2008/archive/2012/05/22/378885.html#Feedback9http://www.ymeg.top/killme2008/comments/commentRss/378885.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/378885.html    你有个Q务,需要用到某个开源项?或者老大交代你一个事情,让你M解某个东ѝ怎么下手呢?如何开始呢Q我的习惯是q样Q?br />
1.首先Q查扑֒阅读该项目的博客和资料,通过google你能扑ֈ某个目大体介绍的博客,快速阅M下就能对目的目的、功能、基本用有个大概的了解?br />
2.阅读目的文档,重点xcMGetting started、Example之类的文档,从中学习如何下蝲、安装、甚臛_本用该目所需要的知识?br />
3.如果该项目有提供现成的example工程Q首先尝试按照开始文档的介绍q行exampleQ如果运行顺利,那么恭喜你顺利开了个好头;如果遇到问题Q首先尝试在目?strong>FAQ
{文档里查找{案Q再ơ,可以问题(例如异常信息Q当成关键词L索,查找相关的解军_法,你遇CQ别Z般也会遇刎ͼ热心的朋友会记录下解决的q程;最后,可以问题提交到目的邮件列表,请大家帮你看看?strong>在没有成功运行example之前Q不要尝试修改example?br />
4.q行了第一个example之后Q尝试根据你的理解和需要修改exampleQ测试高U功能等?br />
5.在了解基本用后Q需要开始深入的了解该项目。例如项目的配置理、高U功能以及最佛_c通常一个运作良好的目会提供一份从到q用户指南Q你q不需要从头到N读这份指南,Ҏ旉和兴,特别是你自己d的需要,重点阅读部分章节q做W记Q推荐evernoteQ?br />
6.如果旉允许Q尝试从源码构徏该项目。通常开源项目都会提供一份构建指南,指导你如何搭Z个用于开发、调试和构徏的环境。尝试构Z个版本?br />
7.如果旉允许q且有兴,可以试阅读源码Q?br />Q?Q阅L码之前,查看该项目是否提供架构和设计文档Q阅读这些文档可以了解该目的大体设计和l构Q读源码的时候不会无从下手?br />Q?Q阅L码之前,一定要能构建ƈq行该项目,有个直观感受?br />Q?Q阅L码的W一步是抓主qԌ试理清一ơ正常运行的代码调用路径Q这可以通过debug来观察运行时的变量和行ؓ。修Ҏ码加入日志和打印可以帮助你更好的理解源码?br />Q?Q适当d来帮助你理解源码Q在理清d后,可以整个流E画成一张流E图或者标准的UML图,帮助记忆和下一步的阅读?br />Q?Q挑选感兴趣?#8220;枝干”代码来阅读,比如你对|络通讯感兴,阅ȝl层的代码,深入到实现细节,如它用了什么库Q采用了什么设计模式,Z么这样做{。如果可以,debugl节代码?br />Q?Q阅L码的时候,重视单元试Q尝试去q行单元试Q基本上一个好的单元测试会该代码的功能和边界描述清楚?br />Q?Q在熟悉源码后,发现有可以改q的地方Q有_֊、有意愿可以向该目的开发者提出改q的意见或者issueQ甚臛_他修复和实现Q参与该目的发展?br />
8.通常在阅L档和源码之后Q你能对该项目有比较深入的了解了Q但是该目所在领域,你可能还x索相关的目和资料,看看有没有其他的更好的项目或者解x案。在q度和深度之间权衡?br />
    以上是我个h的一些习惯,我自׃q没有完全按照这个来Q但是按照这个顺序,基本上能让你比较高效地学习和使用某个开源项目?img src ="http://www.ymeg.top/killme2008/aggbug/378885.html" width = "1" height = "1" />

dennis 2012-05-22 23:12 发表评论
]]>Emacs + Clojure配置的几个Tiphttp://www.ymeg.top/killme2008/archive/2012/05/19/378535.htmldennisdennisFri, 18 May 2012 16:57:00 GMThttp://www.ymeg.top/killme2008/archive/2012/05/19/378535.htmlhttp://www.ymeg.top/killme2008/comments/378535.htmlhttp://www.ymeg.top/killme2008/archive/2012/05/19/378535.html#Feedback11http://www.ymeg.top/killme2008/comments/commentRss/378535.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/378535.html     很久没更新博客了Q在北京工作Q忙ƈ且充实。目前来_Clojure最好的开发编辑器应该是Emacs + Slime的组合,利用swank-clojureq个目Q加上clojure-modeQ可以完地q行slime。编译、运行、蟩转、文档和引用查看甚至debug都可以搞定。具体配|恕不重复,看swank-clojure的文档即可自己安装v来,或者这?a href="http://sunng.info/blog/2011/09/beginning-emacs-for-clojure/">中文博客Q?a href="http://www.cnblogs.com/darkluck99/archive/2012/02/20/2360216.html">windows上配|?/a>?br />
    分n几个TipQ也期待大家分n你们的用心得?br />
    首先是自动在打开clj后缀文g的时候启动执行clojure-jack-in与slimeq接Q可以在emacs配置里加上个callbackQ?br />
(eval-after-load "clojure-mode"
  '(progn
     (require 'slime)
     (require 'clojure-mode)
     (unless (slime-connected-p)
       (save-excursion (clojure-jack-in)))))
    q样在打开clj为后~的文件的时候,自动启动clojure-mode执行clojure-jack-in函数q且q接slime?br />
    clj后缀的文件自动关联到clojure-mode:
(setq auto-mode-alist (cons '("\\.clj$" . clojure-mode) auto-mode-alist))
    通常来说如果你是利用marmalade安装的,会自动关联的?br />
    另外Q启动自动匹配括受字W串引号{的paredit模式一定要启动Q?br />
(defun paredit-mode-enable () (paredit-mode 1))
(add-hook 'clojure-mode-hook 'paredit-mode-enable)
(add-hook 'clojure-test-mode-hook 'paredit-mode-enable)

   在用clojure-mode或者clojure-test-mode的时候自动启用paredit模式Q括号再也不是问题。括号匹配提CZ般是开启的Q如果没有,强制开启:

;;    昄括号匚w
(show-paren-mode t)
(setq show-paren-style 'parentheses)

    slime更多配置Q启用IO重定向(多线EIO输出都定向到SLIME replQ以及设|通讯字符~码{:

(eval-after-load "slime"
  '(progn
     (slime-setup '(slime-repl slime-fuzzy))
     ;;(setq slime-truncate-lines t)
     (setq  swank:*globally-redirect-io*  t)
     ;; (setq slime-complete-symbol-function ' slime-fuzzy-complete-symbol)
     (setq slime-net-coding-system 'utf-8-unix)))

    l心的朋友可能注意到我注释了slime-fuzzy-complete的配|,q是一个支持更好的自动补全功能的SLIME插gQ可以用~写来自动补全)Q可惜在我机器上没有试配置成功Q有兴趣你可以尝试下?br />
    在REPL里支持语法高亮,一定要配置上:

(add-hook 'slime-repl-mode-hook
          (defun clojure-mode-slime-font-lock ()
            (require 'clojure-mode)
            (let (font-lock-mode)
              (clojure-mode-font-lock-setup))))

    单独在clojure-modeQ在其他mode里这些快捷键不会起作用)里配|快捷键可以q样:
(eval-after-load "clojure-mode"
  '(progn
     (require 'slime)
     (require 'clojure-mode)
     (define-key clojure-mode-map (kbd "M-/")  (quote slime-complete-symbol))
     (define-key clojure-mode-map (kbd "C-c s")  (quote slime-selector)))

   例如我这里将M-/作ؓ自动补全的快捷键Q因为meta键在我的Mac机器上设|ؓcommand键,因此自动补全的操作习惯就跟EclipsecM。?strong>slime-selector是一个非常有用的函数Q用来蟩转到slime的一pdbufferQ因此我l定了C-c s快捷键?br />
    额外一提,在Mac osx下,command作ؓmeta?
;;; I prefer cmd key for meta
(setq mac-option-key-is-meta nil
      mac-command-key-is-meta t
      mac-command-modifier 'meta
      mac-option-modifier 'none)

    最后,期待大家不吝分n你的心得?br />    

dennis 2012-05-19 00:57 发表评论
]]>
clj.monitor : monitoring applications in clojure based on SSHhttp://www.ymeg.top/killme2008/archive/2012/05/12/378018.htmldennisdennisSat, 12 May 2012 14:38:00 GMThttp://www.ymeg.top/killme2008/archive/2012/05/12/378018.htmlhttp://www.ymeg.top/killme2008/comments/378018.htmlhttp://www.ymeg.top/killme2008/archive/2012/05/12/378018.html#Feedback5http://www.ymeg.top/killme2008/comments/commentRss/378018.htmlhttp://www.ymeg.top/killme2008/services/trackbacks/378018.html
    My weekend project clj.monitor is beta release,it's a clojure DSL for monitoring system and applications based on SSH.

Home:https://github.com/killme2008/clj.monitor

An example:
(ns clj.monitor.example
  (:use [clj.monitor.core]
        [control.core]
        [clj.monitor.tasks]))

;;define a mysql cluster
(defcluster mysql
  :clients [{:user "deploy" :host "mysql.app.com"}])

;;define a monitor for mysql cluster
(defmonitor mysql-monitor
  :tasks [(ping-mysql "root" "password")
            (system-load :5 3)]
  :clusters [:mysql])

;;start monitors
(start-monitors
 :cron "* 0/5 * * * ?"
 :alerts [(mail :from "alert@app.com" :to "yourname@app.com")]
 :monitors [mysql-monitor])

API document: http://fnil.net/clj.monitor

It is just a beta release,if you have any questions or find issues ,please let me know,thanks.


dennis 2012-05-12 22:38 发表评论
]]>
׼ƽФ
    <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

    <bdo id="rub96"></bdo>

      1. <track id="rub96"><div id="rub96"></div></track>
        <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

            <nobr id="rub96"><address id="rub96"><big id="rub96"></big></address></nobr>
          1. <menuitem id="rub96"><strong id="rub96"><menu id="rub96"></menu></strong></menuitem>
            <dl id="rub96"><source id="rub96"><tr id="rub96"></tr></source></dl>
            1. <tbody id="rub96"><div id="rub96"></div></tbody>
              1. <bdo id="rub96"><optgroup id="rub96"></optgroup></bdo>
              2. <bdo id="rub96"><dfn id="rub96"><dd id="rub96"></dd></dfn></bdo>
                1. <option id="rub96"><source id="rub96"></source></option>
                2. <bdo id="rub96"></bdo>

                    <p id="rub96"><tr id="rub96"></tr></p>
                  1. <tbody id="rub96"></tbody>

                    <bdo id="rub96"></bdo>

                  2. <option id="rub96"><source id="rub96"></source></option>

                    <bdo id="rub96"><optgroup id="rub96"><dd id="rub96"></dd></optgroup></bdo>
                      <track id="rub96"></track>

                        <bdo id="rub96"></bdo>
                      1. <option id="rub96"><p id="rub96"><tr id="rub96"></tr></p></option>

                          <bdo id="rub96"></bdo>
                          1. <track id="rub96"></track>
                            1. <track id="rub96"></track>
                                  <bdo id="rub96"></bdo>
                                  <option id="rub96"></option>

                                      1. <track id="rub96"><span id="rub96"></span></track>

                                          <option id="rub96"></option>

                                          1. 
                                            
                                              <option id="rub96"><span id="rub96"></span></option>
                                              <bdo id="rub96"><address id="rub96"></address></bdo>
                                              <option id="rub96"><source id="rub96"></source></option>
                                                <nobr id="rub96"><address id="rub96"></address></nobr>
                                              1. <nobr id="rub96"><optgroup id="rub96"><big id="rub96"></big></optgroup></nobr>
                                                <track id="rub96"></track>

                                                <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>
                                                  <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                  <bdo id="rub96"></bdo>

                                                    1. <track id="rub96"><div id="rub96"></div></track>
                                                      <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                          <nobr id="rub96"><address id="rub96"><big id="rub96"></big></address></nobr>
                                                        1. <menuitem id="rub96"><strong id="rub96"><menu id="rub96"></menu></strong></menuitem>
                                                          <dl id="rub96"><source id="rub96"><tr id="rub96"></tr></source></dl>
                                                          1. <tbody id="rub96"><div id="rub96"></div></tbody>
                                                            1. <bdo id="rub96"><optgroup id="rub96"></optgroup></bdo>
                                                            2. <bdo id="rub96"><dfn id="rub96"><dd id="rub96"></dd></dfn></bdo>
                                                              1. <option id="rub96"><source id="rub96"></source></option>
                                                              2. <bdo id="rub96"></bdo>

                                                                  <p id="rub96"><tr id="rub96"></tr></p>
                                                                1. <tbody id="rub96"></tbody>

                                                                  <bdo id="rub96"></bdo>

                                                                2. <option id="rub96"><source id="rub96"></source></option>

                                                                  <bdo id="rub96"><optgroup id="rub96"><dd id="rub96"></dd></optgroup></bdo>
                                                                    <track id="rub96"></track>

                                                                      <bdo id="rub96"></bdo>
                                                                    1. <option id="rub96"><p id="rub96"><tr id="rub96"></tr></p></option>

                                                                        <bdo id="rub96"></bdo>
                                                                        1. <track id="rub96"></track>
                                                                          1. <track id="rub96"></track>
                                                                                <bdo id="rub96"></bdo>
                                                                                <option id="rub96"></option>

                                                                                    1. <track id="rub96"><span id="rub96"></span></track>

                                                                                        <option id="rub96"></option>

                                                                                        1. 
                                                                                          
                                                                                            <option id="rub96"><span id="rub96"></span></option>
                                                                                            <bdo id="rub96"><address id="rub96"></address></bdo>
                                                                                            <option id="rub96"><source id="rub96"></source></option>
                                                                                              <nobr id="rub96"><address id="rub96"></address></nobr>
                                                                                            1. <nobr id="rub96"><optgroup id="rub96"><big id="rub96"></big></optgroup></nobr>
                                                                                              <track id="rub96"></track>

                                                                                              <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>
                                                                                              1. 3Ѽƻ þɰ汾 AGټ ϸ22ѡ5ƽ500 ʱʱ ʱʱֱƵ Ӯ½ַ ֲ㼼ɴ pkapp pk10׼1ڼƻ 3d¾ɱķ 齫ӮƼ ƻ zso8ɲʱȷ 253Ʊ