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

<channel>
	<title>Here comes the Sun &#187; java</title>
	<atom:link href="http://sunng.info/blog/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://sunng.info/blog</link>
	<description>47% users on this site use *nix</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:08:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>slacker 0.2.0 is out</title>
		<link>http://sunng.info/blog/2011/12/slacker-0-2-0-is-out/</link>
		<comments>http://sunng.info/blog/2011/12/slacker-0-2-0-is-out/#comments</comments>
		<pubDate>Sat, 10 Dec 2011 09:27:16 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1090</guid>
		<description><![CDATA[Slacker 0.2.0 has been pushed to clojars today. Connection pooling and json serialization are available in this release. Connection Pool Generally, pooling connection is a good idea in high concurrence application. To make slacker for real world, connection pool support &#8230; <a href="http://sunng.info/blog/2011/12/slacker-0-2-0-is-out/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/sunng87/slacker">Slacker 0.2.0</a> has been pushed to clojars today. Connection pooling and json serialization are available in this release.</p>
<h4>Connection Pool</h4>
<p>Generally, pooling connection is a good idea in high concurrence application. To make slacker for real world, connection pool support is a high-prioritized feature in its development. The new connection pool is backended by commons-pool which you might familiar with. To use connection pool, just create slacker client with a new function `slackerc-pool`</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">def</span> scp <span style="color: #66cc66;">&#40;</span>slackerc<span style="color: #66cc66;">-</span>pool <span style="color: #ff0000;">&quot;localhost&quot;</span> <span style="color: #cc66cc;">2104</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Then you can use this pool just like a single client.</p>
<p>Some options are available to configure the pool by your wish:</p>
<ul>
<li><em>:max-active</em>, max connections opened by the pool</li>
<li><em>:exhausted-action</em>
<ul>
<li><em>:fail</em> throw an exception when pool exhausted.</li>
<li><em>:block</em> block current thread and wait until max-wait exceed (throw an exception)</li>
<li><em>:grow</em> automatically create new connection and add it to pool</li>
</ul>
</li>
<li><em>:max-wait</em> max wait time before throwing an exception</li>
<li><em>:min-idle</em> minimal number of pool hold idle connections </li>
</ul>
<p>The options are inherited from GenericObjectPool, you can find detailed information from their <a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html">javadoc</a>.</p>
<h4>JSON Serialization</h4>
<p>slacker just added json serialization provided by clj-json. According to my test, clj-json is 1x faster than carbonite in serialization.</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">def</span> sc <span style="color: #66cc66;">&#40;</span>slackerc <span style="color: #ff0000;">&quot;localhost&quot;</span> <span style="color: #cc66cc;">2104</span> :<span style="color: #555;">content</span><span style="color: #66cc66;">-</span>type :<span style="color: #555;">json</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>However, with json serialization, you may lost some clojure types like keyword and set in type conversion. You should be caution when using json as serialization method. </p>
<p>In next release, I am planning to use <a href="https://github.com/AlibabaTech/fastjson/" target="_blank">fastjson</a> as json lib which provides option to write type name into json so it could be a full featured serialization for clojure. And fastjson is claimed even faster than jackson.</p>
<h4>Performance</h4>
<p>slacker gains high performance with its non-blocking server, serialization and direct function call. As tested on a dual 6 core server,  it reaches 10000+ TPS for a single client (50 connections, 50 threads). The server just use 35% CPU so I consider it could have even more TPS if there is two or more client machines.</p>
<p>So if you are interested in some benchmarks, you can test it with client like <a href="https://gist.github.com/1449860" target="_blank">this</a>. All the requests are using synchronous call because I believe it&#8217;s the most common case you use slacker.</p>
<h4>Next steps</h4>
<p>Inspired by discussion in <a href="http://groups.google.com/group/cn-clojure" target="_blank">cn-clojure</a> mailing list, I&#8217;m going to add HTTP transport for slacker. With HTTP transport, it&#8217;s easier to debug and evaluate your clojure functions, it also makes slacker available to ClojureScript. </p>
<p>At lst, thanks Zach Tellman for reviewing my client code. </p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/12/slacker-0-2-0-is-out/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>普通青年、二逼青年与文艺青年的Java代码缩进</title>
		<link>http://sunng.info/blog/2011/10/%e6%99%ae%e9%80%9a%e9%9d%92%e5%b9%b4%e3%80%81%e4%ba%8c%e9%80%bc%e9%9d%92%e5%b9%b4%e4%b8%8e%e6%96%87%e8%89%ba%e9%9d%92%e5%b9%b4%e7%9a%84java%e4%bb%a3%e7%a0%81%e7%bc%a9%e8%bf%9b/</link>
		<comments>http://sunng.info/blog/2011/10/%e6%99%ae%e9%80%9a%e9%9d%92%e5%b9%b4%e3%80%81%e4%ba%8c%e9%80%bc%e9%9d%92%e5%b9%b4%e4%b8%8e%e6%96%87%e8%89%ba%e9%9d%92%e5%b9%b4%e7%9a%84java%e4%bb%a3%e7%a0%81%e7%bc%a9%e8%bf%9b/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 06:57:19 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[自话]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1046</guid>
		<description><![CDATA[普通青年 while&#40;true&#41; &#123; &#160; &#160; if &#40;something&#41; &#123; &#160; &#160; &#160; &#160; System.out.println&#40;something&#41;; &#160; &#160; &#160; &#160; break; &#160; &#160; &#125; &#125; 特点： tab与空格混用，无其他特点。 常见于：各类代码仓库。 二逼青年 while&#40;true&#41; &#123; &#160; &#160; if &#40;something&#41; &#160; &#160; &#123; &#160; &#160; &#160; &#160; System.out.println&#40;something&#41;; &#8230; <a href="http://sunng.info/blog/2011/10/%e6%99%ae%e9%80%9a%e9%9d%92%e5%b9%b4%e3%80%81%e4%ba%8c%e9%80%bc%e9%9d%92%e5%b9%b4%e4%b8%8e%e6%96%87%e8%89%ba%e9%9d%92%e5%b9%b4%e7%9a%84java%e4%bb%a3%e7%a0%81%e7%bc%a9%e8%bf%9b/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>普通青年</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>特点： tab与空格混用，无其他特点。<br />
常见于：各类代码仓库。</p>
<p>二逼青年</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
<br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></div>
<p>特点：总担心代码不够长<br />
见于：各类劣质技术书籍</p>
<p>文艺青年</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>something<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>特点：普通Java青年永远不会理解的缩进，lisp程序员会心一笑<br />
见于：Clojure源码</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/10/%e6%99%ae%e9%80%9a%e9%9d%92%e5%b9%b4%e3%80%81%e4%ba%8c%e9%80%bc%e9%9d%92%e5%b9%b4%e4%b8%8e%e6%96%87%e8%89%ba%e9%9d%92%e5%b9%b4%e7%9a%84java%e4%bb%a3%e7%a0%81%e7%bc%a9%e8%bf%9b/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Convert a Python function to Java anonymous class</title>
		<link>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/</link>
		<comments>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 07:09:59 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=855</guid>
		<description><![CDATA[When calling Java with Jython, anonymous inner class might be an issue because there is no such equivalent in Python. In GUI programming, jython made additional effort on AWT event processing. You can pass a python function as some types &#8230; <a href="http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When calling Java with Jython, anonymous inner class might be an issue because there is no such equivalent in Python.</p>
<p>In GUI programming, jython made additional effort on AWT event processing. You can pass a python function as some types of event listener.</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> change_text<span style="color: black;">&#40;</span>event<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Clicked!'</span><br />
<br />
button <span style="color: #66cc66;">=</span> JButton<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Click Me!'</span><span style="color: #66cc66;">,</span> actionPerformed<span style="color: #66cc66;">=</span>change_text<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">add</span><span style="color: black;">&#40;</span>button<span style="color: black;">&#41;</span></div></div>
<p>Described in the <a href="http://www.jython.org/jythonbook/en/1.0/GUIApplications.html">Definitive Guide of Jython</a>:</p>
<blockquote><p>This works because Jython is able to automatically recognize events in Java code if they have corresponding addEvent()* and *removeEvent() methods. Jython takes the name of the event and makes it accessible using the nice Python syntax as long as the event methods are public. </p></blockquote>
<p>However, it does not work with Runnable, Callable and many other interfaces designed for anonymous usage.</p>
<p>To solve the incompatibility, I created a small decorator that converts Python function to a Java object.<br />
<script src="https://gist.github.com/947926.js"> </script></p>
<p>Thanks to python&#8217;s dynamic magic, we can create class in runtime and assign modified method to a particular instance. The conversion is performed once the function loaded. Also, you can pass something as arguments to constructor.</p>
<p>With anonymous_class decorator, the example above can be written as:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> javax.<span style="color: black;">swing</span> <span style="color: #ff7700;font-weight:bold;">import</span> JButton<span style="color: #66cc66;">,</span> JFrame<br />
<span style="color: #ff7700;font-weight:bold;">from</span> java.<span style="color: black;">awt</span>.<span style="color: black;">event</span> <span style="color: #ff7700;font-weight:bold;">import</span> ActionListener<br />
<br />
frame <span style="color: #66cc66;">=</span> JFrame<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Hello, Jython!'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaultCloseOperation <span style="color: #66cc66;">=</span> JFrame.<span style="color: black;">EXIT_ON_CLOSE</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">300</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#41;</span><br />
<br />
<span style="color: #66cc66;">@</span>anonymous_class<span style="color: black;">&#40;</span>ActionListener<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;actionPerformed&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">def</span> change_text<span style="color: black;">&#40;</span>dummy<span style="color: #66cc66;">,</span> event<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Clicked!'</span><br />
<br />
button <span style="color: #66cc66;">=</span> JButton<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Click Me!'</span><span style="color: #66cc66;">,</span> actionPerformed<span style="color: #66cc66;">=</span>change_text<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">add</span><span style="color: black;">&#40;</span>button<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">visible</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GPars的Actor实现</title>
		<link>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/</link>
		<comments>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 15:32:22 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=853</guid>
		<description><![CDATA[Actor是一种Continuation技术，可以在少量的线程运行大量Actor对象。Actor对象之间通过消息机制进行交互。而Actor本身线程安全，这样的模型使并发编程的复杂度降低，同时也在一定的场景下实现了可扩展性。 gpars是Java和Groovy都可以使用的并行编程库，他实现了Actor、Agent、DataFlow等模型，旨在为Groovy提供高层的并行编程模型。以下分析gpars 0.12中非阻塞Actor的实现。 @Grab&#40;&#34;org.codehaus.gpars:gpars:0.11&#34;&#41; import groovyx.gpars.actor.Actors def worker = Actors.actor &#123; &#160; &#160; loop &#123; &#160; &#160; &#160; &#160; react &#123; &#160; &#160; &#160; &#160; &#160; &#160; reply it.reverse&#40;&#41; &#160; &#160; &#160; &#160; &#125; &#160; &#160; &#125; &#125; def console &#8230; <a href="http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Actor是一种Continuation技术，可以在少量的线程运行大量Actor对象。Actor对象之间通过消息机制进行交互。而Actor本身线程安全，这样的模型使并发编程的复杂度降低，同时也在一定的场景下实现了可扩展性。</p>
<p>gpars是Java和Groovy都可以使用的并行编程库，他实现了Actor、Agent、DataFlow等模型，旨在为Groovy提供高层的并行编程模型。以下分析gpars 0.12中非阻塞Actor的实现。</p>
<div class="codecolorer-container groovy twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Grab<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;org.codehaus.gpars:gpars:0.11&quot;</span><span style="color: #66cc66;">&#41;</span><br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20import"><span style="color: #000000; font-weight: bold;">import</span></a> <span style="color: #a1a100;">groovyx.gpars.actor.Actors</span><br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> worker <span style="color: #66cc66;">=</span> Actors.<span style="color: #006600;">actor</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; loop <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; react <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reply it.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20reverse"><span style="color: #663399;">reverse</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> console <span style="color: #66cc66;">=</span> Actors.<span style="color: #006600;">actor</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; worker <span style="color: #66cc66;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;Hello GPars&quot;</span><br />
&nbsp; &nbsp; react <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20println"><span style="color: #993399;">println</span></a> it<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
console.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20join"><span style="color: #663399;">join</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>首先，在工厂类中Actors里会初始化一个DefaultPGroup用来封装后台的线程池、管理actors。Actors默认使用ResizeablePool，他是JDK Concurrent Framework中的ThreadPoolExecutor的封装，coreSize和maxSize不同所以称Resizeable。</p>
<p>Actors的工厂方法actor生成的是DefaultActor，它是非阻塞actor的默认实现。（ActorGroup:67）</p>
<p>DefaultActor的构造方法接受一个Groovy的闭包对象，将其封装为DefaultActorClosure对象后，调用其父类AbstractLoopingActor的initialize方法（DefaultActor：73）.</p>
<p>initialize方法创建一个Runnable对象AsyncMessagingCore，并将线程池传递给core对象。（AbstractLoopingActor:57）AsyncMessagingCore对象负责消息的传递和处理，是线程池处理的目标对象。</p>
<p>调用start启动actor后，actor会向自己发送一个start消息（AbstractLoopingActor:173）.<br />
core获得start消息后，调用DefaultActor覆盖的handleStart方法（DefaultActor:328）。</p>
<p>在handleStart中，actor会调用用户传入的闭包方法。上面的例子是一种典型的用法，loop是DefaultActor中的方法，loop也并不是无限空转的，他仅在收到消息被时被触发（DefaultActor:191）react也是DefaultActor中的方法，它将nextContinuation方法设为内部闭包对象，用来处理actor接收的消息。</p>
<p>向Actor发送消息，是通过actor的send方法和重载的leftShift运算符进行操作。（AbstractLoopingActor:236）actor调用core的store方法，将ActorMessage压入core的队列中。入队列之后，core会检查锁对象activeUpdater，判断当前core是否在线程处理中，如果不在，则将core加入线程池中处理。activeUpdater是一个AtomicIntegerFieldUpdater对象，他的compareAndSet可以保证原子性。而通过activeUpdater也可以保证同一时刻只有一个core被线程池处理，从而使actor的线程不安全代码也线程安全地运行。</p>
<p>进入线程池后，core首先将自己放进threadlocal对象中，并保存当前线程的引用。然后会循环消费MessageQueue中的消息直至Queue的可处理部分为空。（AsyncMessagingCore:126）。handleMessage在AbstractLoopingActor中被覆盖，会根据消息的类型进行分发调用（前面提到的start消息就是一种）。默认的业务消息，在DefaultActorClojure中调用DefaultActor的onMessage方法处理。</p>
<p>onMessage中，react的闭包会被调用来处理业务。之后nextContinuation被置为null，这时loop闭包被重新调用，react闭包重新被赋给nextContinuation。这部分代码就是前面所说的loop并非空转，而是在消息处理完成后重新准备而已。</p>
<p>此外，core的MessageQueue的实现是DefaultMessageQueue。它使用两个LinkedList作为输入（向actor输入）队列和输出队列，当输入队列为空时，通过同步方法swap交换输入输出队列。swap是整个actor系统里唯一一个同步方法。这样的机制保证actor的core在线程池中处理时，外界仍然可以向actor发送消息，消息会在actor被调度出线程池之前全部处理掉。不过，他的前提是只有一个线程读这个队列，这个条件在actor系统里，通过core对象的activeUpdater可以有效的保证。</p>
<p>Actor模式采用这种onDemand方式的线程使用，允许大量的actor共存，并只有活跃的actor会占用线程，非活跃状态的actor处在dettach状态，并不消耗计算资源，取消了空转的loop。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>jip 0.2 released</title>
		<link>http://sunng.info/blog/2011/04/jip-0-2-released/</link>
		<comments>http://sunng.info/blog/2011/04/jip-0-2-released/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 14:29:15 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/04/jip-0-2-released/</guid>
		<description><![CDATA[As you may know, jip is a dependency management tool for Jython/Java development. It resolves and downloads Java packages from maven-compatible repositories. jip also follows some best practices, encouraging you to use a portable and standalone environment (virtualenv) for your &#8230; <a href="http://sunng.info/blog/2011/04/jip-0-2-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As you may know, jip is a dependency management tool for Jython/Java development. It resolves and downloads Java packages from maven-compatible repositories. jip also follows some best practices, encouraging you to use a portable and standalone environment (virtualenv) for your Jython development.</p>
<p>It has been four months since the initial release. In version 0.2, I made following changes for you:</p>
<ul>
<li>Improved console output format</li>
<li>Correct scope dependency management inheritance</li>
<li>Snapshot management, alpha</li>
<li>Environment independent configuration</li>
<li>Bug fixes</li>
</ul>
<p>You can find the typical usage doc on github:<br />
<a href="https://github.com/sunng87/jip">https://github.com/sunng87/jip</a></p>
<p>jip-0.2 has been published to pypi so you can install or upgrade it with:<br />
easy_install -U jip</p>
<p>Please do remember to use it inside virtualenv!</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=6d854cec-aede-8421-9daa-99288bc44ead" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/jip-0-2-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>gefr API updates</title>
		<link>http://sunng.info/blog/2011/03/gefr-api-updates/</link>
		<comments>http://sunng.info/blog/2011/03/gefr-api-updates/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 13:11:52 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[gefr]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=818</guid>
		<description><![CDATA[早上收到jythonet作者的一封邮件，受到启发，我打算扩展一下gefr这个WSGI adapter。原本gefr是写给soldat用来测试的，结果发现现在出现了买椟还珠的效果，既然大家更加关注这个，我决定多花一些时间在上面。不过话说回来gefr确实是Jython Web程序的新思路，过去大家都在想怎样把Jython放进Servlet中，gefr的思路是把Java的服务器实现放到WSGI后面。未来会有gefr-netty, gefr-mina, gefr-servlet等等出现，如果真的存在一个可靠的backend，也许这种思路也不失为一个办法，毕竟python的web框架更吸引人，而java的基础设施相对可靠，各取所长。 根据这个目的，现在gefr 0.2的API更新为： 即在创建Gefr的时候需要告知backend类型，目前还只有soldat一种后端。未来也可能通过自动检测让这个参数成为可选。 gefr 0.2已经在开发中，您可以通过这里关注： https://bitbucket.org/sunng/gefr/overview]]></description>
			<content:encoded><![CDATA[<p>早上收到<a href="http://jythonet.appspot.com">jythonet</a>作者的一封邮件，受到启发，我打算扩展一下gefr这个WSGI adapter。原本gefr是写给soldat用来测试的，结果发现现在出现了买椟还珠的效果，既然大家更加关注这个，我决定多花一些时间在上面。不过话说回来gefr确实是Jython Web程序的新思路，过去大家都在想怎样把Jython放进Servlet中，gefr的思路是把Java的服务器实现放到WSGI后面。未来会有gefr-netty, gefr-mina, gefr-servlet等等出现，如果真的存在一个可靠的backend，也许这种思路也不失为一个办法，毕竟python的web框架更吸引人，而java的基础设施相对可靠，各取所长。</p>
<p>根据这个目的，现在gefr 0.2的API更新为：<br />
<script src="https://bitbucket.org/sunng/gefr/src/8490748055f1/src/examples/example.py?embed=t"></script></p>
<p>即在创建Gefr的时候需要告知backend类型，目前还只有soldat一种后端。未来也可能通过自动检测让这个参数成为可选。</p>
<p>gefr 0.2已经在开发中，您可以通过这里关注：<br />
<a href="https://bitbucket.org/sunng/gefr/overview">https://bitbucket.org/sunng/gefr/overview</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/gefr-api-updates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Setting up soldat and gefr</title>
		<link>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/</link>
		<comments>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 08:40:23 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soldat]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=813</guid>
		<description><![CDATA[本文介绍soldat服务器和gefr WSGI适配器的环境搭建，以及jip的基本使用。 安装python工具 virtualenv和pip是python开发的关键工具 sudo apt-get install python-virtualenv sudo apt-get install python-pip jython需要您手动下载安装。推荐安装到/usr/local/下，并建立软连接到/usr/local/bin/中，下文将假设您是这么做的。 创建虚拟jython环境 virtualenv -p /usr/local/bin/jython gefr-test cd gefr-test source bin/activate 安装jip pip install jip 配置jip 在$HOME下创建文件.jip，内容为： &#91;repos:oss&#93; uri=http://oss.sonatype.org/content/repositories/snapshots/ type=remote &#91;repos:central&#93; uri=http://repo1.maven.org/maven2/ type=remote &#91;repos:local&#93; uri=/home/sun/.m2/repository/ type=local 安装soldat 配置完jip后，可以使用jip来安装soldat jip &#8230; <a href="http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>本文介绍soldat服务器和gefr WSGI适配器的环境搭建，以及jip的基本使用。</p>
<h4>安装python工具</h4>
<p>virtualenv和pip是python开发的关键工具<br />
sudo apt-get install python-virtualenv<br />
sudo apt-get install python-pip</p>
<p>jython需要您手动下载安装。推荐安装到/usr/local/下，并建立软连接到/usr/local/bin/中，下文将假设您是这么做的。</p>
<h4>创建虚拟jython环境</h4>
<p>virtualenv -p /usr/local/bin/jython gefr-test<br />
cd gefr-test<br />
source bin/activate</p>
<h4>安装jip</h4>
<p>pip install jip</p>
<h4>配置jip</h4>
<p>在$HOME下创建文件.jip，内容为：</p>
<div class="codecolorer-container ini twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:oss<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://oss.sonatype.org/content/repositories/snapshots/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:central<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://repo1.maven.org/maven2/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:local<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">/home/sun/.m2/repository/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">local</span></div></div>
<h4>安装soldat</h4>
<p>配置完jip后，可以使用jip来安装soldat<br />
jip install info.sunng.soldat:soldat:1.0-SNAPSHOT</p>
<p>文件将被下载到 javalib 目录中，您可以检查安装的正确性：<br />
$ ls javalib/<br />
log4j-1.2.16.jar     slf4j-log4j12-1.6.1.jar<br />
slf4j-api-1.6.1.jar  soldat-1.0-SNAPSHOT.jar</p>
<h4>安装gefr</h4>
<p>pip install gefr==0.1dev2</p>
<h4>创建一个简单的Python WSGI程序</h4>
<p>创建test.py</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> gefr <span style="color: #ff7700;font-weight:bold;">import</span> Gefr<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> wsgiapp<span style="color: black;">&#40;</span>environ<span style="color: #66cc66;">,</span> start_response<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; status <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'200 OK'</span><br />
&nbsp; &nbsp; res_body <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Welcome&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;It works!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&quot;</span><br />
&nbsp; &nbsp; res_headers <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Type'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'text/html'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Length'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>res_body<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; start_response<span style="color: black;">&#40;</span>status<span style="color: #66cc66;">,</span> res_headers<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>res_body<span style="color: black;">&#93;</span><br />
<br />
Gefr<span style="color: black;">&#40;</span>wsgiapp<span style="color: #66cc66;">,</span> host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'0.0.0.0'</span><span style="color: #66cc66;">,</span> port<span style="color: #66cc66;">=</span><span style="color: #ff4500;">8000</span><span style="color: black;">&#41;</span>.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<h4>启动服务</h4>
<p>使用jip附带的jython-all<br />
jython-all test.py</p>
<p>打开浏览器，访问 http://localhost:8000/</p>
<h4>用ab测试服务性能</h4>
<p>$ ab -n 10000 -c 100 http://localhost:8000/</p>
<pre>
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests

Server Software:        gefr/0.1dev
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        79 bytes

Concurrency Level:      100
Time taken for tests:   2.539 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1640000 bytes
HTML transferred:       790000 bytes
Requests per second:    3938.11 [#/sec] (mean)
Time per request:       25.393 [ms] (mean)
Time per request:       0.254 [ms] (mean, across all concurrent requests)
Transfer rate:          630.71 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.6      0       8
Processing:     9   25  22.4     21     239
Waiting:        9   25  22.4     21     239
Total:         13   25  22.3     21     239

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     22
  75%     22
  80%     23
  90%     26
  95%     40
  98%     65
  99%    233
 100%    239 (longest request)
</pre>
<p>Good Luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>包管理与路径管理</title>
		<link>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/</link>
		<comments>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/#comments</comments>
		<pubDate>Sat, 22 Jan 2011 08:07:17 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/</guid>
		<description><![CDATA[现在几乎每一种语言都有一些依赖管理工具，或者是中央的包仓库。比如这些： Java: maven, ivy, gradle Ruby: gems Python: easy_install, pip Clojure: leinigen Groovy: maven, grape, gradle Hashkell: cabal PHP: pear Nodejs: npm 这些工具在管理包和路径时都会采用各不相同的策略，有的是通过自身实现，有的是借助语言平台本身的特点。 Java 其中最注明的Maven，它的方式是在POM文件中定义你的依赖，Maven会在本地仓库中维护这些依赖。Maven的本地仓库默认是在$HOME/.m2/repository目录下，是用户独立的，当然要下载一个依赖也不需要root权限。而在通过Maven运行Java项目时，Maven插件会自动管理classpath，你并不需要把这些依赖从本地仓库里拷贝出来而单独维护一个所谓lib目录（这样也不好管理）。这是Maven的方式，目前看来，这也是最经典的一种方式。除了maven本身的特性以外，这也和Java的classpath机制有关。 最近势头很猛的Java构建工具gradle，方式也与Maven类似，它会把下载的依赖存放在$HOME/.gradle/cache目录里，并自动管理classpath。 同样是Java，与maven相对应的是ant+ivy。ivy可以为你管理依赖，但是ivy不会帮你管理classpath。ivy的包管理，是以project为scope的，你需要维护一个lib目录来存放这些下载的包，再通过传统的ant的方式去管理classpath，从而使项目可以进行编译和运行。 在Java世界里，还有一个特别的工具叫做grape，它是专门用于groovy的轻量级的依赖解决方案。grape是以脚本为scope，在需要依赖的脚本中通过@Grab声明依赖，grape工具可以从maven仓库中下载依赖到$HOME/.groovy/grapes中，并把相关的依赖加入groovy的classpath。除此以外，grape还有一个命令行工具帮助你手动下载依赖到本地仓库。grape的内部是基于ivy的，不过它的方式比ant要自动化很多。 在Java世界里还有一个特例，是Clojure的依赖管理工具leiningen。leiningen本身也比较简单，它的方式与ivy相同，会解析project.clj文件中定义的依赖关系，并下载到当前的工程目录下的lib中。lein是鼓励通过uberjar的方式把依赖统统打包的，所以它并没有classpath的管理功能。 总体来说，Java世界的工具和Java是相似的，其最大特点就是System independent，安装包不需要root权限，每次的运行都需要管理classpath。作为开发人员，classpath中有哪些可以访问的类库是可以控制的，这也使Java程序的移植性得到良好的控制和管理。 Python 与Java不同，Python通常作为系统分发的一部分，他的包管理和PATH管理要相对混乱一些。通常我们有两种方式来安装一个Python的软件包： sudo apt-get install python-redis sudo easy_install redis &#8230; <a href="http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>现在几乎每一种语言都有一些依赖管理工具，或者是中央的包仓库。比如这些：</p>
<ul>
<li>Java: maven, ivy, gradle</li>
<li>Ruby: gems</li>
<li>Python: easy_install, pip</li>
<li>Clojure: leinigen</li>
<li>Groovy: maven, grape, gradle</li>
<li>Hashkell: cabal</li>
<li>PHP: pear</li>
<li>Nodejs: npm</li>
</ul>
<p>这些工具在管理包和路径时都会采用各不相同的策略，有的是通过自身实现，有的是借助语言平台本身的特点。</p>
<h3>Java</h3>
<p>其中最注明的Maven，它的方式是在POM文件中定义你的依赖，Maven会在本地仓库中维护这些依赖。Maven的本地仓库默认是在$HOME/.m2/repository目录下，是用户独立的，当然要下载一个依赖也不需要root权限。而在通过Maven运行Java项目时，Maven插件会自动管理classpath，你并不需要把这些依赖从本地仓库里拷贝出来而单独维护一个所谓lib目录（这样也不好管理）。这是Maven的方式，目前看来，这也是最经典的一种方式。除了maven本身的特性以外，这也和Java的classpath机制有关。</p>
<p>最近势头很猛的Java构建工具gradle，方式也与Maven类似，它会把下载的依赖存放在$HOME/.gradle/cache目录里，并自动管理classpath。</p>
<p>同样是Java，与maven相对应的是ant+ivy。ivy可以为你管理依赖，但是ivy不会帮你管理classpath。ivy的包管理，是以project为scope的，你需要维护一个lib目录来存放这些下载的包，再通过传统的ant的方式去管理classpath，从而使项目可以进行编译和运行。</p>
<p>在Java世界里，还有一个特别的工具叫做grape，它是专门用于groovy的轻量级的依赖解决方案。grape是以脚本为scope，在需要依赖的脚本中通过@Grab声明依赖，grape工具可以从maven仓库中下载依赖到$HOME/.groovy/grapes中，并把相关的依赖加入groovy的classpath。除此以外，grape还有一个命令行工具帮助你手动下载依赖到本地仓库。grape的内部是基于ivy的，不过它的方式比ant要自动化很多。</p>
<p>在Java世界里还有一个特例，是Clojure的依赖管理工具leiningen。leiningen本身也比较简单，它的方式与ivy相同，会解析project.clj文件中定义的依赖关系，并下载到当前的工程目录下的lib中。lein是鼓励通过uberjar的方式把依赖统统打包的，所以它并没有classpath的管理功能。</p>
<p>总体来说，Java世界的工具和Java是相似的，其最大特点就是System independent，安装包不需要root权限，每次的运行都需要管理classpath。作为开发人员，classpath中有哪些可以访问的类库是可以控制的，这也使Java程序的移植性得到良好的控制和管理。</p>
<h3>Python</h3>
<p>与Java不同，Python通常作为系统分发的一部分，他的包管理和PATH管理要相对混乱一些。通常我们有两种方式来安装一个Python的软件包：</p>
<ul>
<li>sudo apt-get install python-redis</li>
<li>sudo easy_install redis</li>
</ul>
<p>一种是通过系统的包管理工具（如apt-get）从系统的软件仓库里安装，一种是通过python自己的包管理工具（如easy_install / pip）从Python Cheese Shop中下载安装。这两种安装方式有什么不同呢。以Ubuntu为例，通过apt-get安装的python包通常会被放在 /usr/share/pyshared 或 /usr/lib/python2.6/dist-packages 中，相对应的，由easy_install安装的Python包，则存放在 /usr/local/lib/python2.6/dist-packages 中。Python启动后可以通过查看sys.path来了解当前的path情况。</p>
<p>除了安装到系统目录，easy_install可以通过 &#8211;user 选项来把软件包安装到用户目录 $HOME/.local/lib/python2.6/site-packages。不过无论是系统级别还是用户级别，python都很难在启动时管理Path，即任何时候python都可以访问安装在系统中的所有软件包。这导致了混乱的情况，导致编写的python软件难以进行依赖管理和移植（即使没有定义在setup.py中，很多依赖还是可以访问的）。</p>
<p>由此virtualenv营运而生，virtualenv帮助你创建一个独立的python运行环境。激活这个小环境之后，easy_install/pip仅仅安装软件到小环境，python仅能访问环境内部的site-packages，这样整个环境中的依赖关系就非常清楚，也保障了程序的移植性。这样，就将原本系统scope的python包管理级别改进为项目级别。我之前写的jip也是将依赖下载或拷贝到virtualenv的小环境中，并且修改jython的启动脚本修改PYTHONPATH的设置，保证Java依赖对Jython的透明可访问。</p>
<h3>Nodejs</h3>
<p>nodejs是一个新兴的生态系统，一个包管理工具对其也是必不可少。npm是目前整个社区都比较认可的工具。</p>
<p>不过目前npm并不好用。npm默认会把自己安装到 node安装前缀的目录，比如node安装时你选择了默认前缀/usr/local，那么npm会把自己安装到/usr/local/lib/node里。这个目录是系统级别的，所以需要root权限，而npm本身又不鼓励用户用root权限来安装软件包（安全问题）。所以作者说希望用户把/usr/local/lib/node权限授予用户，或者把node安装到用户目录里。这两种方式其实都不太优雅。</p>
<p>Ruby的gems在这方面最符合unix哲学，即用户知道自己在做什么。如果用户以root权限运行gem  install，gem会把软件包安装到系统目录中对所有用户可用，而如果以普通用户权限运行，则安装到用户目录 $HOME/.gem 中仅当前用户可见。</p>
<p>nodejs在加载软件包时，会在require.paths中的几个目录里查找，前两个都是用户目录，所以npm也并非一定要把包安装到系统目录里去。虽然现在可以用过修改.npmrc文件在修改npm的默认行为，不过在这个CoC的时代，显然太繁琐了。</p>
<h3>Best Pratice</h3>
<p>总结一下，包管理和路径管理的最佳实践应该是：语言平台有CoC的路径机制，包管理器有基于环境变量、用户权限的判断执行合适行为。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>soldat &amp; gefr</title>
		<link>http://sunng.info/blog/2011/01/soldat-gefr/</link>
		<comments>http://sunng.info/blog/2011/01/soldat-gefr/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 16:31:09 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[gefr]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soldat]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/01/soldat-gefr/</guid>
		<description><![CDATA[我的这一套stack正在走向完整。上次贴了一张soldat-http的图，现在基于soldat的wsgi服务器也已经有了一个基本可以运行的实现，名字叫做gefr（我的命名出处参考这里）。现在gefr上已经可以跑基于bottle框架的wsgi程序了，也就是说一些基于python的web应用可能可以通过jython来运行在soldat上。为了搞定jython的环境，这几天我还花了不少时间做了jip帮我从maven仓库里自动下载依赖的jar包。 soldat和gefr的代码都放在我的bitbucket上： soldat https://bitbucket.org/sunng/soldat gefr https://bitbucket.org/sunng/gefr 此外，这两个项目也分别发布到了sonatype oss仓库和python cheese shop。 现在还有几个问题： soldat在读buffer的时候先获得buffer的limit，再去读相应长度的buffer有时会出现BufferUnderflowException。这个可能存在线程安全问题，现在还没发现。 gefr启动之后可以通过在jvisualvm里找到这个进程，但是绑定profiler之后很诡异的是gefr就不再处理请求了。 直接用soldat的处理http请求，吞吐量可以上万；但是在上面加上jython的gefr，再加上bottle框架，同样的功能吞吐量就剩下原来的十分之一了。就是因为没法做profile，所以还不知道时间花到哪里去了。 简单地 announce 一下，这样我有更多的动力来继续把这两个小东西做好。]]></description>
			<content:encoded><![CDATA[<p>我的这一套stack正在走向完整。上次贴了一张soldat-http的图，现在基于soldat的wsgi服务器也已经有了一个基本可以运行的实现，名字叫做gefr（我的命名出处参考<a href="http://en.wikipedia.org/wiki/Rank_insignia_of_the_German_armed_forces">这里</a>）。现在gefr上已经可以跑基于bottle框架的wsgi程序了，也就是说一些基于python的web应用可能可以通过jython来运行在soldat上。为了搞定jython的环境，这几天我还花了不少时间做了jip帮我从maven仓库里自动下载依赖的jar包。</p>
<p>soldat和gefr的代码都放在我的bitbucket上：</p>
<ul>
<li>soldat <a href="https://bitbucket.org/sunng/soldat">https://bitbucket.org/sunng/soldat</a></li>
<li>gefr <a href="https://bitbucket.org/sunng/gefr">https://bitbucket.org/sunng/gefr</a></li>
</ul>
<p>此外，这两个项目也分别发布到了<a href="https://oss.sonatype.org/content/repositories/snapshots/">sonatype oss仓库</a>和<a href="http://pypi.python.org/pypi/gefr">python cheese shop</a>。</p>
<p>现在还有几个问题：</p>
<ul>
<li>soldat在读buffer的时候先获得buffer的limit，再去读相应长度的buffer有时会出现BufferUnderflowException。这个可能存在线程安全问题，现在还没发现。</li>
<li>gefr启动之后可以通过在jvisualvm里找到这个进程，但是绑定profiler之后很诡异的是gefr就不再处理请求了。</li>
<li>直接用soldat的处理http请求，吞吐量可以上万；但是在上面加上jython的gefr，再加上bottle框架，同样的功能吞吐量就剩下原来的十分之一了。就是因为没法做profile，所以还不知道时间花到哪里去了。</li>
</ul>
<p>简单地 announce 一下，这样我有更多的动力来继续把这两个小东西做好。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/01/soldat-gefr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jip 0.1</title>
		<link>http://sunng.info/blog/2011/01/jip-0-1/</link>
		<comments>http://sunng.info/blog/2011/01/jip-0-1/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 14:49:04 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/01/jip-0-1/</guid>
		<description><![CDATA[The original idea is to create a standalone jython environment, I took traditional Java tools, ant and ivy, to resolve Java dependencies. But the XMLs seem to be verbose and not pythonic. So I decide to create something like pip, &#8230; <a href="http://sunng.info/blog/2011/01/jip-0-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The original idea is to create a standalone jython environment, I took <a href="http://sunng.info/blog/2010/12/setup-a-jython-development-environment/">traditional Java tools, ant and ivy</a>, to resolve Java dependencies. But  the XMLs seem to be verbose and not pythonic. So I decide to create something like pip, that is, resolves and installs dependencies in a pythonic way.  It is jip.</p>
<p>jip will automatically download jars and its <strong>non-optional</strong> <strong>runtime</strong> dependencies from Maven repositories. By default, jip will search your local repository and maven central repository for the requested artifact. Also, you can create a configuration file to overwrite this.</p>
<p>Virtualenv is required by jip. You must run jip within a standalone environment, created by virtualenv:<br />
<i>virtualenv -p /usr/local/bin/jython jython-env</i><br />
<i>cd jython-env</i><br />
<i>source bin/activate</i></p>
<p>Don&#8217;t forget to activate it.</p>
<p>Then download jip with pip:<br />
<i>pip install jip</i></p>
<p>Now you have pip for python and jip for java. To install a Java package, just type:<br />
jip install &lt;groupId&gt;:&lt;artifactId&gt;:&lt;version&gt;</p>
<p>groupId+artifactId+version is known as the coordinate of a maven artifact. For example, you need spring-core in your jython development:<br />
<i>jip install org.springframework:spring-core:3.0.5.RELEASE</i></p>
<p>The jars will be stored in <i>javalib</i> directory:<br />
<i>ls javalib</i></p>
<pre>
commons-logging-1.1.1.jar     spring-core-3.0.5.RELEASE.jar
spring-asm-3.0.5.RELEASE.jar
</pre>
<p>And When you installed jip, I will provide you a <i>jython-all</i> command to include dependencies by default. So use <i>jython-all</i> instead of <i>jython</i> to run your program and the shell.</p>
<p>For traditional Java user, there is a <i>resolve</i> subcommand to download dependencies defined in a pom file. This is more maintainable, some of you may prefer this way to typing it one by one.<br />
<i>jip resolve pom.xml</i></p>
<p>To define custom repositories, place a dot file <i>.jip</i> in your home directory:</p>
<div class="codecolorer-container ini twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>jboss<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://repository.jboss.org/maven2/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>local<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">/home/sun/.m2/repository/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">local</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>central<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://repo1.maven.org/maven2/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span></div></div>
<p>You may have internal Nexus, just append to this file following the pattern.</p>
<p>Finally, a clean subcommand to remove everything you downloaded.</p>
<p>That&#8217;s all. You can find the project at:</p>
<ul>
<li><a href="http://pypi.python.org/pypi/jip">http://pypi.python.org/pypi/jip</a></li>
<li><a href="https://github.com/sunng87/jip">https://github.com/sunng87/jip</a></li>
</ul>
<p>Your feedback is appreciate. Fire an issue in github if you find any bugs or new ideas about this tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/01/jip-0-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

