88250

Java

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  82 随笔 :: 0 文章 :: 5 评论 :: 0 Trackbacks

2010年11月2日 #



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-134.html
posted @ 2011-01-26 00:32 88250 阅读(255) | 评论 (0)编辑 收藏

上周硅谷非常热闹,重大消息频繁出现,其中包括了乔布斯因病休假,苹果的恐怖财报等等。对于我们所关心的移动业界跟互联网来说,Google 换帅是另外一个重量级消息。

Quora 上有一个讨论串,题目是“Larry Page 上任之后,Google 的重点应该是什么?”,讨论相当活跃。我也在这里凑个热闹,谈一谈在我看来,Larry Page 应该如何去改变 Google。

download (4).png

1:关注核心业务,也就是搜索

Google 前段时间在搜索结果上算是饱受攻击,由于与日俱增的垃圾内容,搜索结果的污染状况越发严重。Stack Overflow 的创始人之一 Jeff Atwood 在一篇文章里这样评价 Google 现在的搜索结果:

Google ,这个曾经的必备工具,某种程度上已经失去了它的优势地位。垃圾内容制造者、以点击率为终极目标的内容聚合站点正在走向胜利。

在 这一点上来说,ifanr 感同身受。作为内容提供者,我们是创造价值的人,是在给互联网不断添砖加瓦的一方。而之前在 Google 里搜索我们的原创文章,出现在结果最顶端的却往往是是通过拷贝+粘贴、有时候还不注明出处进行转载的内容聚合站点。它们用毫无成本的方式夺取着应该属于原 作者的访问量。

好在 Google 似乎已经认识到了这一点。之前搜索质量组的 Matt Cutts 表示他 们已经意识到了垃圾内容的增多,以及劣质内容聚合站点引发的不满,并且会很快进行处理。从我今早的实验来看,似乎 Google 已经采取了措施,最近 ifanr 的原创文章都出现在首页头条。从根子上(点击量带来的经济利益)驱逐劣质内容聚合站点,对现代互联网来说,确实是件好事

搜索,是 Google 的立身之本,从上周发布的财报来看,Google 收入的主要增长点仍然是在网站本身的业务。不断改进搜索,添加新的搜索方式,才能保持和增强 Google 在这个领域的领导地位。后院不起火,才有在其他领域发展的资本。

2323.jpg

这一条,是 Larry Page 上任以后最需要关注的。未来十年的搜索是什么样子?如何提高内容关联性,改进使用体验?怎么样通过创新,把 Bing 等竞争对手远远甩开,对 Google 来说,至关重要。

2:在社交网络方面另辟蹊径

Google 在社交网络方面的试探,到目前为止都是悲剧,坦率地说,我个人认为Google 已经错过了第一班社交网络的列车。

RIP-Google-Wave-Dead.jpg

作为新生事物的社交网络,从一开始负载的是用户虚拟交流的需求。

目 前的胜利者里面,Facebook 满足了人们交流的愿望,利用网络,表现了某种程度上真实的人与人关系,而大量互动元素的引入,则是模拟了现实生活的部分人际往来,从根底上来说,没有理念 上的创新,然而它仍然足够伟大,Facebook 把现实生活成功投影到了虚拟世界,是真正意义上的创造者。

另一个赢家是 Twitter,它满足的,是人们表达自己的愿望。通过简短的 140 个字,人与人之间形成了一种奇妙的交流关系,普通人也可以第一时间见证重大事件。可以说,Twitter 与智能手机的结合,创造了一种新媒体。表达自己,记录周边,关注别人,是 Twitter 类社交网络的根本。无论是变种的 foursquare,还是 Quora,从理念上看,都是这样的东西。

Google 之前的尝试呢? Wave 那个体验一塌糊涂的东西不去说它,出生太早了;Buzz 则是无限制版本的 Twitter:Google 试图利用现成的庞大用户群,但没有实质性创新,再加上拙劣的整合方式,这个产品的前景乐观不到哪儿去。

社交网络走到现在,实际上已经到了一个重要的关口,即:虚拟的内容如何与现实社会结合起来,怎样把线上关系与实体经济整合,创造出一个崭新的商业模式。在我看来,这才是第二代社交网络,也即成熟版本的社交网络。这个方向是未来两年的热点,也是 Google 下一步可以突围的角度。

Google 的最大优势是什么?大家应该都非常清楚,其一是庞大的用户群,其二就是信息了。Google 相对于 Twittter、fousquare 等来说,先天就有信息方面的优势。而 Google 在建设社交网络的时候,却完全忽略了这个优势,捆着手脚去从头开始跟已经成熟的对手竞争,怎么可能胜利?

举个最简单的例子,Google Maps 信息丰富,我经常用它来寻找晚餐地点,最大的好处之一就是可以看到多个网站的用户评价,看看截图:

Untitled-1.jpg

看 到了吧,有 Buzz 选项,然而搞笑的事来了。我可以看到其他网站的评价,可以在 Buzz 上分享这个地点,然后呢?没了。我完全看不到 Buzz 关于这个餐馆的讨论,看不到我分享以后朋友的看法——一点也没有。实体经济方面的内容本身就是 Google 的长项,然而在它的任何产品里面,都没有把这个长处跟自己的社交网络更紧密得结合起来。

放着庞大的现实数据不用,几个产品之间几乎没有交流,捧着金饭碗要饭,这就是 Google 的社交网络。跟现实社会结合的社交网络,将是 Google 在这一领域的最后一个机会。

3:细节,细节,还是细节

有一句老话,细节决定成败,然而 Google 现在的很多做法,却表现了一种对细节的漠视,极大影响了产品的使用体验。还是要以 Android 为例(这玩意简直就是反面教材):

就从简单的设置界面说起。Android 平铺直叙的设置界面,完全没有突出重点(我甚至怀疑这帮人安排顺序的时候是不是拍脑门做出的决定。),跟右边的 iOS 比,孰优孰劣,一目了然。

Untitled-2.jpg

还有应用市场,每次谈到 Android 的应用市场,我都有爆粗口的冲动。缓慢的速度、时常丢失的已下载应用列表、迟迟没有解决的应用无法下载问题……这是整个产业的核心之一,Google 就准备这么糊弄下去?

Android 不讲究的地方何止这些,工程师文化并不代表着可以不拘小节,Google 的目光,应该多放些在细节上。移动设备,用户体验至关重要。

4: 继续拥抱云,下注新能源产业

在这个卖杂货的、搞 B2C 的、做软件的都在搞云应用平台的当口,互联网界巨头,拥抱云的先驱之一,可能拥有着世界上最好硬件以及网络设施的 Google,当然也拥有自家的 App Engine。

download (3).png

云 计算平台对于中小企业、个人的意义,无论如何赞扬也不会过分,它直接引领了当前的互联网创业潮。低廉的平台成本,按需付费的方式,Amazon EC2 吸引了大量的个人开发者,Google 的 App Engine 当然不错,但我要说,还是不够灵活,如果能提供更多语言支持,就再好不过了。

新能源很好理解,随着碳交易市场的兴起,碳排放量眼看就要变成金融市场上的一个新产品。在这个趋势影响下,每个企业都应该考虑下自己的能源来源,为将来更加严格的排放调控措施做好准备,规避可能的经济风险。

data-center.jpg

降低所消耗能源的碳排放,对于 Google 这种能源消耗大户来说,是经济跟政治上都很正确的方向,而且同样有大量的利益存在。新能源产业,应该成为 Google 下一步的重点投入方向。

5:提高决策速度与质量,减少内部沟通环节

大 家都知道 Google 著名的 20% 规则:员工可以把 20% 的上班时间放在其他项目上。Google 的员工无疑是优秀的,这些业余时间做出的项目也应该有很多不错的点子,然而,从中孵化的成果却并不多。其中的部分原因,恐怕与 Google 的内部引导以及沟通机制存在很大的关系。由于缺乏引导,员工的项目往往与 Google 本身没什么联系,而因为沟通问题,好的项目不一定能够获得公司的帮助。

Google 的前员工遍布整个互联网业界,大量创新却往往出现在他们离开 Google 以后。应该如何去引发员工的创造力、提高内部效率跟执行力度,Larry Page 需要仔细考虑,以便调整内部架构来适应这个变化迅速的世界。三星这个反应快到根本不像大公司的大公司在全世界攻城掠地,诺基亚反应稍微迟缓一点就束手束 脚,Google,你要快一点,再快一点,才能跟 Facebook 以及数以千计的创业企业进行竞争。

转自:http://www.oschina.net/news/14996/larry-page-google-five-things-todo



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/larry-page-google-five-things-todo.html
posted @ 2011-01-25 09:21 88250 阅读(268) | 评论 (0)编辑 收藏

没有人能说清哪种缓存算法优于其他的缓存算法。(以下的几种缓存算法,有的我也理解不好,如果感兴趣,你可以Google一下)

Least Frequently Used(LFU):

大家好,我是 LFU,我会计算为每个缓存对象计算他们被使用的频率。我会把最不常用的缓存对象踢走。

Least Recently User(LRU):

我是LRU缓存算法,我把最近最少使用的缓存对象给踢走。

我总是需要去了解在什么时候,用了哪个缓存对象。如果有人想要了解我为什么总能把最近最少使用的对象踢掉,是非常困难的。

浏览器就是使用了我(LRU)作为缓存算法。新的对象会被放在缓存的顶部,当缓存达到了容量极限,我会把底部的对象踢走,而技巧就是:我会把最新被访问的缓存对象,放到缓存池的顶部。

所以,经常被读取的缓存对象就会一直呆在缓存池中。有两种方法可以实现我,array 或者是 linked list。

我的速度很快,我也可以被数据访问模式适配。我有一个大家庭,他们都可以完善我,甚至做的比我更好(我确实有时会嫉妒,但是没关系)。我家庭的一些成员包括LRU2 和 2Q,他们就是为了完善 LRU 而存在的。

Least Recently Used 2(LRU2):

我是 Least Recently Used 2,有人叫我最近最少使用twice,我更喜欢这个叫法。我会把被两次访问过的对象放入缓存池,当缓存池满了之后,我会把有两次最少使用的缓存对象踢走。 因为需要跟踪对象2次,访问负载就会随着缓存池的增加而增加。如果把我用在大容量的缓存池中,就会有问题。另外,我还需要跟踪那么不在缓存的对象,因为他 们还没有被第二次读取。我比LRU好,而且是 adoptive to access 模式 。

Two Queues(2Q):

我是 Two Queues;我把被访问的数据放到LRU的缓存中,如果这个对象再一次被访问,我就把他转移到第二个、更大的LRU缓存。

我踢走缓存对象是为了保持第一个缓存池是第二个缓存池的1/3。当缓存的访问负载是固定的时候,把 LRU 换成 LRU2,就比增加缓存的容量更好。这种机制使得我比 LRU2 更好,我也是 LRU 家族中的一员,而且是 adoptive to access 模式 。

Adaptive Replacement Cache(ARC):

我是 ARC,有人说我是介于 LRU 和 LFU 之间,为了提高效果,我是由2个 LRU 组成,第一个,也就是 L1,包含的条目是最近只被使用过一次的,而第二个 LRU,也就是 L2,包含的是最近被使用过两次的条目。因此, L1 放的是新的对象,而 L2 放的是常用的对象。所以,别人才会认为我是介于 LRU 和 LFU 之间的,不过没关系,我不介意。

我被认为是性能最好的缓存算法之一,能够自调,并且是低负载的。我也保存着历史对象,这样,我就可以记住那些被移除的对象,同时,也让我可以看到被移除的对象是否可以留下,取而代之的是踢走别的对象。我的记忆力很差,但是我很快,适用性也强。

Most Recently Used(MRU):

我是 MRU,和 LRU 是对应的。我会移除最近最多被使用的对象,你一定会问我为什么。好吧,让我告诉你,当一次访问过来的时候,有些事情是无法预测的,并且在缓存系统中找出最少最近使用的对象是一项时间复杂度非常高的运算,这就是为什么我是最好的选择。

我是数据库内存缓存中是多么的常见!每当一次缓存记录的使用,我会把它放到栈的顶端。当栈满了的时候,你猜怎么着?我会把栈顶的对象给换成新进来的对象!

First in First out(FIFO):

我是先进先出,我是一个低负载的算法,并且对缓存对象的管理要求不高。我通过一个队列去跟踪所有的缓存对象,最近最常用的缓存对象放在后面,而更早的缓存对象放在前面,当缓存容量满时,排在前面的缓存对象会被踢走,然后把新的缓存对象加进去。我很快,但是我并不适用。

Second Chance:

大家好,我是 second chance,我是通过FIFO修改而来的,被大家叫做 second chance 缓存算法,我比 FIFO 好的地方是我改善了 FIFO 的成本。我是 FIFO 一样也是在观察队列的前端,但是很FIFO的立刻踢出不同,我会检查即将要被踢出的对象有没有之前被使用过的标志(1一个bit表示),没有没有被使用 过,我就把他踢出;否则,我会把这个标志位清除,然后把这个缓存对象当做新增缓存对象加入队列。你可以想象就这就像一个环队列。当我再一次在队头碰到这个 对象时,由于他已经没有这个标志位了,所以我立刻就把他踢开了。我在速度上比FIFO快。

CLock

我是Clock,一个更好的FIFO,也比 second chance更好。因为我不会像second chance那样把有标志的缓存对象放到队列的尾部,但是也可以达到second chance的效果。

我持有一个装有缓存对象的环形列表,头指针指向列表中最老的缓存对象。当缓存miss发生并且没有新的缓存空间时,我会问问指针指向的缓存对象的标 志位去决定我应该怎么做。如果标志是0,我会直接用新的缓存对象替代这个缓存对象;如果标志位是1,我会把头指针递增,然后重复这个过程,知道新的缓存对 象能够被放入。我比second chance更快。

Simple time-based:

我是 simple time-based 缓存算法,我通过绝对的时间周期去失效那些缓存对象。对于新增的对象,我会保存特定的时间。我很快,但是我并不适用。

Extended time-based expiration:

我是 extended time-based expiration 缓存算法,我是通过相对时间去失效缓存对象的;对于新增的缓存对象,我会保存特定的时间,比如是每5分钟,每天的12点。

Sliding time-based expiration:

我是 sliding time-based expiration,与前面不同的是,被我管理的缓存对象的生命起点是在这个缓存的最后被访问时间算起的。我很快,但是我也不太适用。

好了!听了那么多缓存算法的自我介绍,其他的缓存算法还考虑到了下面几点:

  • 成本。如果缓存对象有不同的成本,应该把那些难以获得的对象保存下来。
  • 容量。如果缓存对象有不同的大小,应该把那些大的缓存对象清除,这样就可以让更多的小缓存对象进来了。
  • 时间。一些缓存还保存着缓存的过期时间。电脑会失效他们,因为他们已经过期了。

根据缓存对象的大小而不管其他的缓存算法可能是有必要的。

原文:http://www.zavakid.com/27



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/general-cache-algorithms.html
posted @ 2011-01-21 14:13 88250 阅读(2757) | 评论 (0)编辑 收藏



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-133.html
posted @ 2011-01-20 00:19 88250 阅读(220) | 评论 (0)编辑 收藏

提交 B3log Solo(运行在 GAE/J 上的博客程序) 代码后发现 Google Code 版本控制系统会将提交日志同步发布到 Google Buzz 中:

code-buzz.png

但在 Buzz connected sites 里并没有看到与 Google Code 关联:

buzz-connected.png

 

现在一提交代码就 Buzz,还是比较无奈的....



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/code-buzz.html
posted @ 2011-01-14 10:04 88250 阅读(208) | 评论 (0)编辑 收藏



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-132.html
posted @ 2011-01-11 22:09 88250 阅读(242) | 评论 (0)编辑 收藏

有时我们需要随机地获取数据记录(实体),比如博客程序中的“随机文章”的实现。

目前 GAE 并没有 API 可以直接获取随机实体,要实现这样的需求我们只能自己想办法了 :-)

在 stackoverflow 上也有人提过该问题,总结如下:

  • Generate and store a random number on your entities as you create them, then pick a random number and look (via a query) for the closet record(s) to it.
  • Implement some mechanism to ensure your entity ids are "densely" populated, then fetch within the known range using keys.
  • Periodically generate random lists of the entities and return entities from those lists. This may take the form of a stack that entities are popped off of, or as actual lists that are returned.

目前 B3log Solo 在处理“随机阅读”上采用的是方法一,即在每个文章实体上添加一个属性保存 0-1 的随机浮点数。

在获取随机文章时生成一个 0-1 的随机数(mid)作为查询条件,以此查询条件作为边界(0 <= mid <=1)来过滤实体保存的随机值属性。

这个方法基本可以达到随机的效果了,为了让随机的效果更动态一点,我们可以考虑经常更新文章实体中的随机浮点值:

  • 访问文章时(即在更新文章浏览次数时一并更新该文章的随机浮点值)
  • 后台定时任务(获取一定数量的随机文章然后更新它们的随机浮点值)
  • 用户做文章更新时

加上以上处理后,随机的效果比较好了 :-)



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/get-gae-random-entities.html
posted @ 2011-01-10 21:16 88250 阅读(224) | 评论 (0)编辑 收藏

作者 荣浩 发布于 2010年12月28日 上午12时0分

jBPM来说,今年最大的事件莫过于jBPM的创建者Tom Baeyens离开JBoss了。Tom Baeyens离开的具体原因尚不清楚,但他的离开产生了两个结果:一是jBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过;二是Tom Baeyens加入Alfresco后很快推出了新的基于jBPM4的开源工作流系统Activiti。 由此不难推测Tom Baeyens离开的部分原因:JBoss内部对jBPM未来版本的架构实现产生了严重的意见分歧。更加巧合的是12月1日Activiti5刚发布,紧 接着12月2日jBPM5就发布了第一个候选发布版本,jBPM与Activiti之间的微妙关系可见一般。

在这篇文章里,我们将一起回顾jBPM从jBPM3到jBPM5以及Activiti5的发展历程,我们可以清晰的看见jBPM(包括 Activiti)设计所遵循的一致原则:强调流程服务的可嵌入性和可扩展性。同时,从各个版本之间的变化我们也能看见产品设计思路的变化:更加强调面向 业务人员,增加BPMS(业务流程管理系统)特性。

在回顾之前,我们首先讨论一下BPMS应该嵌入还是独立部署的问题,因为不管是jBPM还是Activiti,都强调了流程服务的可嵌入性。此外,我们还需要讨论一下什么是BPMS的特性,它们所解决的问题是什么。

一、嵌入式还是独立部署?

不管是jBPM还是Activiti,都强调了流程服务的可嵌入性。Tom Baeyens在其个人博客里称作为独立部署的BPMS已死,原因有两个:一是独立部署的BPMS需要很高的安装使用成本,需要独立部署、需要用户支出大 量的培训成本和维护成本;二是独立部署的BPMS与外部系统的交互方式是分布式,这使得很多问题变得复杂,例如分布式事务。Tom Baeyens代表了相当一部分人特别是开发人员的观点。

Tom Baeyens没有完全理解BPMS。什么是BPMS?BPMS最重要的目标就是需要打破各个应用系统(CRM、ECM、ERP、SCM)之间的界线,将 分散在这些系统中的流程集中管理,这是BPMS的实质。一如流程再造,打破各个部门之间的壁垒,减少浪费,建立流程驱动性的组织。如下图1所示:

图 1:BPMS打破应用系统之间的界线

BPMS所要解决的问题要求其必然是独立部署的。Tom Baeyens错误的根本原因在于其将BPMS与工作流系统的定义混为了一谈,他如此定义BPMS:BPMS旨在简化对组织核心流程进行支撑的软件创建。 也就是BPMS面向的是软件开发人员,旨在简化他们的开发,降低他们使用流程的门槛。而这正是工作流系统需要解决的问题。

BPMS面向企业用户,工作流面向开发社区和系统集成商。

二、BPMS特性

jBPM4、jBPM5和Activiti5都增加了其BPMS特性,那些特性能够称为BPMS特性呢?我们先看一看BPMS需要解决的问题,为解决这些问题所增加的特性就是BPMS特性。

  1. 如何设计流程,在组织中高效地对设计出的流程进行沟通,取得共识?

    • 提供跨越组织的流程标准标记符号与术语(BPMN已经成为标准)
    • 流程及相关文档的可视化(流程/内容存储仓库)
    • 提供在组织结构内进行不同层次之间的流程导航(流程存储仓库支持组织模型)
    • 流程定义在各个层次/部门间的一致性,避免业务人员的流程建模转换到IT系统时受到损耗(流程引擎支持基于图的建模,支持扩展)
  2. 如何更好地执行流程?

    • 业务活动的实时监控,预警与控制(BAM)
    • 流程执行的仿真
    • 流程执行的统计分析与反馈(报表)
  3. 如何更好地管理流程?
    • 打破各个应用系统之间的界线,统一管理所有流程(EAI,与ESB的集成)
    • 对业务人员友好的建模工具
  4. 如何在执行流程过程中遵循业内最佳实践和规则?
    • 面向流程的知识管理
    • 规则引擎

三、完整的工作流实现jBPM3

jBPM3的最新版本是3.2.7,其包括了以下组件:基于Eclipse的流程设计器、用于监控案例(流程实例)和处理任务的Web控制台以及jPDL核心库。如下图2所示:

图 2:jBPM3组件

  1. 基于Eclipse的流程设计器

    提供给开发人员绘制jPDL流程图,因为该设计器基于Eclipse,所以生成的流程文件可以与开发代码一起组织管理,非常容易进行单元测试。实现了工作流管理系统参考模型里的接口1。

  2. Web管理控制台

    主要有两个功能:一是作为工作流客户端应用接口,给用户提供一种手段,以处理案例运行过程中需要人工处理的任务;二是对案例的状态进行监控与管理。实现了工作流管理系统参考模型里的接口2和5。

  3. jPDL核心库

    jPDL核心库是一个单独的JAR包,可以嵌入到目标应用中执行,它包括了:

    • 流程仓库:解析jPDL流程定义文件并存储读取;
    • 流程引擎:对流程定义进行初始化和调度执行,节点的运行期行为与jPDL里定义的节点类型一一绑定;
    • 任务管理:生成任务节点所对应的工作项,管理工作项的生命周期(初始化、分配执行者、执行、挂起、结束、终止);
    • 事件管理:发布案例和任务的开始、结束事件,通过监听者模式调用相应的事件处理器;
    • 异步执行机制:通过线程实现了Job Executor,进行异步工作的处理,这些工作包括了时间处理、异步动作。
    • 身份组件模型:实现了一套简单的身份组件模型,包括了组、用户和权限。

    通过调用自定义Java代码实现了对外部应用的调用,从而实现工作流管理系统参考模型里的接口3。

  4. jBPM3是一个轻量级的嵌入式工作流系统。它在Java社区的成功得益于两个方面:一是嵌入式,这降低了使用工作流的门槛;二是对开发人 员友好,这表现在易读的jPDL、流程的可测试性(Eclipse插件)以及节点行为的可扩展性,我们可以非常容易的在流程运行中加入自己定制的行为(通 过事件处理器和Action)。jBPM3面向开发人员,它解决的问题是流程的自动化,它的影响力集中在Java开发社区,是一个完整的工作流系统实现。

四、向BPMS努力的jBPM4

与jBPM3相比,jBPM4最大的变化是引入了流程虚拟机(PVM),同时增加了BPMS的特性。jBPM4不再满足于工作流系统的定位,开始向BPMS努力。

  1. 为什么引入流程虚拟机

    尽管jBPM3在Java社区取得了很大的成功,但是有一件事始终被人们诟病,那就是它不支持流程语言规范,从最开始的XPDL、BPEL 到后来的BPMN,它采用了自定义的jPDL。在jBPM3中,节点的运行期行为与jPDL里定义的节点类型是一一绑定的,这造成了流程引擎与特定流程语 言的绑定,要支持其他的流程语言变得困难。于是在jBPM4中,jBPM提出了流程虚拟机的概念,即流程引擎与流程语言解耦,通过一套通用的流程模型并配 以可定制的节点运行期行为实现了对多流程语言的支持。

    流程虚拟机带来的好处是多方面的:第一也是最重要的是jBPM4支持了BPMN。

    第二是实现了基于流程组件的流程引擎,流程图(语言)与实现解耦,我们使用通用编程语言实现节点运行期行为,称之为流程组件,通过将流程图 与流程组件挂接,避免了图的损耗。在这一点上,Tom Baeyens对BPMN到BPEL的转换提出了一针见血的批评:BPMN和jPDL以及XPDL都是基于图的,而BPEL是基于块的,这造成了当将业务 人员使用BPMN所建立的流程模型向BPEL执行模型进行转换时,出现许多的不匹配,最初的流程模型会扭曲变形。而扭曲的后果就是业务人员与开发人员之间 的协作困难,这影响了流程从业务到技术的实现。

    第三个好处是我们可以定义领域特定语言(DSL),在特定的应用里,采用DSL约定并隐藏了大部分的技术细节可能做到业务人员对执行流程的直接修改,例如企业文档管理里的审批流程。

  2. BPMS特性的加入

    这表现在以下三个方面:第一是支持了BPMN,BPMN已经成为业务人员的流程建模标准;第二是引入了Signavio作为面向业务人员的Web建模器;第三是在已有的Web管理控制台加入了对案例和任务的统计功能。jBPM4的组件如下图3所示:

    图3:jBPM4组件

    和jBPM3一样,jBPM4依然是轻量级的、可嵌入的工作流系统。相比jBPM3,它将业务人员作为最终用户之一,增加了部分BPMS特性,同时PVM的引入使得它的可扩展性得到了极大的增强,我们甚至可以定义自己的DSL。

    在BPMS特性里我们提到了应该避免业务人员的流程建模转换到IT系统时受到损耗,最理想的情况是业务人员与开发人员共用一个流程模型,业 务人员能够直接对流程进行调整(在特定应用中,通过DSL是可以做到的);其次是通过BPMS将业务人员的模型与实际执行的技术模型关联起来(很多商业产 品已经做到了这一点,在Activiti5中我们也会看到这一点),业务人员、开发人员以及运营团队之间能够做到很好的协调;最差是业务人员与开发人员各 自为政,独立维护各自的流程模型,并且模型之间存在极大的不匹配,此时流程的迅速变化基本上是奢望。

五、鸠占鹊巢的Drools Flow与jBPM5

目前jBPM5刚刚发布了第一个候选发布版本,jBPM5基本上完全抛弃了jBPM4的代码,所有代码全部来自原先的Drools Flow。Drools Flow最初被用来解决规则执行顺序的问题。其实从Drools Flow开始支持BPMN时起,我们已经预感到它与jBPM的竞争关系。

jBPM5依旧定位为轻量级的可嵌入的工作流系统。在jBPM5的特性里,有这么两条引人关注:一是引入了Guvnor作为流程仓库,这解决了流程 的可视化问题,流程定义作为资源被管理,我们可以对流程定义进行可视化管理以及全文检索(Guvnor使用了Jackrabbit作为了其存储实现,但我 们的经验表明Jackrabbit在大数据量情况下性能存在严重问题);第二是规则引擎(Drools Expert)、事件处理引擎(Drools Fusion)与流程引擎的合三为一,这是jBPM5最让人期待的地方。jBPM5的组件如下图4所示:

图 4:jBPM5组件

规则引擎在流程中的应用已经非常广泛了,我们这里说说事件处理引擎。

事件处理引擎是业务活动监控(BAM)的基础,BAM的功能及执行过程,如下:

  • 捕获:BAM捕获各种事件(通过消息监听器、适配器、代理等)。这些事件来自应用、系统软件、外部交易伙伴。消息是BAM的核心——它们反应底层业务流程的状况。
  • 过滤:BAM过滤掉没有直接后果的事件,在很多情况下由支持事件流处理(Event Stream Processing,简称ESP)或复杂事件处理(Complex Event Processing,简称CEP)引擎来进行过滤。
  • 分析:BAM根据分析模型和规则将相关事件联系起来。
  • 警告:BAM向用户提出警告,以便用户在必要时进行控制。

如上所示,BAM的执行过程包含四个步骤,而前三个步骤都是对事件进行相关的处理(捕获事件、过滤事件、分析事件、关联事件),因此在大多数BAM的技术实现方案中,都基于CEP和ESP的引擎来实现BAM的功能。

与jBPM4相比,jBPM5对PVM的放弃也带来了几个不小的问题:第一是对开发人员来说只支持BPMN,不再支持jPDL(当然提供了迁移工 具);第二是流程执行的可扩展性回到了jBPM3的年代,仅仅支持自定义动作(相当于jBPM3里的Action)。此外,Web建模器由 Signavio替换为了Oryx Designer。

总而言之,jBPM5通过引入流程仓库和BAM继续向BPMS迈进(目前的进展是与流程仓库的集成还未完成,BAM基于日志进行分析),同时,由于不再支持PVM和jPDL,带来了流程扩展性的降低和社区开发人员的未来流失。

六、Activiti5的反击

Activiti5是Tom Baeyens加入Alfresco后推出的新的基于jBPM4的开源工作流系统,1号刚刚发布第一个版本。Activiti的开发团队相比与jBPM强 大了许多,有23位核心开发者。当然这也是由于activiti规划的功能所致:包括核心引擎、Web的流程建模器、协作工具Activiti Cycle、Activiti Probe、Activiti Explorer、与Spring的集成、与Mule的集成等。

图 5:Activiti5的组件

如上图所示,Activiti5由三种类型的组件组成,分别是:专用工具(Dedicated Tools)、内容存储工具(Stored Content)和协作工具(Collaboration Tool)。

专用工具包括以下:

  • Alfresco—Alfresco公司的企业级内容管理产品
  • Alfresco 是一个开源的、企业级的内容管理系统,功能包括:文档管理、协作、记录管理、知识库管理、Web内容管理等功能。Alfresco与Activiti的深 入集成实现了流程及相关文档的可视化。更重要的是Alfresco支持组织模型,能够提供在组织结构内进行不同层次之间的流程导航。

  • Activiti Modeler—建模器
  • 基于开源Signavio Web流程编辑器的一个定制版本,提供了对BPMN2.0图形化规范的支持,建模后的流程以文件格式进行存储。

  • Activiti Designer—Eclipse插件形式的建模器
  • Activiti probe—管理及监控组件
  • 对流程引擎运行期实例提供管理及监控的Web控制台。包含部署的管理、流程定义的管理、数据库表的检视、日志查看、事务的平均执行时间、失败多次的工作等功能。

  • Activiti Explorer—任务管理组件
  • 提供任务管理功能和对案例、任务基于历史数据的统计分析(报表)功能。Web应用程序。

内容存储工具:包括了文档仓库、模型仓库、SVN仓库、MVN仓库和Activiti引擎。其中文档仓库、SVN仓库和MVN仓库三个组件为协作工具(Activiti Cycle)提供底层的支撑。Activiti引擎则是以前的PVM。

协作工具:与jBPM4相比,Activiti5最令人瞩目的特性就在于它的协作工具组件。

Activiti Cycle完全是一种新类型的BPM组件。它是一个用来促进业务人员、开发人员和IT运营人员协作的Web应用程序。 在现实的场景中,业务文档有业务人员所持有,而软件程序由开发团队所管理,被部署的软件应用则被IT管理人员所管理。三者之间不能很好的协作。我们可以想 象这样一个场景,业务经理用文档来维护需求和visio格式的流程图,开发人员管理可执行的流程和大量的Java源文件而IT维护人员则管理部署在 Tomcat中的.war文件和存储在Activiti数据库中的流程。

图 6:Activiti cycle协作组件逻辑示意图

Activiti Cycle通过BusinessLink将与流程相关的业务人员、开发团队与IT维护人员关联起来,实现他们之间的协作。

总而言之,与jBPM4相比,Activiti5目前最重要的增强就是实现了流程的可视化以及创新的Activiti Cycle协作组件,此外,通过与Mule的集成加强了其集成能力。其对PVM的保留使其继承了jBPM4强大的可扩展能力,对jBPM的老用户来说,这是向其迁移的重要理由。

七、总结

jBPM3是一个完整的工作流系统实现,面向开发人员,目的在于简化对组织核心流程进行支撑的软件创建,不支持标准。

jBPM4引入PVM,使其拥有更强大的扩展性,同时增加BPMS特性,这些特性包括了对BPMN的支持、面向业务人员的Web建模器和简单统计分析功能的加入。

jBPM5基于原先的Drools Flow,支持BPMN,通过与Drools的合并支持BAM,通过内容仓库增加对流程可视化的支持。由于放弃了jBPM4的PVM,引擎的可扩展性受到损害,并且不再支持jPDL。

Activiti5基于jBPM4,与Alfresco的集成增加了其流程可视化与管理能力,同时通过创新的Activiti Cycle协作组件支持流程相关人员之间的协调,最后,它加强了集成能力。

对于工作流应用或者jBPM3、jBPM4的老用户,建议转向Activiti5。

关于作者

荣浩,ThoughtWorks咨询师,关注敏捷和企业流程改进过程,目前正与辛鹏合著《Head First Process-深入浅出IT流程》一书。博客地址http://ronghao.javaeye.com

转自:http://www.infoq.com/cn/articles/rh-jbpm5-activiti5



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/rh-jbpm5-activiti5.html
posted @ 2011-01-05 13:55 88250 阅读(8568) | 评论 (4)编辑 收藏

有很多理由都能说明为什么我们应该写出清晰、可读性好的程序。最重要的一点,程序你只写一次,但以后会无数次的阅读。当你第二天回头来看你的代码 时,你就要开始阅读它了。当你把代码拿给其他人看时,他必须阅读你的代码。因此,在编写时多花一点时间,你会在阅读它时节省大量的时间。

让我们看一些基本的编程技巧:

 

  1. 尽量保持方法简短
  2. 永远永远不要把同一个变量用于多个不同的目的
  3. 使用自描述的变量名和方法名
  4. 尽可能的把变量定义在靠近使用它的地方
  5. 拒绝神秘数字
  6. 友好的对待你的语言
  7. 不要逆常规而行
  8. 警惕过早优化
  9. 积极重构测试过的程序
  10. 不要过度沉迷于技巧
  11. 通过习例学习新知

现在,让我们把每个小点展开来详细讲一下。

1. 尽量保持方法简短

尽管很多人都遵循这个规则,但它仍然非常的重要。你写的方法要始终能在一个屏幕里放得下。如果你需要去滚动屏幕,这会分散你的注意力,而且你看不到 整个的上下文。最佳长度是5-20行,这根据你的情况而定。当然,getters/setters 通常是一行代码的方法,但与其说它们是真正的方法,不如说它们只是存取工具。

2. 永远永远不要把同一个变量用于多个不同的目的

一个变量应该始终只为一个目的服务。通过使变量常量化(C++里的const, Java里的final),使得编译器能够优化编译,而且使你的代码醒目表达这个变量是不能改变的,你的程序的可读性会变得更好。

3. 使用自描述的变量名和方法名

你的代码应该,对于任何人来说,只要看一眼就能知道是干嘛的。尽量不要用简写方式,除非有特殊的习惯,就像下面的:

 src - source
pos - position
prev - previous

如果你认为描述性的名称并不是那么有价值,请对比一下n, ns, nsisdnumTeamMembers, seatCount, numSeatsInStadium

4. 尽可能的把变量定义在靠近使用它的地方

盖房子时,你可不希望把锤子放到别人的院子里。你希望把它们放的离手头越近越好。定义变量也是同样的道理。

int foo = 3;
int bar = 5;
// 一大段使用“bar”的代码,
// 但没用到“foo”
// ...

baz(foo);

这段代码可以简单的重构成

int bar = 5;
// 一大段使用“bar”的代码,
// 但没用到“foo”
// ...

int foo = 3;
baz(foo);

当你把变量的声明和第一次用到它的地方间隔太远时(距离超过一个屏幕),这确实会成为一个问题。记住上下文关系会变得困难,你需要滚动屏幕去找哪来的这个变量。

5. 拒绝神秘数字

当你要把什么东西跟一个常量值做比较时,记得把这个值定义成常量。没有什么会比去猜测你的同事写的这样的代码更让人头疼的事了:

il < 4384

换个形式感觉如何?

inputLength < MAX_INPUT_LENGTH

6. 友好的对待你的语言

学习新语言是一种很有乐趣的事情,你能学到一种新的完成任务的途径。当一个对一种语言已经很专业的人去学习另一种语言时,会出现一种很大的负面效应。比如说你是一个Java开发者,试图去学习Ruby。你应该学会用Ruby的方式解决问题,而不是沿用Java的解决问题的思想。

当你需要重复5遍”Hello world!“时,在Java里,你可能会这样做:

for (int i = 0; i < 5; i++) {
System.out.println("Hello world!");
}

在Ruby里,你也许会禁不住这样写:

for i in (0..5)
puts "Hello world!"
end

这样看起来没问题,但有一个更好的方式:

5.times { puts "Hello world!" }

7. 不要逆常规而行

每种语言都有自己不同的习俗约定。一般来说,人们听的最多的是Java的编码规范。让我们看看其中的一些习俗规范:

  • 方法名应该小写字母开头,其后用字母大写的单词连接(veryLongVariableName)
  • 类名应该都使用首字母大写的单词连接而成
  • 常量名应该全部大写,用下划线连接(MY_CONSTANT)
  • 左大括号应该跟 if 语句在同一行

只有在有必要的理由时才去打破这些常规,不要轻易的因为你不高兴就违反它。如果你只是在团队里改变一些这样的习惯,那也没问题,但当把你代码拿出来和其他的没有这些思想准备的程序员共享时,问题就会来了。

8. 警惕过早优化

过早优化是所有问题的根源,至少电视上是这么说的 … 你第一应该关心的事情是写出易于理解的代码。起初写的程序不要求快。除非你的程序很慢,否则谈优化都是为时太早。如果你想优化什么东西,你首先需要知道问题出在哪。这就是我们需要profilers这个工具的原因。

在没有知道问题在哪的情况下试图对程序进行优化,其结果必然是把程序能坏,至少你的代码会丧失可读性。如果你觉得有些地方很慢,不要盲目的重写代码,你应先找到慢的证据

不要傻乎乎的去解决根本不存在的问题。

9. 积极重构测试过的程序

没有任何东西会是完美的。即使你感觉你真正写出了一段完美的代码,几个月后回头再看看,你可能会惊讶道”怎么会这样傻?“

改进程序的一个好方法就是重构,但要等程序测试通过之后。你首先要确保程序是好的可运行的,你可以通过自动化测试或手工测试完成这个工作。

之初,你需要的是程序可用。不要期望在第一次就写出完美的程序,你只需要把它写出来,可用。然后重构它,使之完美。对于你们当中知道测试驱动开发 (TDD)的人来说,对这个会很熟悉。这里的关键就在于你要习惯于重构这种事情。如果你使用的是像IntelliJ IDEA这样强大的集成开发工具的话,重构的工作会变得简单的多。

重构之后,你也许会弄出一些Bug,导致某些功能出问题。这就是为什么说写自动化测试的原因。不论何时重构后,只要运行一下所有的测试用例,你就能准确的知道什么地方出了问题。

10. 不要过度沉迷于技巧

当我第一次读到有关设计模式的知识时,我觉得我找到了圣杯。这些精心设计的思想作用显著,它能使你的设计易于理解,因为你可以简单的说”我使用的是 ‘观察器模式’“,而不用从头到尾的解释一遍。那么,有问题吗?一切看起来都这么自然、简单,你开始不论在哪都使用设计模式。为什么不把这个类做成 singleton呢?干嘛不去再创建一些工厂类呢?

于是一个80行就能写完的脚本,你最终使用了10个类,15个接口,外加一大堆范式和标记符。97%的代码不做任何事情。设计模式是一种十分有用的用来简化你的设计的工具,但这不意味着你该在所有能用到的地方都用它。你应该用它们,但不能滥用。

11. 通过习例学习新知

编程是一种学习新知的过程。当你学到了新的程序库或新语言,你可能会迫不及待的丢掉旧的代码,用你新学到的东西重新写一遍。有很多的理由都能说明你不该这么做。

往现有的应用里增加新的类库或框架同属于这种情况。就说你写了一个Javascript的web应用,期间,你发现了jQuery。现在你突然急切的想丢到你的Javascript程序,重新用jQuery写,尽管你还从来没用过它。

最好的方式是你先用jQuery写一些简单的例子,通过这种方式把你在应用里将要用到的知识都学会。需要AJAX?在你的项目之外做一些小例子,当完全弄懂了后,丢掉例子,应用到你的产品里。

如果你非常关注编程技术,我强烈的推荐你阅读Steve McConnell写的 《代码大全》 一书。它会永远的改变你对编程的认识。:)

 

[英文出处]:11 tips for better code

[译文来源]:外刊IT评论



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/11-tips-for-better-code.html
posted @ 2011-01-05 09:08 88250 阅读(325) | 评论 (0)编辑 收藏



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-131.html
posted @ 2011-01-04 10:14 88250 阅读(219) | 评论 (0)编辑 收藏

“我说我是警察,也是执法 人员,应该文明执法,但还是被打断腿!”昨天,躺在病床上,昆明市 公安局民警张俊(化名)说起事发当天的情形时,依然有些愤怒!当天他接到母亲的电话,说辖区城管要强行拆除小区内的违章建筑,让他回家收拾东西。不料,张 俊刚到门口表明自己身份时,却遭到拆迁执法人员的围殴。据小区目击者称,张俊被殴打时,对方扬言“打的就是警察!”。

“我还以为身上有警械,就能够证明自己身份。”昨天下午,在解放军昆明总医院骨科住院部,记者见到了被打伤的张俊,他向记者讲述了事发经过。

“我是警察,也是执法人员。”张俊说,为了阻止自己被继续殴打,他一边表明自己的身份,一边准备从身上掏证件。慌忙中,张俊只摸到了自己随身携带的一根伸缩警棍,这一摸不要紧,更是遭了对方一顿暴打。

当 时现场执法人员叫张俊放下警棍,然后将他的警棍拿走。张俊说,第一次被打之后,自己的鼻子和嘴角已经被打出血了。但噩运还没有结束,之后,他被4名城管反 绑着双手押到邻居家的门前。他再次向执法人员提出要回家收拾东西,但没有人理他。听到他的反复要求后,一名执法人员转头对他说:“你拿警棍打我,怎么可能 让你上去。”张俊表示,他拿出警棍根本没有打到人。“我是市公安局的,也是执法者,执法要文明。”张俊说完时就听到对方一句狂喷:“你敢用手指头指我,兄 弟们,拿下。”

张俊说,他只感觉周围的20多名城管全部围了上来,用警棍和铁棍将他打倒在地,还有人上前用脚踩他。当时他感觉自己的右腿很疼,他大声恳求:“求求你们别打了,我的腿断了。”随后,他被打晕在地。

现 场很多小区业主都目睹了张俊被殴打的过程,“总共被打了两次。”张俊的邻居老邢说。同样目睹事情经过的程先生也说,张俊大概被殴打了10多分钟,他远远看 着张俊满脸都是血,倒在地上。他听到在场的一位执法人员对着几乎快晕厥过去的张俊喊道:“装死。”张俊的好友陈小姐说,现场就有执法人员带去的救护车,但 没有对他进行救治。

而对此,当时执法拆除违章建筑的昆明市综合行政执法局盘龙分局负责人称,是张俊先挥舞警棍导致冲突发生。

据知情人称,事件发生之后,已经有一名参与冲突的执法队长被拘留,但此说法未得到有关部门的证实。

转自:http://news.qq.com/a/20110103/000492.htm?qq=0&ADUIN=845765&ADSESSION=1294033435&ADTAG=CLIENT.QQ.3187_.0



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2011/01/03/1294035696457.html
posted @ 2011-01-03 14:22 88250 阅读(163) | 评论 (0)编辑 收藏

过去与今天
词 \ 黄家驹. 曲 \ 黄家驹. 主唱 \ 黄家驹.

夜雨街中里宁与静
雾色灯影照我身
在我的心里常会问
幻变的都市四周
可知我已放弃旧日的理想
知否我也有个梦 要我醉倒
就像 就像 就像
像那方的星光闪动 眼也会发光
仰望浮云常变不定 暗里叹一声
冲出他朝崎岖道上 哪怕会退倒
试问谁人曾会考虑 过去与今天
踏破这黑暗宁与静
谁会管失意冷风
幻变的都市谁问过
让暖风紧靠我身



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/31/1293811895091.html
posted @ 2011-01-01 00:12 88250 阅读(144) | 评论 (0)编辑 收藏

EverBox LogoEverBox 是一款由盛大创新院推出的网盘产品,提供数据存储和同步服务。EverBox 提供了 10GB 超大免费存储空间,支持文件同步、文件分享、在线浏览照片、在线听音乐等功能,并支持数据同步客户端。需要邀请的朋友可以改我留言 :-)

 

主要功能:

支持数据同步客户端:安装 EverBox后,您所需的文件都将自动同步到设备上,可以随时、随地的使用手边的任意一款设备访问文件了。目前提供了 Windows 客户端程序,支持 Windows XP,Windows Vista 和 Windows 7。在以后的版本中,EverBox 将会陆续推出其他客户端程序,如: Android,iPhone,iPad,Mac,Linux 等。

容灾备份服务:EverBox 会自动的、实时的备份文件数据到 EverBox 安全服务器,因此,当您本地的设备坏损或丢失时,不必担心由于数据丢失造成的损失,恢复数据易如反掌!

在线音乐播放:EverBox 支持在线音乐播放功能,几乎支持所有常用的音频格式,使用简单、便捷,无需操作即可连续播放 EverBox 当前目录中的歌曲,很适于一边使用电脑一边听歌时使用。

在线浏览图片:EverBox 支持在线浏览图片功能,几乎支持所有常用的图片格式,操作简单、便捷,并支持自动播放 EverBox 当前目录中的图片文件。

EverBox 功能特性

  1. 10GB 超大免费空间

    成功注册 EverBox 即可获得 2GB 免费空间,完成指定任务可升级空间到 10GB!EverBox 在随后的版本中将会有更多的奖励措施,赠送活跃用户更多空间,敬请期待!

  2. 支持数据同步客户端

    您是不是经常遇到以下的情况?“我喜欢在外出时用 iPhone 听歌,但是我需要从 PC 下载歌曲再用数据线将 MP3 导到 iPhone”;“我经常出差,但是程序和文件都在笨重的 PC 上,而我只带着笔记本”;“我到 XX 会议做演讲,但是保存 PPT 的 U 盘坏掉了”。

    现在有了 EverBox,这些问题将迎刃而解!只需安装 EverBox,您所需的文件都将自动同步到设备上,您就可以随时、随地的使用手边的任意一款设备访问文件了。当然,使用浏览器一样可以访问到您需要的文件。

  3. 容灾备份服务

    硬盘损坏?数据无法访问?笔记本电脑被盗?完了,重要的数据丢失了!

    不用担心,有了 EverBox,这一切都不会再是问题。EverBox 会自动的、实时的备份文件数据到 EverBox 安全服务器,因此,当您本地的设备坏损或丢失时,不必担心由于数据丢失造成的损失,恢复数据易如反掌!

  4. 在线音乐播放

    EverBox 支持在线音乐播放功能,几乎支持所有常用的音频格式,使用简单、便捷,无需操作即可连续播放 EverBox 当前目录中的歌曲,很适于一边使用电脑一边听歌时使用。

  5. 在线浏览图片

    EverBox 支持在线浏览图片功能,几乎支持所有常用的图片格式,操作简单、便捷,并支持自动播放 EverBox 当前目录中的图片文件。

     



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/everbox-invite.html
posted @ 2010-12-31 10:09 88250 阅读(201) | 评论 (0)编辑 收藏

B3log LogoGAE 博客 —— B3LOG Solo 0.2.5 Beta1 发布了。

该版本除了修复 Bugs,还增加了草稿夹、多人写作、改进了缓存,以及加入了新皮肤 community。

借此机会,祝大家圣诞节愉快,一切平安 :-)

新特性

  • 多人写作
  • 链接排序
  • 新皮肤——community(多人写作皮肤)

Bug 修复

  • 缓存多实例不一致
  • 文章访问次数统计失效
  • IE8 下 Feed 不能显示

改进

  • 存储对象缓存
  • 自定义页面排序方式
  • 改进了页面缓存

具体改动看这里

升级

如果您是 0.2.1 的用户,那么请在部署完 0.2.5 Beta1 后登录后台,访问 http://${application-id}.appspot.com/upgrade/v021-v025.do 进行升级。

项目

如果在使用、测试中发现任何问题,如果您有任何意见或建议,请告知我们 :-)

发布计划

  • 2011 年 1 月 21 日发布 0.2.5 Beta2
  • 2011 年 2 月 14 日发布 0.2.5

作者博客

发布历史

  1. GAE 博客——B3log Solo 0.2.1 发布了!
  2. GAE 博客——B3log Solo 0.2.0 发布了!
  3. GAE 博客——B3log Solo 0.1.1 发布了!
  4. B3log Solo 0.1.0 发布了!
  5. B3log Solo 0.1.0-preview2 发布了!
  6. Solo 0.1.0-Preview1 发布了


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/b3log-solo-release-025-beta1.html
posted @ 2010-12-24 21:31 88250 阅读(143) | 评论 (0)编辑 收藏



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-130.html
posted @ 2010-12-23 15:36 88250 阅读(184) | 评论 (0)编辑 收藏

GAEAmazon WS

最近一个潜在客户要求我们比较一下 Amazon EC2 和 Google App Engine,正好我们刚刚在 EC2 和 Google App Engine 上完成了两个相对来说规模较大的项目,因此有必要做一下总结。

我打算从三个角度来对比这两大云计算平台:技术,业务和未来发展趋势,本文是技术方面的对比,ok,准备好咖啡,我们开始吧!

 

如果按平台类型来分,大家可能已经知道Google App Engine属于PaaS(平台即服务),而Amazon EC2属于IaaS(基础设施即服务),Amazon EC2给你一个安装了操作系统的“盒子”,你可以自己安装应用程序,也可以使用AMI(Amazon Machine Image),如果你想构建一个高度复杂的定制应用,Amazon EC2是不二之选,它允许你控制环境参数,底层操作系统,存储和网络需求,从技术上讲,它属于很底层的服务,你可以调整你需要的大部分东西。

Google App Engine给你一个完整的平台,包括完整的SDK(以及Eclipse插件)和服务,你可以构建和部署你自己的应用程序,但你不能很好地控制操作系统, 硬件和存储,诸如写文件系统,使用线程等操作都有限制,这样设计的目的是为了确保平台不会被某个应用程序绑架。

简单起来就是:

IaaS:原始硬件(处理器,网络和存储)

PaaS:操作系统,系统软件,开发框架和虚拟机。

下面从技术角度来比较一下这两个平台。

1、提供的服务

Google App Engine凭借丰富的服务击败Amazon EC2,Google App Engine提供的服务可以让开发人员快速进入开发状态。如 Blobstore,Images,Mail,Memcache,Multitenancy,Oauth,Task Queues,URL Fetch,Users,XMPP这些服务在Amazon EC2上是需要自己安装的,为了便于比较,假设你已经为Memcache,Mail和多租户搭建好了基础设施,看看在EC2上你用了多长时间安装,我敢打 赌你会超过一个小时,使用Google App Engine时,这些服务都是现成的,就象果盘中插好牙签的水果一样,你可以随时享用。

2、管理

Google App Engine再次胜出,因为一旦你的应用程序部署成功后,它几乎不需要管理,当你的应用程序负载变大时,你不需要向服务注入新的实例,Google App Engine可以自由扩大负载能力,新实例是实时剥离的。使用Amazon EC2时,你必须时刻跟踪通信流量(现在可以通过脚本自动跟踪了),新实例是在你的配置基础上剥离的,因此,如果我的峰值负载是2x+y,那么需要剥离2 个以上的应用程序服务器。

此外,使用Google App Engine升级应用程序服务器实例,安装新的负载均衡器时,没有管理开销,这一切都是自动执行的。

3、抽象水平

和上一条联系紧密的是抽象水平,Google App Engine抽象得比较好,你只需要关心你的应用程序和业务逻辑,不用担心底层基础设施的管理,正如Nick Johnson所说的那样,抽象水平应作为挑选云计算平台的一个基本原则,你需要做的是驾驶,不需要研究引擎盖以下的东西。在我看来,如果你的核心业务是 货物运输,那么你应该买一辆卡车,它能高效地把你的货物从A地运输到B地,相反,你不应该考虑如何购买零部件自己组装一辆卡车。

在软件开发领域,我们看到有Grails,RoR等框架,它们大受欢迎,是因为它们提供了高水平的抽象,如果你是一名泥瓦匠,它们就象是脚手架,你可以踩在它们上面干你的工作。

4、可靠性

从我个人的认识来讲,两者都很可靠,这一点从它们的用户数量就可以知道一二,用户可以时刻查看Google App Engine的状态,它是透明的,但从历史数据来看,Amazon EC2的正常运行时间比Google App Engine要好。

5、可移植性

从使用的底层操作系统和开发框架来看,Amazon EC2具有更好的可移植性,但也不要担心你会被Google App Engine给锁住,Google已经给出了迁移指南,指导你如何从转移出Google App Engine平台,当然包含你所有的数据在内。还有AppScale这样的程序可以帮助你将Google App Engine上的程序转移到Amazom EC2或其它云平台上,AppScale已经可以支持EC2,Eucalyptus,Xen和KVM。

6、存储

Google App Engine目前严重依赖于BigTable,开发人员需要从一个完全不同的角度来认识和学习它,特别是对于那些特熟悉关系数据库,被关系数据库理论束缚 的人更需要洗洗脑,它提供了一个JPA&JDO访问接口,但它不支持所有的JPA&JDO功能,特别是关系部分,Google最近也高调 宣布要让Google App Engine支持传统的SQL数据库。Amazon EC2已经支持SQL数据库,你可以使用Oracle,MySQL等你所熟悉的关系数据库。

7、应用程序维护和升级

对Google App Engine来说,应用程序维护和升级是件轻而易举的事,它为各种应用程序提供了一个详细的管理面板,包括日志查看器和数据查看器,一个程序可以有多个版 本,当新版本经过测试,可以用于生产环境时,你可以将其设为默认的版本,而Amazon EC2就麻烦多了,因为它属于IaaS类型,所有维护和升级相关的事情你必须亲力亲为。

8、开发限制

使用Google App Engine时,你必须受到平台的限制,如果你的查询处于僵死状态,很难将其杀掉,此外,Google App Engine没有线程,提供的SDK也是受限的,有些类和功能被列入黑名单,因此不能被使用,也不能写文件系统等等。

从表面上看这些限制是不可理喻的,但如果有朝一日你也要提供PaaS类型的平台时,你就能理解为什么Google要做这些限制了,这样才能确保运行 在平台上的应用程序不会违反平台的规则,否则平台就可能被应用程序绑架,从而变得不可使用,平台上的其它应用程序就会收到牵连。

即便有这些限制,90%的商业应用程序仍然可以在Google App Engine上正常运行,但对于那些要使用线程,或写文件系统的应用,最好还是选择Amazon EC2,因为它提供了所有底层访问和控制权。

9、语言支持

截至目前,Google App Engine支持Java和Python,但任何可以转换成字节码,可在JVM上执行的任何编程语言都可以在Google App Engine上运行,如果你喜欢其它编程语言,最好选择Amazon EC2,因为你可以在它的操作系统上面安装语言运行时环境,你拥有几乎完整的硬件和操作系统控制权,还有什么不能做的呢?在Amazon EC2上也托管了许多有趣的C#,.NET,ASP.NET MVC/Visual Studio项目,具有讽刺意味着的是,尽管还有Microsoft Azure,但许多以MS技术开发的项目却托管在Amazon EC2上。

概括地说,Amazon EC2是进入云计算的早期尝试者,它利用互联网标准和开放平台创建了一个非常灵活的云计算平台,Google则利用了它在大型数据库方面的研究成果和它内 部实现的一些技术创建了一个强大,但有更多限制的云计算环境。从核心技术来讲,Amazon EC2允许你扩展任何计算机实例到多个实例,因此你拥有每个虚拟盒子的完全控制权,Google App Engine从操作系统抽象而来,没有计算机实例的概念,如果你的Web应用程序不需要操作系统相关的功能,那么Google App Engine无疑是最好的选择,如果需要更好地控制你的系统环境,特别是操作系统相关的控制,那么最好选择Amazon EC2。

原文名:Comparing Google App Engine and Amazon EC2 on Technology 作者:Vikas Hazrati



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/ec2-vs-gae.html
posted @ 2010-12-22 15:21 88250 阅读(150) | 评论 (0)编辑 收藏

有人在Stack Overflow上发问,动手开发网站之前,需要知道哪些事情?

不出意料地,他得到了一大堆回答。

通常情况下,你需要把所有人的发言从头到尾读一遍。但是,Stack Overflow有一个很贴心的设计,它允许在问题下方开设一个wiki区,让所有人共同编辑一个最佳答案。于是,就有了下面这篇文章,一共总结出六个方面共计61条"网站开发须知"。

我发现,这种概述性的问题,最适合这种集合群智、头脑风暴式的回答方式了。这也是我第一次觉得,Stack Overflow做到了Wikipedia做不到的事。(难怪它最近挤进了全美前400大网站。)

在我的印象中,关于网站开发,这样全面的概述性文章非常少见,因此也就非常有用。大家不妨看看,61件事情中你做到了多少?

(更新:刚刚发现,一共应该是62条建议,我先前数错了,这个......太窘了。)

=============================

网站开发人员应该知道的61件事

原文网址:http://stackoverflow.com/questions/72394

译者:阮一峰

一、界面和用户体验(Interface and User Experience)

1.1

知道各大浏览器执行Web标准的情况,保证你的站点在主要浏览器上都能正常运行。你至少要测试以下引擎:Gecko(用于Firefox)、Webkit(用于SafariChrome和一些手机浏览器)、IE(你可以利用微软发布的Application Compatibility VPC Images进行测试)和Opera。同时,不同的操作系统,可能也会影响浏览器如何呈现你的网站。

1.2

除了浏览器,网站还有其他使用方式:手机、屏幕朗读器、搜索引擎等等。你应该知道在这些情况下,你的网站的运行状况。MobiForge提供了手机网站开发的一些相关知识。

1.3

知道如何在基本不影响用户使用的情况下升级网站。通常来说,你必须有版本控制系统(CVS、Subversion、Git等等)和数据备份机制(backup)。

1.4

不要让用户看到那些不友好的出错提示。

1.5

不要直接显示用户的Email地址,至少不要用纯文本显示。

1.6

为你的网站设置一些合理的使用限制,一旦超过门槛值,就自动停止服务。(这也与网站安全相关。)

1.7

知道如何实现网页的渐进式增强(progressive enhancement)。

1.8

用户发出POST请求后,总是将其重导向(redirect)至另外一个网页。

1.9

不要忘记网站的可访问性(accessibility,即残疾人如何使用网站)。对于美国网站来说,有时这是法定要求WAI-ARIA有一些这方面很好的参考资料。

二、安全性(Security

2.1

阅读《OWASP开发指南》,它提供了全面的网站安全指导。

2.2

了解SQL注入(SQL injection)及其预防方法。

2.3

永远不要信任用户提交的数据(cookie也是用户端提交的!)。

2.4

不要明文(plain-text)储存用户的密码,要hash处理后再储存。

2.5

不要对你的用户认证系统太自信,它可能很容易就被攻破,而你事先根本没意识到存在相关漏洞。

2.6

了解如何处理信用卡

2.7

在登录页面及其他处理敏感信息的页面,使用SSL/HTTPS

2.8

知道如何对付session劫持(session hijacking)。

2.9

避免"跨站点执行"(cross site scripting,XSS)。

2.10

避免"跨域伪造请求"(cross site request forgeries,XSRF)。

2.11

及时打上补丁,让你的系统始终跟上最新版本。

2.12

确认你的数据库连接信息的安全性。

2.13

跟踪攻击技术的最新发展,以及你使用的平台的最新安全漏洞。

2.14

阅读Google的《浏览器安全手册》(Browser Security Handbook)。

2.15

阅读《网络软件的黑客手册》(The Web Application Hackers Handbook)。

三、性能(Performance)

3.1

只要有可能,就使用缓存(caching)。正确理解和使用HTTP cachingHTML5离线储存

3.2

优化图片。不要把一个20KB的图片文件,作为重复出现的网页背景图案。

3.3

学习如何用gzip/deflate压缩内容(deflate方式更可取)。

3.4

将多个样式表文件或脚本文件,合为一个文件,这样可以减少浏览器的http请求数,以及减小gzip压缩后的文件总体积。

3.5

浏览Yahoo的Exceptional Performance网站,里面有大量提升前端性能的优秀建议,还有他们的YSlow工具。Google的page speed则是另一个用来分析网页性能的工具。两者都要求安装Firebug

3.6

如果你的网页用到大量的小体积图片(比如工具栏),就应该使用CSS Image Sprite,目的是减少http请求数。

3.7

大流量的网站应该考虑将网页对象分散在多个域名(split components across domains)。

3.8

静态内容(比如图片、CSS、JavaScript、以及其他cookie无关的网页内容)都应该放在一个不需要使用cookie的独立域名之上。因为域名之下如果有cookie,那么客户端向该域名发出的每次http请求,都会附上cookie内容。这里的一个好方法就是使用"内容分发网络"(Content Delivery Network,CDN)。

3.9

将浏览器完成网页渲染所需要的http请求数最小化。

3.10

使用Google的Closure Compiler压缩JavaScript文件,YUI Compressor亦可。

3.11

确保网站根目录下有favicon.ico文件,因为即使网页中根本不包括这个文件,浏览器也会自动发出对它的请求。所以如果这个文件不存在,就会产生大量的404错误,消耗光你的服务器的带宽。

四、搜索引擎优化(Search Engine Optimization,SEO)

4.1

使用"搜索引擎友好"的URL形式,比如example.com/pages/45-article-title,而不是example.com/index.php?page=45。

4.2

不要使用"点击这里"之类的超级链接,因为这样等于浪费了一个SEO机会,而且降低了"屏幕朗读器"(screen reader)的使用效果。

4.3

创建一个XML sitemap文件,它的缺省位置一般是/sitemap.xml(即放在网站根目录下)。

4.4

当你有多个URL指向同一个内容时,在网页代码中使用<link rel="canonical" ... />

4.5

使用Google的Webmaster Tools和Yahoo的Site Explorer

4.6

从一开始就使用Google Analytics(或者开源的访问量分析工具Piwik)。

4.7

知道robots.txt的作用,以及搜索引擎蜘蛛的工作原理。

4.8

将www.example.com的访问请求导向example.com(使用301 Moved Permanently重定向),或者采用相反的做法,目的是防止Google把它们当做两个网站,分开计算排名。

4.9

知道存在着恶意或行为不正当的网络蜘蛛。

4.10

如果你的网站有非文本的内容(比如视频、音频等等),你应该参考Google的sitemap扩展协议

五、技术(Technology)

5.1

理解HTTP协议,以及诸如GET、POST、sessions、cookies之类的概念,包括"无状态"(stateless)是什么意思。

5.2

确保你的XHTML/HTMLCSS符合W3C标准,使得它们能够通过检验。这可以使你的网页避免触发浏览器的古怪行为(quirk),而且使它在"屏幕朗读器"和手机上也能正常工作。

5.3

理解浏览器如何处理JavaScript脚本。

5.4

理解网页上的JavaScript文件、样式表文件和其他资源是如何装载及运行的,考虑它们对页面性能有何影响。在某些情况下,可能应该将脚本文件放置在网页的尾部

5.5

理解JavaScript沙箱(Javascript sandbox)的工作原理,尤其是如果你打算使用iframe。

5.6

知道JavaScript可能无法使用或被禁用,以及Ajax并不是一定会运行。记住,"不允许脚本运行"(NoScript)正在某些用户中变得流行,手机浏览器对脚本的支持千差万别,而Google索引网页时不运行大部分的脚本文件。

5.7

了解301重定向和302重定向之间的区别(这也是一个SEO相关问题)。

5.8

尽可能多得了解你的部署平台(deployment platform)。

5.9

考虑使用样式表重置(Reset Style Sheet)。

5.10

考虑使用JavaScript框架(比如jQueryMooToolsPrototype),它们可以使你不用考虑浏览器之间的差异。

六、解决bug

6.1

理解程序员20%的时间用于编码,80%的时间用于维护,根据这一点相应安排时间。

6.2

建立一个有效的错误报告机制。

6.3

建立某些途径或系统,让用户可以与你接触,向你提出建议和批评。

6.4

为将来的维护和客服人员撰写文档,解释清楚系统是怎么运行的。

6.5

经常备份!(并且确保这些备份是有效的。)除了备份机制,你还必须有一个恢复机制。

6.6

使用某种版本控制系统储存你的文件,比如SubversionGit

6.7

不要忘记做单元测试(Unit Testing),Selenium之类的框架会对你有用。

(完)

转自:http://www.ruanyifeng.com/blog/2010/11/61_things_every_web_developer_should_know.html



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/61_things_every_web_developer_should_know.html
posted @ 2010-12-21 17:05 88250 阅读(198) | 评论 (0)编辑 收藏

Memcached Banner
Martin Brown, 自由撰稿人, Freelance Developer

简介: 开源 memcached 工具是一个用来存储常用信息的缓存,有了它,您便无需从缓慢的资源,比如磁盘或数据库,加载(并处理)信息了。该工具可部署在专用的情况下,也可作为用完 现有环境内的多余内存的一种方法。尽管 memcached 十分简便,但有时它仍被不当使用,或被用在错误的环境类型中。在本文中,了解使用 memcached 的最佳时机。

简介

memcached 常被用来加速应用程序的处理,在这里,我们将着重于介绍将它部署于应用程序和环境中的最佳实践。这包括应该存储或不应存储哪些、如何处理数据的灵活分布以 及如何调节用来更新 memcached 和所存储数据的方法。我们还将介绍对高可用性的解决方案的支持,比如 IBM WebSphere® eXtreme Scale。

所有的应用程序,特别是很多 web 应用程序都需要优化它们访问客户机和将信息返回至客户机的速度。可是,通常,返回的都是相同的信息。从数据源(数据库或文件系统)加载数据十分低效,若是每次想要访问该信息时都运行相同的查询,就尤显低效。

虽然很多 web 服务器都可被配置成使用缓存发回信息,但那与大多数应用程序的动态特性无法相适。而这正是 memcached 的用武之地。它提供了一个通用的内存存储器,可保存任何东西,包括本地语言的对象,这就让您可以存储各种各样的信息并可以从诸多的应用程序和环境访问这些信息。


基础知识

memcached 是一个开源项目,旨在利用多个服务器内的多余 RAM 来充当一个可存放经常被访问信息的内存缓存。这里的关键是使用了术语缓存:memcached 为加载自他处的信息提供的是内存中的暂时存储。

比如,考虑这样一个典型的基于 web 的应用程序。即便是一个动态网站可能也会有一些组件或信息常量是贯穿页面整个生命周期的。在一个博客站点内,针对单个 blog post 的类别列表不大可能在页面查看间经常性地变更。每次都通过一个对数据库的查询加载此信息相对比较昂贵,特别是在数据没有更改的情况下,就更是如此。从图 1 可以看到一个博客站点内可被缓存的页面分区。


图 1. 一个典型的博客页面内的可缓存元素
此图显示了可缓存的 blog 元素及其布局:顶部是 Page Header,左边是当前的 Current post lists,右边是 About、Post History、External Links 和 Category list

将这种结构放在 blog 站点的其他元素,poster 信息、注释 — 设置 blog post 本身 — 进行推断,可以看出为了显示主页的内容很可能需要发生 10-20 次数据库查询和格式化。 每天对数百甚至数千的的页面查看重复此过程,那么您的服务器和应用程序执行的查询要远远多于为了显示页面内容所需执行的查询。

通过使用 memcached,可以将加载自数据库的格式化信息存储为一种可直接用在 Web 页面上的格式。并且由于信息是从 RAM 而不是通过数据库和其他处理从磁盘加载的,所以对信息的访问几乎是瞬时的。

再强调一下,memcached 是一个用来存储常用信息的缓存,有了它,您便无需从缓慢的资源,比如磁盘或数据库,加载并处理信息了。

对 memcached 的接口是通过网络连接提供的。这意味着您可以在多个客户机间共享单个的 memcached 服务器(或多个服务器,如本文稍后所示的)。这个网络接口非常迅速,并且为了改善性能,服务器会故意不支持身份验证或安全性通信。但这不应限制部署选项。 memcached 服务器应该存在于您网络的内部。网络接口的实用性以及可以部署多个 memcached 实例的简便性让您可以使用多个机器上的多余 RAM 来提高您缓存的整体大小。

memcached 的存储方法是一个简单的键/值对,类似于很多语言内的散列或关联数组。通过提供键和值来将信息存储到 memcached 内,通过按特定的键请求信息来恢复信息。

信息会无限期地保留在缓存内,除非发生如下的情况:

  1. 为缓存分配的内存耗尽 — 在这种情况下,memcached 使用 LRU(最近最少使用)方法从此缓存删除条目。最近未曾使用的条目会从此缓存中先删除,最旧的最先访问。
  2. 条目被明确删除 — 总是可以从此缓存内删除条目。
  3. 条目过期失效 — 各条目均有一个有效的期限以便针对此键存储的信息在过于陈旧时可从缓存中清除这些条目。

上述这些情况可以与您应用程序的逻辑综合使用以便确保缓存内的信息是最新的。有了这些基础知识后,让我们来看看在应用程序内如何能最好地利用 memcached。


何时使用 memcached

在使用 memcached 改进应用程序性能时,可以对一些关键的过程和步骤进行修改。

在加载信息时,典型的场景如图 2 所示。


图 2. 加载要显示的信息的典型顺序
此图显示了从加载数据到处理/格式化数据再到发送数据至客户机的流程

一般而言,这些步骤是:

  1. 执行一个或多个查询来从数据库加载信息
  2. 格式化适合于显示(或进一步处理)的信息
  3. 使用或显示格式化了的数据

在使用 memcached 时,为配合这个缓存,可对应用程序的逻辑进行稍许修改:

  • 尽量从缓存加载信息
  • 如果存在,使用信息的被缓存版本
  • 如果它不存在:
    1. 执行一个或多个查询来从数据库加载信息
    2. 格式化适合于显示或进一步处理的信息
    3. 将信息存储到缓存内
    4. 使用格式化了的数据

图 3 是对这些步骤的总结。


图 3. 在使用 memcached 时加载适合于显示的信息
此图显示了如果所请求的数据位于缓存内,它就会跳过所有处理步骤,节省了时间

数据加载成为了至多三个步骤的一个过程,从缓存加载数据或从数据库(视情况而定)加载数据并存储在缓存内。

当这个过程首次发生时,数据将正常地从数据库或其他数据源加载,然后再存储到 memcached 内。当下一次访问此信息时,它就会从 memcached 拉出,而不是从数据库加载,节省了时间和 CPU 循环。

问题的另一个方面是要确保如果更改了要存储在 memcached 内的信息,在更新后端信息的同时还要更新 memcached 的版本。这会让图 4 内所示的这个典型顺序发生稍许变化,如 图 5 所示。


图 4. 在一个典型的应用程序内更新或存储数据
此图显示了从更新数据到处理/格式化数据再到发送更新了的数据至客户机的流程

图 5 显示了使用 memcached 后发生了变化的流程。


图 5. 在使用 memcached 时更新或存储数据
此图显示了拓展了的流程:从更新数据到处理/格式化数据,再到将数据存储在 memcached 内,最后到发送更新了的数据至客户机

比如,仍以博客站点为例,在博客系统更新数据库内的类别列表时,更新应该遵循如下顺序:

  1. 更新数据库内的类别列表
  2. 格式化信息
  3. 将信息存储到 memcached 内
  4. 将信息返回至客户机

memcached 内的存储操作是原子的,所以信息的更新不会让客户机只获得部分数据;它们获得的或者是老版本,或者是新版本。

对于大多数应用程序,这两个操作是您惟一需要注意的。在访问他人使用的数据时,它会自动被添加到这个缓存内,而且如果对该数据进行了更改,此缓存内也会自动进行更新。


键、名称空间和值

memcached 另一个需要重点考虑的因素是如何组织和命名存储在缓存内的这些数据。从之前博客站点的例子中,不难看出需要使用一种一致的命名结构以便您能加载博客类别、历史和其他信息,然后再在加载信息(并更新缓存)时或者在更新数据(同样也要更新缓存)时使用。

使用的何种具体的命名系统特定于应用程序,但通常可以使用一种与现有应用程序类似的结构,并且这种结构很可能基于某种惟一识别符。当从数据库拉出信息或在整理信息集时,就会发生这种情况。

以 blog post 为例,可以在一个具有键 category-list 的项中存储类别列表。与此 post ID 对应的单个 post,比如 blogpost-29 相关的值都可以使用,而该项的注释则可以存储在 blogcomments-29 内,其中 29 就是这个 blog post 的 ID。这样一来, 您就可以将各种各样的信息存储在缓存内,使用不同的前缀来标识这些信息。

memcached 键/值存储的简便性(以及安全性的缺乏)意味着如果您想要在使用同一个 memcached 服务器的同时支持多个应用程序,那么就可以考虑使用其他格式的量词来标识数据属于某种特定的应用程序。比如,可以添加像 blogapp:blogpost-29 这样的应用程序前缀。这些键是没有格式的,所以可以使用任何字符串作为键的名称。

在存储值的方面,应该确保存储在缓存内的信息适合于您的应用程序。比如,对于这个博客系统,您可能想要存储被博客应用程序使用的对象以便格式化博客信息,而不是原始的 HTML。如果同一个基础结构用在应用程序内的多个地方,这一点更具实用性。

大多数语言的接口,包括 Java™、Perl、PHP 等,都能串行化语言对象以便存储在 memcached 内。这就让您可以存储并随后从内存存储恢复全部对象,而不是在您的应用程序内手动重构它们。 很多对象,或它们使用的结构,都基于某种散列或数组结构。对于跨语言的环境,比如在 JSP 环境和 JavaScript 环境间共享相同信息,可以使用一种架构中立的格式,比如 JavaScript Object Notation (JSON) 甚或 XML。


填充并使用 memcached

作为一种开源产品以及一种最初开发用来工作于现有开源环境内的产品,memcached 受大量环境和平台支持。与 memcached 服务器通信的接口有很多,并常常具有针对所有语言的多个实现。参见 参考资料 以获得常用的库和工具箱。

要列出所有受支持的接口和环境不太可能,但它们均支持 memcached 协议提供的基础 API。这些描述已经被简化并应用在不同语言的上下文内,在这些语言中,使用不同的值可指示错误。主要的函数有:

  • get(key) — 从存储了特定键的 memcached 获得信息。 如果键不存在,就返回错误。
  • set(key, value [, expiry]) — 使用缓存内的标识符键存储这个特定的值。如果键已经存在,那么它就会被更新。期满时间的单位为秒,并且如果值小于 30 天 (30*24*60*60),那么就用作相对时间,如果值大于 30 天,那么就用作绝对时间 (epoch)。
  • add(key, value [, expiry]) — 如果键不存在就将这个键添加到缓存内,如果键已经存在就返回错误。如果您想要显式地添加一个新键而又不会因它已经存在而更新它,那么这个函数将十分有用。
  • replace(key, value [, expiry]) — 更新此特定键的值,如果键不存在就返回一个错误。
  • delete(key [, time]) — 从缓存中删除此键/值对。如果您提供一个时间,那么添加具有此键的一个新值就会被阻塞这个特定的时期。超时让您可以确保此值总是可以重新读取自您的数据中心。
  • incr(key [, value]) — 为特定的键增 1 或特定的值。只适用于数值。
  • decr(key [, value]) — 为特定的键减 1 或特定的值,只适用于数值。
  • flush_all — 让缓存内的所有当前条目无效(或到期失效)。

比如,在 Perl 内,基本 set 操作可以如清单 1 所示的那样处理。


清单 1. Perl 内的基本 set 操作

				
use Cache::Memcached;

my $cache = new Cache::Memcached {
'servers' => [
'localhost:11211',
],
};

$cache->set('mykey', 'myvalue');

 

Ruby 内的相同的基本操作如清单 2 所示。


清单 2. Ruby 内的基本 set 操作

				
require 'memcache'
memc = MemCache::new '192.168.0.100:11211'

memc["mykey"] = "myvalue"

 

在两个例子中可以看到相同的基本结构:设置 memcached 服务器,然后分配或设置值。其他的接口也可用,包括适合于 Java 技术的那些接口,让您可以在 WebSphere 应用程序内使用 memcached。memcached 接口类允许将 Java 对象直接序列化到 memcached 以便于存储和加载复杂的结构。当在像 WebSphere 这样的环境内进行部署时,有两个事情非常重要:服务的弹性(在 memcached 不可用时如何做)以及如何提高缓存存储量来改进在使用多个应用程序服务器或在使用像 WebSphere eXtreme Scale 这样的环境时的性能。我们接下来就来看看这两个问题。


弹性和可用性

有关 memcached 最常见的一个问题是:“若缓存不可用了,会发生什么情况呢?”正如之前章节中明示的,缓存内的信息不应该成为信息的的惟一资源。必须要能够从其他位置加载存储在缓存内的数据。

虽然,无法从缓存访问信息将会减缓应用程序的性能,但它不应该阻止应用程序的运转。可能会发生这样几个场景:

  1. 如果 memcached 服务宕掉,应用程序应该回退到从原始数据源加载信息并对信息进行显示所需的格式化。此应用程序还应继续尝试在 memcached 内加载和存储信息。
  2. 一旦 memcached 服务器恢复可用,应用程序就应该自动尝试存储数据。没有必要强制重载已缓存了的数据,可以使用标准的访问来用信息加载和填充缓存。最终,缓存将会被最常用的数据重新填充。

再次重申,memcached 是信息的缓存但并非惟一的数据源。memcached 服务器不可用不应该是应用程序的终结,虽然这意味着在 memcached 服务器恢复正常之前性能会有所降低。实际上,memcached 服务器相对简单,并且虽然不是绝对无故障的,但它的简单性的结果就是它很少会出错。


分配缓存

memcached 服务器只是网络上针对一些键存储值的一个缓存。如果有多台机器,那么很自然地会想要在所有多余机器上设置一个 memcached 的实例来提供一个超大的联网 RAM 缓存存储。

有了这个想法后,还有一种想当然是需要使用某种分配或复制机制来在机器之间复制键/值对。这种方式的问题是如果这么做反而会减少可用的 RAM 缓存,而不是增加。如图 6 所示,可以看出这里有三个应用程序服务器,每个服务器都可以访问一个 memcached 实例。


图 6. 多重 memcached 实例的不正确使用
此图显示了 memcached 的三个独立的 1-GB 实例,支持三个应用程序服务器,各产出 1 GB 的缓存空间

尽管每个 memcached 实例都是 1 GB 的大小(产生 3 GB 的 RAM 缓存),但如果每个应用程序服务器只有其自己的缓存(或者在 memcached 之间存在着数据的复制),那么整个安装也仍只能有 1 GB 的缓存在每个实例间复制。

由于 memcached 通过一个网络接口提供信息,因此单个的客户机可以从它所能访问的任何一个 memcached 实例访问数据。如果数据没有跨每个实例被复制,那么最终在每个应用程序服务器上,就可以有 3 GB 的 RAM 缓存可用,如图 7 所示。


图 7. 多重 memcached 实例的正确使用
此图显示了三个交互的 1-GB memcached 实例,支持三个应用程序服务器,导致总体 3 GB 的共享缓存空间

这个方法的问题是选择哪个服务器来储存键/值对,以及当想要重新获得一个值时,如何决定要与哪个 memcached 服务器对话。问题的解决方案就是忽略复杂的东西,比如查找表,或是寄望 memcached 服务器来为您处理这个过程。而 memcached 客户机则必须要力求简单。

memcached 客户机不必决定此信息,它只需对在存储信息时指定的键使用一个简单的散列算法。当想要从一列 memcached 服务器存储或获取信息时,memcached 客户机就会用一个一致的散列算法从这个键获取一个数值。举个例子,键 mykey 被转换成数值 23875 。是保存还是获取信息无关紧要,这个键将总是被用作惟一标识符来从 memcached 服务器加载,因此在本例中,“mykey” 散列转化后对应的值总是 23875

如果有两个服务器,那么 memcached 客户机将对这个数值进行一个简单的运算(例如,系数)来决定它应将此值存储在第一个还是第二个配置了的 memcached 实例上。

当存储一个值时,客户机会从这个键确定出散列值以及它原来存储在哪个服务器上。当获取一个值时,客户机会从这个键确定出相同的散列值并会选择相同的服务器来获取信息。

如果在每个应用程序服务器上使用的是相同的服务器列表(并且顺序相同),那么当需要保存或检索同一个键时,每个应用程序服务器都将选择同一个 服务器。现在,在这个例子中,有 3GB 的 memcached 空间可以共享,而不是同一个 1 GB 的空间的复制,这就带来了更多的可用缓存,并很有可能会提高有多个用户情况下的应用程序的性能。

这个过程也有其复杂性(比如当一个服务器不可用时会怎样),更多信息,请参见相关文档(参见 参考资料)。


如何能不使用 memcached

尽管 memcached 很简单,但 memcached 实例有时候还是会被不正确地使用。

memcached 不是一个数据库

最常见的 memcached 误用就是把它用作一个数据存储,而不是一个缓存。memcached 的首要目的就是加快数据的响应时间,否则数据从其他数据源构建或恢复需要很长时间。一个典型的例子就是从一个数据库中恢复信息,特别是在信息显示给用户前 需要对信息进行格式化或处理的时候。Memcached 被设计用来将信息存储在内存中以避免每次在数据需要恢复时重复执行相同的任务。

切不可将 memcached 用作运行应用程序所需信息的惟一信息源;数据应总是可以从其他信息源获取。此外,要记住 memcached 只是一个键/值的存储。不能在数据上执行查询,或者对内容进行迭代来提取信息。应该使用它来存储数据块或对象以备批量使用。

不要缓存数据库行或文件

虽然可以使用 memcached 存储加载自数据库的数据行,但这实际上是查询缓存,并且大多数数据库都提供各自的查询缓存的机制。其他的对象,比如文件系统的图像或文件的情况与此相同。很多应用程序和 web 服务器针对此类工作已经有了一些很好的解决方案。

如果在加载和格式化后,使用它来存储全部信息块,就可以从 memcached 获得更多的实用工具和性能上的改善。仍以我们的博客站点为例,存储信息的最佳点是在将博客类别格式化为对象,甚至是在格式化成 HTML 后。博客页面的构造可通过从 memcached 加载各个组件(比如 blog post、category list、post history 等)并将完成的 HTML 写回至客户机实现。

memcached 并不安全

为了确保最佳性能,memcached 并未提供任何形式的安全性,没有身份验证,也没有加密。这意味着对 memcached 服务器的访问应该这么处理:一是通过将它们放到应用程序部署环境相同的私有侧,二是如果安全性是必须的,那么就使用 UNIX® socket 并只允许当前主机上的应用程序访问此 memcached 服务器。

这多少牺牲了一些灵活性和弹性,以及跨网络上的多台机器共享 RAM 缓存的能力,但这是在目前的情况下确保 memcached 数据安全性的惟一一种解决方案。


不要限制自己

除了不应该使用 memcached 实例的情况外,memcached 的灵活性不应忽视。由于 memcached 与应用程序处于相同的架构水平,所以很容易集成并连接到它。并且更改应用程序以便利用 memcached 也并不复杂。此外,由于 memcached 只是一个缓存,所以在出现问题时它不会停止应用程序的执行。如果使用正确的话,它所做的是减轻其余服务器基础设施的负载(减少对数据库和数据源的读操 作),这意味着无需更多的硬件就可以支持更多的客户机。

但请记住,它仅仅是个缓存!


结束语

在本文中,我们了解了 memcached 以及如何最佳地使用它。我们看到了信息如何存储、如何选择合理的键以及如何选择要存储的信息。我们还讨论了所有 memcached 用户都要遇到的一些关键的部署问题,包括多服务器的使用、当 memcached 实例消亡时该怎么做,以及(也许最为重要的)在哪些情况下不能使用 memcached。

作为一种开源的应用程序并且是目的简单而直白的应用程序,memcached 的功能和实用性均来自于这种简单性。通过为信息提供巨大的 RAM 存储空间、让它在网络上可用,然后再让它可通过各种不同的接口和语言访问到,memcached 可被集成到多种多样的安装和环境中。

 

参考资料

学习

获得产品和技术

讨论

关于作者

Martin Brown 成为专业作家已有七年多的时间了。他是题材广泛的众多书籍和文章的作者。他的专业技术涉及各种开发语言和平台 —— Perl、Python、Java™、JavaScript、Basic、Pascal、Modula-2、C、C++、Rebol、Gawk、 Shellscript、Windows、Solaris、Linux®、BeOS、Mac OS/X 等等,还涉及 Web 编程、系统管理和集成。Martin 是 Microsoft® 的主题专家(SME),并且是 ServerWatch.com、LinuxToday.com 和 IBM developerWorks 的定期投稿人,他还是 Computerworld、The Apple Blog 和其他站点的正式博客。您可以通过他的 Web 站点 : http://www.mcslp.com 与他联系。

转自:http://www.ibm.com/developerworks/cn/opensource/os-memcached



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/21/1292901251292.html
posted @ 2010-12-21 11:14 88250 阅读(463) | 评论 (0)编辑 收藏

“比心情更好的是你的选择!”这条挂在“天骄北麓”售楼部房顶上的广告词极其充满诱惑,与之形成鲜明反差的是上百准业主半月来的维权,比其心情更糟的是“天骄北麓”背后“那点房事”。12月18日,位于红云路上的“天骄北麓”在准业主们的不满和遭遇鸡粪洒门中迎来了开盘。

这 场被媒体和市民高度关注的房事,其实是一场赤裸裸的利益纷争,以及一个企业在市场经济下,面对市场风险如何做到诚实守信?对于准业主们来说,需要思考的是 在市场经济下,如何用法律来保障自己的权益。市场经济就是法治经济,道德、诚信这些没有落在纸上具有法律约束力的字眼,在利益面前显得苍白无力。

为防不测,防暴警察也来到现场

昨天上午,“天骄北麓”迎来开盘。由于上百准业主的不满和抗议,让这次开盘显得格外谨慎和受到外界广泛关注。数十警察赶到现场维持秩序,为了防止不测,防暴警察也来到现场。

中 午12点39分左右,准房主们把早已准备好的两箱鸡粪洒在了售楼部的门口。顿时,现场出现了一点骚乱,在旁边维持秩序的警察开始前去阻拦。就在这时,一矿 泉水瓶砸向售楼部大门,站在门口的一名保安拿着警棍朝着准业主们指了指,几个情绪激动的准业主向保安冲去,被维持秩序的警察拦下,在其他保安的劝说下,该 名保安走进了售楼部。

56岁的代阿姨,是这次“天骄北麓”团购房的一名准业主,交了20万元。维权15天以来,代阿姨有着不少的委屈和不满。为了换一套大一点的房子,代阿姨把原来的房子卖了,手里攥着60多万元,本想把这60多万投向“天骄北麓”,买大一点的房子,等待她的却是一场纷争。

“比心情更坏的是花言巧言设下的陷阱,一个没有出口、巷道林立的购房迷宫。”代阿姨说。

说起购买“天骄北麓”的房子,患有高血压的代阿姨苦不堪言,当她7月初从中介公司获知4800元一平方米就可以购买天骄北麓的房子时,义无反顾地交了1.7万元的转让金,并与这家中介公司签下合约。7月10日选房时,她交了20万元。

本以为可以圆一个住房梦的她,每天都在盼着房子开盘,日子就这么一天天过去,代阿姨也没感到有什么烦恼。

当12月1日获知她交了20万元参与团购的“天骄北麓”价格比当初和中介公司签下合约的房价高出一倍时,代阿姨蒙了。自12月4日起,代阿姨和上百团购者开始了维权。由于身体不好,上了年纪,每天的维权之路,代阿姨还是吃不消。

和代阿姨一样的购房者还有来自四川的周女士。周女士交了6万元的购房意向金,结果也陷入了这场纷争。欲哭无泪的周女士昨天上午后悔不已,当初不该草率地卖了房子来购买“天骄北麓”。在这起购房中,还有她的10多个老乡。

“开发商的一小步,维权者的一大步”

在这些准业主提供的协议中,记者没有看到一份真正的购房合同,听到和看到的只是团购、意向金,这些不明不白的词语,让人眼花缭乱。

在“天骄北麓”售楼部,一张由云南伦华房地产有限公司贴出的通告里称,对未选中房子的购房客户,公司愿意现金一次性补偿,以中国人民银行公布的现行两年定期存款率3.25%为计算标准。

对于此,准业主霍先生把其称为“开发商的一小步,维权者的一大步”。霍先生说,在各方压力和他们准业主的努力下,开发商愿意为返还意向金支付利息,来之不易。

代阿姨说,她交了20万元的意向金,可以得到6500多元的利息,对于她来说,这点利息已经对其没有多少用处,因为这几个月来,看着往上涨的房子,她付出去的更多,已经耽误了她买房。

中午12点51分,准业主们开始从售楼部撤离,环卫工人开始打扫门口的鸡粪。下午1点10分左右,“天骄北麓”恢复了暂时的安宁。挂在售楼部西边“所有关于生活的梦想从这一刻开启”的广告词,是否会因为一些准业主们的离开而开启更多准业主们生活的梦想呢?

背景

“天骄北麓”团购风波

2009年11月,由云南伦华房地产有限公司开发的“天骄北麓”项目开始认购,打出的广告上称项目房源最低售价3660元/平米,均价4300元/平米,并承诺如正式开盘时提价,团购房源价格不变,上万的团购者缴纳了2至30万元不等的意向金预订房源。

2010年12月1日,“天骄北麓”项目公布了每套房源价格,均价上调。开发商称所有房源按照公布价格出售,不想买房的,无息返还意向金。

当 准业主们获知这个消息后,犹如五雷轰顶,当初不是说好了3660元到4300元吗?怎么会有这么大的差距呢?一种不满的情绪开始在准业主中蔓延。12月1 日,因开盘价格远远高于已经交了认购金的购房者的心理底线,这些准业主们一气之下砸了售楼部的沙盘模型。12月4日、5日,准业主们聚集售楼部,用番茄鸡 蛋来招呼开发商,表达对开发商行为的不满。

记者秦聪俊(都市时报)

 

转自:http://news.qq.com/a/20101219/001080.htm?qq=0&ADUIN=84588990&ADSESSION=1292750641&ADTAG=CLIENT.QQ.3073_.0

 



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/19/1292773828916.html
posted @ 2010-12-19 23:50 88250 阅读(175) | 评论 (0)编辑 收藏

腾讯微博开放平台API开放啦,使用腾讯微博开放平台提供的API创建自己的应用,需要首先填写个人资料,通过联系邮箱验证,获取开发者资格,就能 创建自己的应用。腾讯微博开放平台,是基于腾讯微博系统,为广大开发者和用户提供的开放数据分享与传播平台。广大开发者和用户登录平台后,就可以使用平台 提供的开放API接口,创建应用从微博系统获取信息,或将新的信息传播到整个微博系统中,丰富多样的API接口和应用,加上你的智慧,将创造出无穷的应用和乐趣。

平台使用说明:

腾讯微博开放平台,是基于腾讯微博系统,为广大开发者和用户提供的开放数据分享与传播平台。广大开发者和用户登录平台后,就可以使用平台提供的开放 API接口,创建应用从微博系统获取信息,或将新的信息传播到整个微博系统中,丰富多样的API接口和应用,加上你的智慧,将创造出无穷的应用和乐趣!

平台介绍 — 在微博开放平台能获取到的资源及优势

应用开发说明 — 说明如何成为一个开发者并创建应用

应用审核流程 — 审核应用的来源字段能获得的好处,以及如何审核

开发者协议 — 在此查看腾讯微博开放平台开发者服务协议

如何开发微博应用?(马上成为开发者)

你只需要按照如下步骤操作:

第一步:填写你的开发者信息;

第二步:联系邮箱通过验证;(电子邮箱将作为我们联系你的重要方式,请提供常用邮箱地址)

第三步:填写要创建的应用信息。

就能马上获取到微博App Key和App Secret,调用微博API,进行应用开发。 查看详细说明

----

代表着中国最先进的互联网技术的腾讯终于走出了开放的第一步 :-)

转自:http://www.oschina.net/news/13863/tencent-open-micro-blogging-api



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/tencent-open-micro-blogging-api.html
posted @ 2010-12-17 09:08 88250 阅读(199) | 评论 (0)编辑 收藏

好久没贴过代码了,心血来潮。

/*
 * Copyright (c) 2009, 2010, B3log Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.b3log.latke.servlet.filter;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 * Abstract HTTP response GZIP filter.
 *
 * @author Liang Ding
 * @version 1.0.0.1, Dec 16, 2010
 */
public abstract class AbstractGZIPFilter implements Filter {

    /**
     * Logger.
     */
    private static final Logger LOGGER =
            Logger.getLogger(AbstractGZIPFilter.class.getName());

    @Override
    public void init(final FilterConfig cfg) throws ServletException {
    }

    /**
     * Wraps the http servlet response with GZIP if could.
     *
     * @param request the specified request
     * @param response the specified response
     * @param chain filter chain
     * @throws IOException io exception
     * @throws ServletException servlet exception
     */
    @Override
    public void doFilter(final ServletRequest request,
                         final ServletResponse response,
                         final FilterChain chain) throws IOException,
                                                         ServletException {
        final HttpServletRequest httpServletRequest =
                (HttpServletRequest) request;
        final String requestURI = httpServletRequest.getRequestURI();
        if (shouldSkip(requestURI)) {
            LOGGER.log(Level.FINEST, "Skip GZIP filter request[URI={0}]",
                       requestURI);
            chain.doFilter(request, response);

            return;
        }

        final String acceptEncoding =
                httpServletRequest.getHeader("Accept-Encoding");
        boolean supportGZIP = false;
        if (null != acceptEncoding
            && 0 <= acceptEncoding.indexOf("gzip")) {
            supportGZIP = true;
        }

        if (!supportGZIP) {
            LOGGER.info("Gzip NOT be supported");
            chain.doFilter(request, response);

            return;
        }

        final HttpServletResponse httpServletResponse =
                (HttpServletResponse) response;
        httpServletResponse.addHeader("Content-Encoding", "gzip");
        httpServletResponse.addHeader("Vary", "Accept-Encoding");
        chain.doFilter(request,
                       new GZIPServletResponseWrapper(httpServletResponse));
    }

    /**
     * Determines whether the specified request URI should be skipped filter.
     *
     * 

* Note: This method SHOULD be invoked for all filters with pattern * "/*". *

* * @param requestURI the specified request URI * @return {@code true} if should be skipped, {@code false} otherwise */ public abstract boolean shouldSkip(final String requestURI); @Override public void destroy() { } /** * HTTP response wrapper for GZIP. * * @author Liang Ding * @version 1.0.0.0, Dec 16, 2010 */ private class GZIPServletResponseWrapper extends HttpServletResponseWrapper { /** * GZIP output stream. */ private GZIPOutputStream gzipStream; /** * Servlet output stream. */ private ServletOutputStream servletOutputStream; /** * Print writer. */ private PrintWriter printWriter; /** * Constructs an {@link GZIPServletResponseWrapper} object with the * specified http servlet response. * * @param httpServletResponse the specified http servlet response * @throws IOException io exception */ GZIPServletResponseWrapper(final HttpServletResponse httpServletResponse) throws IOException { super(httpServletResponse); } @Override public ServletOutputStream getOutputStream() throws IOException { if (null == servletOutputStream) { servletOutputStream = createOutputStream(); } return servletOutputStream; } @Override public PrintWriter getWriter() throws IOException { if (null == printWriter) { printWriter = new PrintWriter( new OutputStreamWriter(getOutputStream(), getCharacterEncoding())); } return printWriter; } /** * Creates output stream with GZIP delegation. * * @return servlet output stream * @throws IOException io exception */ private ServletOutputStream createOutputStream() throws IOException { final ServletResponse servletResponse = this.getResponse(); gzipStream = new GZIPOutputStream(servletResponse.getOutputStream()); return new ServletOutputStream() { @Override public void write(final int b) throws IOException { gzipStream.write(b); } @Override public void flush() throws IOException { gzipStream.flush(); } @Override public void close() throws IOException { gzipStream.close(); } /* * These two are not absolutely needed. They are here simply * because they were overriden by GZIPOutputStream. */ @Override public void write(final byte[] b) throws IOException { gzipStream.write(b); } @Override public void write(final byte[] b, final int off, final int len) throws IOException { gzipStream.write(b, off, len); } }; } } }



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/16/1292515963081.html
posted @ 2010-12-17 00:13 88250 阅读(586) | 评论 (0)编辑 收藏



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-129.html
posted @ 2010-12-14 22:59 88250 阅读(193) | 评论 (0)编辑 收藏

 



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-128.html
posted @ 2010-12-11 11:33 88250 阅读(234) | 评论 (0)编辑 收藏

WebSocket 协议是实现了浏览器与服务器全双工通信的 HTML5 新协议之一。传统浏览器只允许通过 HTTP 与网站互动,然而对于富 Web 应用 如聊天和游戏,HTTP 的效率不太高,因此HTML5 提供了socket API,只需一个握手动作就能在浏览器和服务器之间建立快速通道。

然而在 11 月 26 日,安全研究人员发表一篇研究报告(PDF),他们发现 WebSocket 和透明代理存在严重安全问题,他们演示了基于 Upgrade 和 CONNECT 的缓存中毒攻击,研究人员提议修改握手方式。在 Bugzilla 上,Firefox 开发者讨论了该问题,他们最后决定Firefox 4 将默认不启用 WebSockets,从 Firefox 4 beta 8 开始用户将需要修改设置才能启用 WebSockets。未来在解决安全问题后,Firefox 会选择默认启用。

转自:http://www.oschina.net/news/13668/disabling-websockets-for-firefox-4



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/10/1291942973503.html
posted @ 2010-12-10 09:03 88250 阅读(165) | 评论 (0)编辑 收藏

自从发布第一个版本来,大家给了很多建议,谢谢了 :-)

下个版本 0.2.5 将于明年 2 月 14 日发布,其中加入两个大的特性:

  • 多用户
    Solo 不再是单用户博客了。多人可以一起在一个博客里进行文章撰写,非常适合团队博客。另外,如果是情侣博客的话,哼哼....
  • 草稿夹
    想发布再发布吧!当然,发布了也可以再草稿化....

这个版本的改变比较大(数据存储、逻辑控制、视图),除了 Solo 上述两个大特性的加入,还有 Latke 框架上的增强:

  • 存储缓存
    本地测试可以提升单一实体按 Key 访问时速度 400 倍左右。当然,部署到 GAE 后可能没这么好的效果 - -~

(广告:Latke 是 GAE 上的一个应用框架,主要整合了 Guice、FreeMarker、Jabsorb,数据模型从视图到存储都以 JSON 贯穿

下个版本是 B3log Solo 的第一个正式版吧 :-)

P.S. 情侣博客?两个人也是多用户嘛,0.2.5 中将加入一款皮肤,非常适合情侣写作!谢谢 Lamb 这么给力!

 



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/08/1291818048978.html
posted @ 2010-12-08 22:21 88250 阅读(181) | 评论 (0)编辑 收藏

那大爷买西红柿来着的,挑了三个放到秤盘里,摊主秤了下说:“一斤半,三块七。”

大爷说:“我就做个汤,用不着那么多。”说完就去掉了个儿最大的那个西红柿。

摊主迅速又瞧一眼秤子,“一斤二两,三块。”

正当我看不过去想提醒大爷注意摊主的秤子时,大爷从容的掏出了七毛钱,拿起刚刚去掉的那个大的西红柿,扭头就走了……

摊主当场就风中凌乱了,我憋成内伤,把头扭向一边……

 

转自:http://www.douban.com/group/topic/16089209/



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/12/03/1291338840521.html
posted @ 2010-12-03 09:14 88250 阅读(195) | 评论 (0)编辑 收藏

 



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-127.html
posted @ 2010-12-01 21:06 88250 阅读(254) | 评论 (0)编辑 收藏

B3log LogoGAE 博客 —— B3LOG Solo 0.2.1 正式发布了。

该版本除了修复 Bugs,还增加了自定义文章/页面链接,改进了缓存,以及加入了新皮肤 favourite。

在 0.2.1 开发之际,Lamb 童鞋加入了 B3LOG Solo 开发团队(成员列表),并给我们带来了新皮肤 favourite。

新特性

  • 评论表情
  • 自定义文章链接
  • 自定义页面链接
  • 新皮肤——favourite
  • 加入了“初始化”功能(/init.do)

Bug 修复

  • 修复了偏好设定与统计数据丢失
  • 修复了皮肤显示错误
  • 修复了按标签/存档查看文章时排序的错误
  • 修复了站外相关阅读显示站内文章问题

改进

  • 提交评论/回复后只刷新评论列表
  • ”最新评论“/统计信息使用模板生成
  • 编辑器加入了中文配置
  • 调整一些页面链接后缀为 .html
  • 改进了页面缓存

具体改动看这里

升级

如果您是 0.2.0 的用户,那么请在部署完 0.2.1 后登录后台,访问 http://${application-id}.appspot.com/upgrade/v020-v021.do 进行升级。

该升级程序主要是对页面自定义链接特性进行数据一致性升级。

项目

如果在使用、测试中发现任何问题,如果您有任何意见或建议,请告知我们 :-)

作者博客

发布历史

  1. GAE 博客——B3log Solo 0.2.0 发布了!
  2. GAE 博客——B3log Solo 0.1.1 发布了!
  3. B3log Solo 0.1.0 发布了!
  4. B3log Solo 0.1.0-preview2 发布了!
  5. Solo 0.1.0-Preview1 发布了


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/b3log-solo-release-021.html
posted @ 2010-12-01 12:34 88250 阅读(149) | 评论 (0)编辑 收藏

B3log LogoGAE 博客 ——  B3LOG Solo 下周将发布 0.2.1。

该版本除了修复 Bugs,还增加了自定义文章/页面链接,改进了缓存,以及加入了新皮肤 favourite。

在 0.2.1 开发之际,Lamb 童鞋加入了 B3LOG Solo 开发团队(成员列表),并给我们带来了新皮肤 favourite。

0.2.1 具体改动可以看这里,发布日期定为 12 月 1 日。



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/28/1290918173803.html
posted @ 2010-11-28 12:23 88250 阅读(155) | 评论 (0)编辑 收藏

随着 Web2.0 的风靡,JavaScript 已经成为一门被人们重新认识的编程语言,由于大量 JS 开源框架的出现,利用 JavaScript 开发 的项目越来越多,越来越大。同时,也有越来越多JavaScript 开发问题暴露出来,如性能、网页加载速度等,其中,JavaScript 文档维护也成 为了开发者亟待解决的一个难题。

许多现代编程语言都有自己的集成化文档生成工具,像 Java 有 JavaDoc,.NET有 NDoc,PHP有 PHPDoc,这些自动化文档工具可以根据代码中的注释自动生成代码文档。

JsDoc Toolkit 就是这样一个自动化文档工具,它是发布在 Google code 上的一个开源项目,和其他语言的文档工具一样,它可以自动从 JavaScript 代码中提取注释生成格式化文档。 

下载地址

http://code.google.com/p/jsdoc-toolkit/downloads/list

运行环境

JsDoc Toolkit是用Java开发的,运行时需要 Java 1.5+。

用法

在运行之前,你需要把当前的工作目录切换到JsDoc Toolkit目录,并确保将java.exe所在目录添加到环境变量中。

java -jar jsrun.jar app\run.js -a -t=templates\jsdoc mycode.js

mycode.js是需要生成文档的js代码,如果mycode.js和JsDoc不在同一目录,请加上文件的绝对或者相对路径。如果项目中有多个js, 可以使用通配符*来指定多个js文件(*.js)。-e参数指定文档编码,-t参数指定文档模板位置(可以新建或修改模板文件让输出的代码文件更具特 色),生成的文档文件在JsDoc目录下的out目录中。为了使用方便,我写了一个批处理文件,你可以将代码保存为run.bat,放到JsDoc目录 下:

::run.bat
@echo off
::js文件名(换成你的js文件名)
set jsname=jquery.js
::js文件路径(换成你的js文件路径)
set jspath=C:\test\
echo start...
java -jar jsrun.jar app\run.js -a -e=GBK -t=templates\jsdoc "%jspath%%jsname%.js"
::out\%jsname%\index.html
echo finished.
pause

常用关键字

author 标识代码作者
class 标识该函数是一个类的构造函数
constant 声明常量
constructor 同class
default 默认值
deprecated 声明已弃用的对象
description 对象描述
event 事件函数
example 例子代码
fileOverview Javascript文件总体描述
ignore 忽略有这个标记的函数
link 与其他JsDoc对象关联
name 显示声明JsDoc不能自动检测的对象
namespace 声明命名空间
param 参数
private 声明私有对象
property 显式声明一个属性
public 声明公开对象
requires 声明所依赖的对象或文件
returns 返回值
see 声明可参考的其它对象
since 声明对象从指定版本开始生效
static 显式声明一个静态对象
throws 声明函数执行过程中可能抛出的异常
type 声明变量类型或者函数返回值类型
version 版本号

详细语法请参阅:JsDoc Toolkit Wiki

整理自:http://blog.tugai.net/2010/01/08/jsdoc-toolkit-usage/



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/26/jsdoc-toolkit-usage.html
posted @ 2010-11-26 10:47 88250 阅读(411) | 评论 (0)编辑 收藏

作词: 刘卓辉    作曲: 黄家驹

遥远的东方辽阔的边疆

还有远古的破墙

前世的沧桑后世的风光

万里千山牢牢接壤

围着老去的国度

围着事实的真相

围着浩瀚的岁月

围着欲望与理想

神秘的村庄神秘的中央

还有昨天的战场

皇帝的新衣热血的缨枪

谁却甘心流连塞上

围着欲望与理想叫嚷

蒙着耳朵

那里那天不再听到在呼号的人

woo~

蒙着眼睛

再见往昔景仰的那样一道疤痕

woo~

留在地壳头上

hmm……yeah~

woo~

无冕的身躯忘我的思想

还有显赫的破墙

谁也冲不开谁也抛不低

谁要一生流离浪荡

----

和谐。



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/25/1290648024319.html
posted @ 2010-11-25 09:20 88250 阅读(131) | 评论 (0)编辑 收藏

项目新闻

NetBeans 7.0 Beta版可以下载了!

image NetBeans开发团队宣布支持JDK 7并整合了Oracle WebLogic服务器、Oracle DB和GlassFish 3.1的NetBeans 7.0 Beta版可以下载了。 此外,新版本还包括支持对Maven 3和HTML 5的编辑,一个可以增强Swing GUI开发的GridBagLayout设计器、更好的Java编辑器等等。浏览NetBeans 7.0 Beta新特性页面,阅读新的教程和视频来了解详细内容。


NetBeans 7.0中对Maven 3的支持

在NetBeans 7.0 Beta版中提供了对Maven 3的支持。在本采访中,NetBeans工程师Jesse Glick介绍了Maven用户需要了解的知识。

插件:toString生成器

Simon Martinelli的插件向你提供了一个生成String,StringBuilder或者StringBuffer的工具。

文章

重新加载基于NetBeans模块的Maven程序

Allan Gregersen在文章中描述了他用于重新加载Maven应用并保持已部署对象状态的类似JRebel的解决方法。

如何创建实时图表

Java桌面应用中需要鲜活的图表吗?JFreeChart很难帮上什么忙,但VisualVM charts可以。阅读本页面来了解如何复用这些图表。

博客

Mac,Growl和NetBeans

关于NetBeans中新集成的Growl for Mac的相关信息。

小技巧:NetBeans和Ubuntu中的java.io.IOException

Emilian通过刷新NetBeans用户目录来解决这一问题。

练习

视频:NetBeans 7.0 for PHP中的重命名重构等对编辑器的改进

本视频展示了NetBeans 7.0中PHP编辑器的新特性,如重命名重构,类型层次视图,换行和显示不可打印字符。

在Oracle WebLogic服务器上运行JSF 2.0 web应用

学习使用NetBeans来创建一个JSF web应用并将其部署到Oracle WebLogic服务器上。在练习中你将学习到如何将WebLogic服务器注册到NetBeans IDE中,并配置域来使得JSF作为视图框架。

使用GridBag设计一个基本的Java表单

本练习介绍了NetBeans 7.0 Beta版中新加入的GridBag的基本特性,并使用它来管理应用程序的表单布局。

发布本期时事通讯的是: D. L. 88250

本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-chinese-newsletter-126.html
posted @ 2010-11-24 19:22 88250 阅读(240) | 评论 (0)编辑 收藏

这是一个经常被问到的问题,问的理所当然。作为一个程序员,为什么我就非要被认为知道如何开发Web应用程序呢?这个问题没有一个简单的答案,甚至那些教育机构都未必能清楚的知道;我上的那个大学并没有提供任何关于这个主题的课程。所以,像大多数在这个领域里的web开发人员一样,我只是通过去做, 去实验才学会了这些。没有人告诉我如何去做,我从给自己做点什么东西开始,学会如何开发web应用程序是在这个过程中的一个副产品。这是学习任何语言的一个非常有效的方法。

你很幸运,我在这里将会把如何开发一个web应用程序的主要过程都讲一下。希望能帮助你入门。

 

Web应用程序与网站之间的区别

首先,我要说明,开发一个web应用程序跟开发一个网站是不一样的。虽然在总体上有很大相似之处,但开发它们所需要的时间有巨大的差别。那究竟web应用程序和网站有什么不同呢?通常,维基百科能帮助我们解释这个问题,让我们来看看维基百科是如何定义 应用软件的:

应用软件,通常也被称作应用,指的是专门为帮助用户去执行一个或多个相关特定任务而设计的计算机软件。企业软件,会计软件,办公套件,绘图软件,媒体播放器等都属于这种软件。

跟应用软件相对照的是系统软件和中间件,它们管理计算机效能,管理如何跟计算机集成,但通常这些工作并不会直接反映到使用户受益的任务执行上。举个 例子,一个不是很恰当的实体类比,应用软件跟系统软件之间的关系就好比一个电灯泡和一个发电厂之间的关系,发电厂(系统软件)只是产生电能,它自己没有任 何真正的用途,除非利用一个电灯泡这样的应用工具才能为用户提供服务。

从里面,我总结出来自己对web应用程序的定义:

一个web应用程序是一个能够让用户完成某些特定任务的网站。而一个普通的网站的主要目标是给用户提供信息(博客,新闻,指导,等)。

Web应用程序的开发过程

现在特征已经弄清楚了,我们就可以开始定义开发一个web应用程序的整个过程了。当然,这依赖于工程的大小,过程中的某些步骤可能很小,在你的脑海 里就能完成这种工作,但把事情整个的了解一下总是有好处的。同时还有一点很重要的你要明白,这篇文章并不会对每个步骤进行深层次的描述。

步骤一:分析

开发一个web应用的第一步是分析你的需求。你此时应该定义出一个尽量周全的你的应用应该提供的功能清单。如果是你为一个客户做这些工作,你需要明白他们想要什么(要确保你们对方都知道对方在说些什么)。从你们的讨论中,你能总结出需求和软件规格。你即使是为自己开发,我也建议你把希望这个web应用能够做的功能写下来。

步骤二:设计

一旦你弄清楚了这个web应用需要做哪些事情,你就可以开始设计了。这个步骤通常会反反复复进行很多次,每一次都把设计细化一些。你第一要做的是画出页面流程图(画在纸上,或使用软件工具,凭各自所好吧。我喜欢用纸,这样我可以做更快速的改变)。页面流程图通常是很抽象的黑白绘画,画出你将要实现的web应用的样子(你可以加一些色彩,但尽量保持简单)。

Wireframe created using Draft for the iPad

Wireframe created using Draft for the iPad


这个步骤能够让你知道你的应用最终会是个什么样子。跟37signals倡导的相反,我建议使用一些词语描述,适度细化。当我想到一个很好的想法时,或想 到事情该如何做时,我会把它标注到纸上(例如,当点击这个按钮时应该使另外一个元素改变或隐藏,我会把这写在流程图上)。

当你对做出的草图满意后,你可以开始制作实体模型了。
实体模型仍然是些图案,但有色彩和细节。最终的实体模型看起来应该像你将要实现的web应用的一个截屏图。如果你为一个客户开发,他会看看这些东西,并给你他的认可。然而,很多人都喜欢跳过这一步(大多数都是非设计人员),他们喜欢直接奔向网页原型

原型是用HTML开发出来,使用CSS渲染(有时也是有Javascript)。页面布局要做出来,链接能够点,颜色,字体,字体大小要设定好(如 果你做了实体模型,这个会很容易)。这一步非常的重要,因为这里所有的东西都能用于你最终的应用中。如果允许的话,在你的原型上做一些可用性测试,从长期的效果来看,这能使你避免大量的失误。

在这个步骤的最后,你基本上就知道了你的web应用是如何组织到一起的了。登录页面有些什么,用户如何从主页转向到各个页面。

我建议你去听一下Ryan Singer在“Web应用的未来”研讨会上做的他是如何设计37signals的演讲

步骤三:实现

选择一个框架

现在我们已经知道了要去开发什么东西,那就要把它做出来。这一部分的工作很多,你大部分的时间都要花在这个上面。你第一个要做的决定是如何着手,采用什么样的技术,什么框架。你有很多选择的余地,你需要选出一个适合你的。下面是一个最常用的框架的列表:

没有一个明确的标准说哪个框架最好。它们都各有不同,每个都有自己的长处。最重要的是你要知道它们任何一个都能让你开发出好用的web应用。

开发

一旦你知道了如何去开发,那就要甩开臂膀开干了。这个开发工作可以看作有很多块,但说到底,这都是标准的编程活动了。在后台,你要创建类,对象,服 务,过程,以及持久层来把这些对象保存到数据库中。后台是整个应用的核心,对任何应用来说,它跟普通的编程没有什么区别。接着是前台的开发,你现在编写的 代码才是真正给用户使用的操作界面。你把后台的程序和原型界面集成到一起,把系统各部分集成到一起。你还可以把你在开发过程中想到的一些很炫的小功能用 JavaScript实现。

再说一次,有很多种途径可以实现后台程序。建议你去读一读跟你选择的框架相关的资料,弄清楚如何实现这一部分的工作。通常,这些知识会跟面向对象编程有关,但有些框架正在慢慢的向领域驱动设计发展。

步骤四:打磨抛光

现在应用程序已经开发出来,各个独立的模块也集成到了一起。你需要通过测试来确保你在步骤一中定义的需求和软件规格是否被实现(这个问题在你开发的整个过程中都要记在脑中)。你要确保那些愚蠢的用户不能通过试图做一些你还没有实现的操作而把你的应用弄坏(参考 白盒黑盒测试)。你同时还要确保你的程序能够在各种浏览器里(希望不是IE6)都能正确的运行

现在也是你做一些小的调整,改进你的应用程序给人的感觉的时候,让它趋于完美。

步骤五:发布和后续工作

这最后一步(但不是就此完结)是发布你的应用,让用户能够真正使用它(如果这个应用是个公众开发的应用,别忘了做新闻宣传)。如果你愿意,先发布一 个Beta版,这样只有一小部分用户能够发现你的应用里的大问题(因为你的程序里肯定会有bug),他们会帮助你改进程序的质量。不要忙着增加功能,要专注于把你目前的程序变的稳固。

当经过了beta阶段,你的程序已经变得十分的稳固,听取用户反馈的意见,自己试用一下自己的应用,你可以开始思考如何使应用变的更好。找出不和谐的地方,消除掉。以后每次的迭代都要经过上面所说的五个步骤,但就像我最初说的,你现在已经有了一个可以运行的应用程序,你很容易直接在心里完成这些步骤,直接奔向在代码里测试你的功能。

恭喜,你已经自豪的成为一个web应用程序的作者了。

[英文出处]:How to develop web applications

[译文来源]:外刊IT评论


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/how-to-develop-web-applications.html
posted @ 2010-11-23 13:03 88250 阅读(184) | 评论 (0)编辑 收藏

Attachmate 集团宣布以22 亿美元收购 Novell ,同时 Novell 宣布将部分知识产权以 4 亿 5 千万美元出售给 M$ 组建的 CPTN Holdings 有限责任公司。

Attachmate 集团决定将 Novell 和 SuSe 分别合并至 Attachmate 和 NetIQ 部门运作。

而目前 M$ 方面尚未对从 Novell 手中获得的知识产权做出任何评价,其中牵扯的 WordPrefect 及 Linux 专利池问题依旧不明朗。同时也未透露 CPTN Holdings 公司中其他投资人的身份。

消息来源:ZDNet


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/23/1290473527327.html
posted @ 2010-11-23 08:52 88250 阅读(176) | 评论 (0)编辑 收藏

NetBeans LogoNetBeans 团队宣布 NetBeans IDE 7.0 Beta 可用!

NetBeans IDE 7.0 Beta 引入了对 JDK 7 的支持。本次发布也包含了对 Oracle WebLogic 服务器、Oracle 数据库以及 GlassFish 3.1 支持的增强。

另外,本次发布还加入了 Maven 3、HTML5 编辑支持;一个新的 GridBagLayout 以改进 Swing GUI 开发;改进了对 Java EE 应用运行及调试的支持;改进了 Java 编辑器。

        下载 NetBeans IDE 7.0 Beta
        查看 NetBeans 教程与视频

较大改变:
JDK 7

  • 项目 Coin 支持
  • 编辑器改进:代码自动完成及提示


WebLogic 服务器

  • 流畅的部署应用到 WebLogic
  • 新的服务器运行状态查看
  • JSF 库整合


Oracle 数据库atabase

  • 简洁的链接向导
  • JDBC 驱动安装向导
  • 编辑与部署存储过程


GlassFish

  • 支持 GlassFish 3.1
  • 远程域重启及日志查看
  • 启用/禁用部署了的应用


Java

  • 支持 Maven 3
  • JUnit 4.8.2 整合及一些 JUnit 支持增强
  • Javadoc 远程 HTTP URLs 支持
  • GridBagLayout 可视化设计


Java EE

  • 增强了对 CDI,REST 服务以及 Java Persistence 的支持
  • 支持 Bean Validation
  • 支持 JSF 组件库,捆绑了 PrimeFaces 库
  • 改进了 JSF 表达式语言支持,包括代码自动完成、重构及提示


Web Languages

  • HTML5 编辑支持
  • JSON 格式化器


PHP

  • 生成 PhpDoc
  • 重命名、安全删除重构
  • PHP 5.3 - 支持别名


C/C++

  • 简化了引入已存在二进制数据
  • 新的远程项目类型


NetBeans Platform

  • 加入了在层内生成 Action 的标注
  • 性能改进及调优器整合改进
  • 其他 NetBeans API 修改

本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/netbeans-7-0-beta-release.html
posted @ 2010-11-19 09:21 88250 阅读(346) | 评论 (0)编辑 收藏

刚才按照 Go 官方网站安装文档安好了 Go。顺带写了个 "Hello World" 。

刚才看了 “Go 三天教程”的第一篇,非常有意思的语言,目前对这门语言的语感可以用“简约、洒脱”来形容。

顺便浏览了一下 Go 的官方包(库),发现其中包含了 htmlhttptemplaterpcjsonwebsocketcrypto、等等 Web 相关包,做 Web 应用绝对给力,而且很前沿啊(支持 HTML5)。

明天正式开始学习这门新语言 :-)

 


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/18/1290099452140.html
posted @ 2010-11-19 00:58 88250 阅读(142) | 评论 (0)编辑 收藏

Quartz LogoQuartz 是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。

它提供了巨大的灵 活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。

它有很多特征,如:数据库支持,集群,插件,EJB作业预构 建,JavaMail及其它,支持cron-like表达式等等。

 

该版本主要修复一些小bug,下载地址:
http://www.terracotta.org/dl/quartz-oss-sign-up

该项目已经被 Terracotta收购。

转自:http://www.oschina.net/news/13187/quartz-1-8-4


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/quartz-1-8-4-release
posted @ 2010-11-18 21:52 88250 阅读(191) | 评论 (0)编辑 收藏

作者 Werner Schuster 译者 杨晨 发布于 2010年11月13日 下午6时40分

除了Smalltalkers之外,动态语言程序员使用的工具和IDE等都是用底层语言编写的。但是是对于用户(例如开发者)来说,使用原生开发工 具是大有裨益的。例如如果编辑器和IDE是原生的话,这就意味着开发者能够即时扩展他们的工具,而不需要在另外一种语言和平台上浪费时间。Java开发者 现在有一大批Java原生IDE可供选择,而且均可以编写一些Java代码进行扩展。不过这种情况对于JavaScript和Ruby来说并不适用。 但是,两个新发布的IDE改变了这种现状:JavaScript原生IDECloud9和JRuby原生IDE RedCar

Cloud9 - Javascript

使用JavaScript和HTML编写编辑器和IDE在五年前还是一件很难想象的事情。但是在接下来的数年内,JavaScript VM变得更快,HTML的组件也有足够的能力构建复杂的编辑器。Mozilla程序员的编辑器Skywriter(前身是Bespin)就是使用Canvas元素和API来绘制的。

项目最初的时候,Cloud9仅仅是重新组织了一下Eclipse的视觉元素,而且它也同样使用了Eclipse的插件思想。所有的功能都是由插件来完成 的,包括编辑器,视图,行为等。JavaScript插件的一个好处是可以轻松处理JSON格式的元数据描述字符,让插件开发者省心不少。

从功能上来说,现在讨论Cloud9还是太早了 - 至少和成熟的IDE相比。不过现在它已经有很多很方便的功能了。JavaScript Debugging已经支持GUI、Node.js脚本调试的连接器以及Chrome runtimes,并且在GUI中能够挂起,恢复和设置断点。这个特性的关键在于使用了JavaScript VM的内建调试器。

Cloud9使用ACE作为编辑器组件。Skywriter 使用Canvas和ACE来绘制编辑器以及操作DOM。编辑器的窗格是DIV元素;ACE能够决定在编辑器中哪些能够显示,把这些内容作为DIV元素渲染 然后加入到编辑器的DIV中。ACE使用多层DIV来渲染编辑器中不同的元素,尤其是光标和选择高亮的实现。

看起来现在的HTML渲染器和DOM已经足够强大,能够让ACE高速运行,给用户感觉是像一个原生的编辑器组件。

对编辑器组件大有裨益的一个HTML5 API是Web Worker API,这个组件允许JavaScript代码能够新建JavaScript进程,而不是所谓的无共享的进程,它们之间的通信是使用JSON格式的数据。 在程序员的编辑器中,在后台运行任务是非常重要的;每次敲击键盘或者操作都会产生大量的工作。使用正则表达式的语法高亮就是其中之一,但是,现代编辑器需 要解析源代码来做语义高亮,例如,用不同颜色表示局部变量和全局变量,静态方法和虚拟方法等。其他的特性还包括代码折叠支持等。可以聪明地通过使用 setTimeout来在前台线程中运行这些任务。Web工程师从而不需要破解内部结构,而能够直接在后台运行额外的任务,充分利用多核结构。

虽然名字中带有云的概念,但是Cloud9还可以默认在本地安装和运行,并且可以访问本地文件系统。它在后端使用JavaScript编写的Node.js文件来通过socket进行通信。Node.js将文件内容封装成jsdav库所支持的WebDAV格式。

Skywriter和Cloud9团队最近声称将兴趣放在协作和开发插件共享,特定语言功能等特性。要是这是真的的话,那就又避免了一场IDE战争。

Cloud9 IDE博客提供了新版本的更新信息。GitHub是代码托管的好地方。Cloud9 IDE可以能够通过代码下载安装,在后端服务器运行Node.js和在浏览器中直接安装。

RedCar - JRuby

RedCar是一个可扩展的编辑器,以发展成为IDE为目标。它是使用Ruby,更准确的说是JRuby编写的。RedCar使用SWT作为GUI框架,这样使其能够跨平台使用。

内建的REPL使得程序员能够通过API来探索和发现更多的功能,现存的插件能够帮助程序员更加简单地扩展系统。实际上,RedCar也能够使用HTML/JavaScript进行扩展,而不是仅仅只使用SWT组件或者绘图API。

TextMate用户听到RedCar能够支持TextMate插件将会非常高兴,因为这将使得迁移工作更加轻松。

对RedCar的深入介绍以及如何扩展之类的信息都可以在InfoQ对RedCar创建者Dan Lucraft的采访记录中找到。RedCar Twitter账户或者博客都是获取这些信息的好场所。RedCar还可以和Ruby Gem共存。

转自:http://www.infoq.com/cn/news/2010/11/cloud9ide-redcar-javascript-ruby

 


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/2010/11/18/cloud9ide-redcar-javascript-ruby
posted @ 2010-11-18 09:47 88250 阅读(328) | 评论 (0)编辑 收藏

在过去的几年里,IPv6已经逐渐慢慢地成为主流,但许多IT专业人士在面临IPv6时还手足无措,的确,IPv6和IPv4存在很大的不同,本文为此而写,希望能帮助你消除IPv6恐惧症。

1、IPv6地址是128位十六进制数

IPv4地址是有4个数字位组(总共32位)组成的,IPv6地址的长度时128位,而且是由16进制字符组成的。在IPv4中,每个位组由0-255的十进制数字组成,位组之间由英文的句号隔开,IPv6地址由8个为组组成,每个位组由4个字符的16进制数字组成。

2、很容易识别链路本地单播地址

IPv6为不同的地址类型保留了特殊的地址头,最明显的一个例子就是链路本地单播地址都是以PE80开头的,多播地址都是以FF0x开头,这里的x是一个占位符,可以用数字1-8替换它。

3、支持地址缩写

因为IPv6的地址比较长,往往会包含很多0,如果某个位组的字符全部是0,则这些0可以缩写为一个0,例如,下面的地址:

FE80:CD00:0000:0CDE:1257:0000:211E:729C

可以缩写为

FE80:CD00:0:CDE:1257:0:211E:729C

4、可省略连续的0

如果连续多个位组的字符全部是0,则可以省略掉所有得0,例如,下面的地址:

FE80:CD00:0000:0000:0000:0000:211E:729C

除了可以按第3条介绍的方法缩写外,还可以直接省略掉连续的0,用两个英文冒号代替,操作系统看到这样的IPv6地址后,自然会知道它们之间的字符全是0。因此上面的地址可以简写为

FE80:CD00::211E:729C

5、IPv6的环回地址

在IPv4中,我们知道环回地址是指向本机的一个特殊地址,即我们熟悉的127.0.0.1,IPv6也不例外,同样设计了环回地址,如下:

0000:0000:0000:0000:0000:0000:0000:0001

参考第4条的省略写法,IPv6的环回地址就成了

::1

这看上去是不是不像是一个有效的IP地址啊。

6、不需要传统的子网掩码

在IPv4中,每个IP地址必须要搭配一个子网掩码才能使用,IPv6也使用了子网的概念,但子网ID是直接嵌入到地址中的。在IPv6中,前48 位表示网络前缀,紧接着的16位是子网ID,最后64位才是接口标识,即接口ID或设备ID。如果需要的话,预留给设备ID的位可以借用来表示额外的子网 掩码,但通常是不需要的,因为16位子网和64位设备ID可以提供多达65536个子网。

7、IPv6仍然需要DNS

在IPv4中,主机记录(即A记录)将IP地址映射到主机名,IPv6仍然要使用DNS技术,但IPv6不再使用主机记录,相反,IPv6使用AAAA资源记录,ip6.arpa用于反向主机名的解析。

8、可以跨IPv4网络实现IPv6隧道通信

导致IPv6迟迟得不到有效推进的一个原因就是和IPv4不完全兼容,因此出现了在IPv4网络上走IPv6通信的隧道技术,一个是Teredo, 另一个是6to4,虽然它们的工作方法有点不一样,但基本思想都是将IPv6数据包封装成IPv4数据包进行传输,但通信的两端都需要具有封包和解包的能 力。

9、你可能已经在使用IPv6了

从Windows Vista开始,微软默认就安装了IPv6驱动,并默认启用了IPv6协议,因为这一切都是自动配置的,你可能还不知情,但只有操作系统支持IPv6还不 够,所有交换机和路由器都必须支持,此外,还有一些设计得很差的应用程序将IPv4地址硬编码到程序中了,它们都是阻碍IPv6普及的绊脚石。

10、Windows并没有完整支持IPv6

虽然微软在支持IPv6上表现得很积极,但Windows却并没有完整地支持IPv6,例如,在Windows中,我们以往可以使用UNC(通用命 名约定)访问网络共享文件夹(如\\127.0.0.1\C$),但现在却不能使用IPv6这样做,因为Windows看到IPv6地址中的冒号时,它会 把它当做驱动器盘符对待。

为了解决这个问题,微软为IPv6地址转换建立了一个特殊的域,如果你在UNC路径中使用IPv6地址,你必须使用破折号代替冒号,并在地址的末尾 加上.ipv6.literal.net后缀,例如FE80-AB00–200D-617B.ipv6.literal.net。

转自:http://www.oschina.net/bbs/thread/13034


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/17/1290007783671.html
posted @ 2010-11-17 23:30 88250 阅读(207) | 评论 (0)编辑 收藏

Wine Logo开源 Win32/64 API 实现 wine 项目发布了 1.3.7 版本,改善系统托盘区支持

英文发布公告源代码包下载

 

 

本次更新如下要素:

  • 改善系统托盘区的支持;
  • 更好的支持带有汇编的安装程序(?);
  • 实现大量 M$ VC 运行库 'secure' 函数;
  • 修复大量 GStreamer 支持的 Bug;
  • 进一步改善了 MSXML 的支持;
  • 翻译更新;
  • 各种 Bug 修复。

英文发布公告源代码包下载


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/15/1289782722133.html
posted @ 2010-11-15 08:59 88250 阅读(118) | 评论 (0)编辑 收藏

B3log LogoGAE 博客 —— B3LOG Solo 0.2.0 正式发布了。

该版本除了修复 Bugs,还增加了文件上传,改进了缓存,以及加入了新皮肤 i-nove(移植自 iNove)。

这个版本主要是 Bugs 修复及增强稳定性。另外,同步 Google Buzz 的残次鸡肋功能已经移除(只是注释了界面显示代码 - -~)。

新特性

  • 加入了文件上传、下载
  • 加入了页面评论
  • 加入了代码高亮
  • 加入了缓存状态查看
  • 加入了移除未使用标签
  • 加入了页面关键字、描述自定义

Bug 修复

  • 修复了文章页面缓存重复问题
  • 修复了博客配置偶尔会自动初始化问题
  • 修复了后台评论过多时的显示问题
  • 修复了站外相关阅读显示站内文章问题

改进

  • 改进了博客地址配置的错误检查
  • 改进了博客同步异常显示
  • 改进了后台管理评论时的数据加载

其他

  • 移除了同步 Google Buzz 功能
  • 取消从 0.1.0 到 0.1.1 自动升级后台任务
  • 加入了新皮肤——i-nove

具体改动可以看这里

升级

如果您是 0.1.1 的用户,那么请在部署完 0.2.0 后登录后台,访问 http://${application-id}.appspot.com/upgrade/v011-v020.do 进行升级。

改升级程序主要是对页面评论特性进行数据一致性升级。

项目

如果在使用、测试中发现任何问题,如果您有任何意见或建议,请告知我们 :-)

作者博客

发布历史

  1. GAE 博客——B3log Solo 0.1.1 发布了!
  2. B3log Solo 0.1.0 发布了!
  3. B3log Solo 0.1.0-preview2 发布了!
  4. Solo 0.1.0-Preview1 发布了

本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/11/1289491357284.html
posted @ 2010-11-12 00:03 88250 阅读(118) | 评论 (0)编辑 收藏

项目新闻

NetBeans IDE 7.0 测试人员通缉中——注册 NetCAT 7.0!

image 你喜欢玩弄软件并猎寻缺陷吗?如果你是有经验的 NetBeans IDE 用户,并且从十一月到二月的每周都有几小时空闲,就可以加为到 NetCAT 7.0 项目中的其他社区先锋队员里。让你的 NetBeans Bug 得到修复并在其间结交朋友。请注册 NetCAT 7.0!


插件:PHP Nette 框架

Ondrej Brejla 的 PHP Nette 框架插件提供了对 Nette 框架(一个用于快速简便地创建质优且崭新的 Web 应用程序的框架)的支持。该插件提供了对“Latte”模板语言的内建支持,带有语法高亮和代码完成。

文章

NetBeans、Drupal 插件和 Drupal 设置

有关如何找到并安装 Drupal NetBeans 插件,然后在 NetBeans IDE 中设置现有 Drupal 项目的概述。

设置 NetBeans 以开发谷歌 Android 应用

有关使用诸如 NetBeans IDE 的集成开发环境开发谷歌 Android 应用程序的快速入门文章。

博客

NetBeans IDE 7.0 M2 中的 PHP 支持有什么新点?

该博文审阅了在 NetBeans IDE 7.0 第二个里程碑版本中的增强和新功能。

NetBeans Maven:比 M2Eclipse 还好?

Gunther Popp 亲身尝试了 NetBeans IDE 7.0 M2 的 Maven 3 支持,并发现了许多强大功能。

使用 NetBeans 开发 GAE(Java)应用

image B3LOG Solo 是一个使用 NetBeans IDE 开发的基于 Google App Engine(Java)的博客程序,今日发布 0.2.0 版。查看项目网站以了解更多细节。


社区

Java 焦点博客系列

由甲骨文传道士 Roger Brinkley 和 Terrence Barr 主持,Java 焦点博客是一个新的每周秀,包括深度采访、新闻,以及为并且从 Java 开发人员带来领悟。最近的客人包括 Mark Reinhold,甲骨文 Java 平台组的首席架构师。

练习

NetBeans 平台实验室在 Devoxx,2010-11-12

请加入 Geertjan Wielenga 和 Anton Epple 在 Devoxx 2010 举办的动手实验室。该实验室将提供对 NetBeans 平台的详尽介绍,它如何工作以及如何开始使用它。

NetBeans 平台在甲骨文技术网络开发人员日,维也纳,11-11

在 11 月 11 日于奥地利维也纳举办的甲骨文开发人员日上得到对 NetBeans 平台的介绍。将举办探查 NetBeans 平台背后的概念的研讨会,以及学会在 NetBeans 平台上创建模块化 Swing 应用程序的动手实验室。

发布本期时事通讯的是: D. L. 88250

本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/11/1289444119462.html
posted @ 2010-11-11 10:55 88250 阅读(134) | 评论 (0)编辑 收藏

今年2 月份的时候得知 Kenai.com 将与 java.net 合并,半年多了,终于 beta 了。

Java.net

目前 kenai.com 依然可以访问,等上面的项目迁移得差不多就会关闭。


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://88250.b3log.org/articles/2010/11/11/1289438998967.html
posted @ 2010-11-11 09:30 88250 阅读(90) | 评论 (0)编辑 收藏

昨晚买了个域名:b3log.info。

现在已经可以使用 www.b3log.info 访问我的博客了,但还不知道在 GAE 上如何绑定顶级域名。

本来是想买 b3log.org 的,但对我来说贵了点($14.99),还是先买这个便宜货($1.99,第一年)将就下。。。。


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://www.b3log.info/articles/2010/11/09/1289285414380.html
posted @ 2010-11-09 14:50 88250 阅读(149) | 评论 (0)编辑 收藏

B3log Logo按目前的测试情况看,GAE 博客 ——  B3LOG Solo 下周可以进行 0.2.0 版的发布。

该版本除了修复 Bugs,还增加了文件上传,改进了缓存,以及加入了新皮肤 i-nove(移植自 iNove)。

 

这个版本主要是 Bugs 修复及增强稳定性。另外,同步 Google Buzz 的残次鸡肋功能已经移除(只是注释了界面显示代码 - -~)。

具体改动可以看这里

B3LOG Solo 0.2.0 发布日期定为 11 月 11 日。


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/07/1289137888000.html
posted @ 2010-11-07 21:51 88250 阅读(128) | 评论 (0)编辑 收藏

Berkeley DB 是历史悠久的嵌入式数据库系统,主要应用在 Unix/Linux 操作系统上,其设计思想是简单、小巧、可靠、高性能。

Java 版的 Berkeley DB 4.1.6 在性能上比 4.0 有三倍的性能提升,支持多线程的线程管理和高级内存节点压缩。

下载:http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html

转自:http://www.oschina.net/news/12936/berkeley-db-java-4-1-6


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/07/1289125532482.html
posted @ 2010-11-07 18:25 88250 阅读(102) | 评论 (0)编辑 收藏

今早发现挂在 Google Code 上的 B3log Solo 项目 Downloads 出现了统计问题:

GoogleCode Bug

下载数统计于昨天半夜被清 0 了。

0.0.1-preview1 的上传日期变 1969 年?在我未出生之前就已经在使用为开发 Google Code?

。。。。


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/05/1288919142093.html
posted @ 2010-11-05 09:06 88250 阅读(170) | 评论 (0)编辑 收藏

亲爱的QQ用户:当您看到这封信的时候,我们刚刚作出了一个非常艰难的决定。在360公司停止对QQ进行外挂侵犯和恶意诋毁之 前,我们决定将在装有360软件的电脑上停止运行QQ软件。我们深知这样会给您造成一定的不便,我们诚恳地向您致歉。同时也把作出这一决定的原因写在下 面,盼望得到您的理解和支持。

 

一、保障您的QQ帐户安全

近期360强制推广并胁迫用户安装非法外挂“扣扣保镖”。该软件劫持了QQ的安全模块,导致了QQ失去相关功能。在360软件运行环境下,我们无法保障您的QQ帐户安全。

二、对没有道德底线的行为说不

360屡屡制造“QQ侵犯用户隐私”的谣言,对QQ的安全功能进行恶意污蔑。事实上QQ安全模块绝没有进行任何用户隐私数据的扫描、监控,更绝对没有上传用户数据。目前我们已经将QQ安全模块代码交由第三方机构检测,以证明我们的清白。

更甚的是,360作为一家互联网安全公司,竟推出外挂软件,公然站到了“安全”的对立面,对其他公司的软件进行劫持和控制。这些都是没有道德底线的行为。

三、抵制违法行为

任何商业行为,无论出于何种目的,都应该在国家法律法规的框架下进行。而360竟然采用“外挂”这种非法手段,破坏腾讯公司的正常运营。

360已经在用户电脑桌面上对QQ发起了劫持和破坏。我们本可以选择技术对抗,但考虑再三,我们还是决定不能让您的电脑桌面成为“战场”,而把选择软件的权利交给您。

十二年来,QQ有幸能陪伴着您成长;未来日子,我们期待与您继续同行!

腾讯公司
2010年11月3日

 

 

----

关了 360 就可以正常使用 QQ 了,不用卸载嘛。



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/03/1288791082656.html
posted @ 2010-11-03 21:31 88250 阅读(127) | 评论 (0)编辑 收藏

Hibernate LogoInfoQ Logo

Hibernate是 最流行的对象关系映射(ORM)引擎之一,它提供了数据持久化和查询服务。在你的项目中引入Hibernate并让它跑起来是很容易的。但是,要让它跑得 好却是需要很多时间和经验的。通过我们的使用Hibernate 3.3.1和Oracle 9i的能源项目中的一些例子,本文涵盖了很多Hibernate调优技术。其中还提供了一些掌握Hibernate调优技术所必需的数据库知识。

我们假设读者对Hibernate有一个基本的了解。如果一个调优方法在Hibernate 参考文档(下文简称HRD)或其他调优文章中有详细描述,我们仅提供一个对该文档的引用并从不同角度对其做简单说明。我们关注于那些行之有效,但又缺乏文档的调优方法。

4.6 HQL调优

4.6.1 索引调优

HQL看起来和SQL很相似。从HQL的WHERE子句中通常可以猜到相应的SQL WHERE子句。WHERE子句中的字段决定了数据库将选择的索引。

大多数Hibernate开发者所常犯的一个错误是无论何时,当需要新WHERE子句的时候都会创建一个新的索引。因为索引会带来额外的数据更新开销,所以应该争取创建少量索引来覆盖尽可能多的查询。
4.1节让你使用一个集合来处理所有可能的数据搜索条件。如果这不太实际,那么你可以使用后端剖析工具来创建一个针对应用程序涉及的所有 SQL的集合。基于那些搜索条件的分类,你最终会得到一个小的索引集。与此同时,还可以尝试向WHERE子句中添加额外的谓语来匹配其他WHERE子句。

范例7

有两个UI搜索器和一个后端守护进程搜索器来搜索名为iso_deals的表。第一个UI搜索器在unexpectedFlag、dealStatus、tradeDate和isold属性上有谓语。

第二个UI搜索器基于用户键入的过滤器,其中包括的内容除tradeDate和isold以外还有其他属性。开始时所有这些过滤器属性都是可选的。
后端搜索器基于isold、participantCode和transactionType属性。
经过进一步业务分析,发现第二个UI搜索器实际是基于一些隐式的unexpectedFlag和dealStatus值来选择数据的。我们还让tradeDate成为过滤器的必要属性(为了使用数据库索引,每个搜索过滤器都应该有必要属性)。

鉴于这一点,我们依次使用unexpectedFlag、dealStatus、tradeDate和isold构造了一个复合索引。两个UI搜索 器都能共用它。(顺序很重要,如果你的谓语以不同的顺序指定这些属性或在它们前罗列了其他属性,数据库就不会选择该复合索引。)

后端搜索器和UI搜索器区别太大,因此我们不得不为它构造另一个复合索引,依次使用isold、participantCode和transactionType。

4.6.2绑定参数 vs.字符串拼接

既可以使用绑定参数构造HQL的WHERE子句,也可以使用字符串拼接的方法,该决定对性能会有一定影响。使用绑定参数的原因是让数据库一次解析 SQL,对后续的重复请求复用生成好的执行计划,这样做节省了CPU时间和内存。然而,为达到最优的数据访问效率,不同的绑定值可能需要不同的SQL执行 计划。

例如,一小段数据范围可能只返回数据总量的5%,而一大段数据范围可能返回数据总量的90%。前者使用索引更好,而后者则最好使用全表扫描。

建议OLTP使用绑定参数,数据仓库使用字符串拼接,因为OLTP通常在一个事务中重复插入和更新数据,只取少量数据;数据仓库通常只有少量SQL查询,有一个确定的执行计划比节省CPU时间和内存更为重要。

要是你知道你的OLTP搜索对不同绑定值应该使用相同执行计划又该怎么办呢?

Oracle 9i及以后版本在第一次调用绑定参数并生成执行计划时能探出参数值。后续调用不会再探测,而是重用之前的执行计划。

4.6.3聚合及排序

你可以在数据库中进行聚合和“order by”,也可以在应用程序的服务层中事先加载所有数据然后做聚合和“order by”操作。推荐使用前者,因为数据库在这方面通常会比你的应用程序做得好。此外,这样做还能节省网络带宽,这也是一种拥有跨数据库移植性的做法。

当你的应用程序对数据聚合和排序有HQL不支持的特定业务规则时除外。

4.6.4覆盖抓取策略

详见4.7.1节

4.6.5本地查询

本地查询调优其实并不直接与HQL有关。但HQL的确可以让你直接向底层数据库传递本地查询。我们并不建议这么做,因为本地查询在数据库间不可移植。

4.7抓取策略调优

抓取策略决定了在应用程序需要访问关联对象时,Hibernate以何种方式以及何时获取关联对象。HRD中的第20章“改善性能”对该主题作了很好的阐述,我们在此将关注它的使用方法。

4.7.1覆盖抓取策略

不同的用户可能会有不同的数据抓取要求。Hibernate允许在两个地方定义数据抓取策略,一处是在映射元数据中,另一处是在HQL或Criteria中覆盖它。

常见的做法是基于主要的抓取用例在映射元数据中定义默认抓取策略,针对少数用例在HQL和Criteria中覆盖抓取策略。

假设pojoA和pojoB是父子关系实例。如果根据业务规则,只是偶尔需要从实体两端加载数据,那你可以声明一个延迟加载集合或代理抓取 (proxy fetching)。当你需要从实体两端获取数据时,可以用立即抓取(eager fetching)覆盖默认策略,例如使用HQL或Criteria配置连接抓取(join fetching)。

另一方面,如果业务规则在大多数时候需要从实体两端加载数据,那么你可以声明立即抓取并在Criteria中设置延迟加载集合或代理抓取来覆盖它(HQL目前还不支持这样的覆盖)。

4.7.2 N+1模式或是反模式?

select抓取会导致N+1问题。如果你知道自己总是需要从关联中加载数据,那么就该始终使用连接抓取。在下面两个场景中,你可能会把N+1视为一种模式而非反模式。

第一种场景,你不知道用户是否会访问关联对象。如果他/她没有访问,那么你赢了;否则你仍然需要额外的N次select SQL语句。这是一种令人左右为难的局面。

第二种场景,pojoA和很多其他POJO有one-to-many关联,例如pojoB和pojoC。使用立即的内连接或外连接抓取会在结果集中 将pojoA重复很多次。当pojoA中有很多非空属性时,你不得不将大量数据加载到持久层中。这种加载需要很多时间,既有网络带宽的原因,如果 Hibernate的会话是有状态的,其中也会有会话缓存的原因(内存消耗和GC暂停)。

如果你有一个很长的one-to-many关联链,例如从pojoA到pojoB到pojoC以此类推,情况也是类似的。

你也许会去使用HQL中的DISTINCT关键字或Cirteria中的distinct功能或是Java的Set接口来消除重复数据。但所有这些都是在Hibernate(在持久层)中实现的,而非数据库中。

如果基于你的网络和内存配置的测试表明N+1性能更好,那么你可以使用批量抓取、subselect抓取或二级缓存来做进一步调优。

范例8

以下是一个使用批量抓取的HBM文件片段:

<class name="pojoA" table="pojoA">

<set name="pojoBs" fetch="select" batch-size="10">

<key column="pojoa_id"/>

</set>
</class>

以下是多端pojoB生成的SQL:

selectfrom pojoB where pojoa_id in(?,?,?,?,?, ?,?,?,?,?);

问号数量与batch-size值相等。因此N次额外的关于pojoB的select SQL语句被减少到了N/10次。

如果将fetch="select"替换成fetch="subselect",pojoB生成的SQL语句就是这样的:

selectfrom pojoB where pojoa_id in(select id from pojoA where …); 

尽管N次额外的select减少到1次,但这只在重复运行pojoA的查询开销很低时才有好处。

如果pojoA中的pojoB集合很稳定,或pojoB有pojoA的many-to-one关联,而且pojoA是只读引用数据,那么你可以使用二级缓存来缓存pojoA以消除N+1问题(4.8.1节中有一个例子)。

4.7.3延迟属性抓取

除非有一张拥有很多你不需要的字段的遗留表,否则不应该使用这种抓取策略,因为它的延迟属性分组会带来额外的SQL。

在业务分析和设计过程中,你应该将不同数据获取或修改分组放到不同的领域对象实体中,而不是使用这种抓取策略。

如果不能重新设计遗留表,可以使用HQL或Criteria提供的投影功能来获取数据。

4.8 二级缓存调优

HRD第20.2节 “二级缓存”中的描述对大多数开发者来说过于简单,无法做出选择。3.3版及以后版本不再推荐使用基于“CacheProvider”的缓存,而用基于“RegionFactory”的缓存,这也让人更糊涂了。但是就算是最新的3.5参考文档也没有提及如何使用新缓存方法。

出于下述考虑,我们将继续关注于老方法:

  • 所有流行的Hibernate二级缓存提供商中只有JBoss Cache 2Infinispan 4Ehcache 2支持新方法。OSCacheSwarmCacheCoherenceGigaspaces XAP-Data Grid只支持老方法。
  • 两种方法共用相同的<cache>配置。例如,它们仍旧使用相同的usage属性值“transactional|read-write|nonstrict-read-write|read-only”。
  • 多个cache-region适配器仍然内置老方法的支持,理解它能帮助你快速理解新方法。

4.8.1 基于CacheProvider的缓存机制

理解该机制是做出合理选择的关键。关键的类/接口是CacheConcurrencyStrategy和它针对4中不同缓存使用的实现类,还有EntityUpdate/Delete/InsertAction。

针对并发缓存访问,有三种实现模式:

  • 针对“read-only”的只读模式。
  • 无论是锁还是事务都没影响,因为缓存自数据从数据库加载后就不会改变。

  • 针对“read-write”和“nonstrict-read-write”的非事务感知(non-transaction-aware)读写模式。
  • 对缓存的更新发生在数据库事务完成后。缓存需要支持锁。

  • 针对“transactional”的事务感知读写。
  • 对缓存和数据库的更新被包装在同一个JTA事务中,这样缓存与数据库总是保持同步的。数据库和缓存都必须支持JTA。尽管缓存事务内部依赖于缓存锁,但Hibernate不会显式调用任何的缓存锁函数。

以数据库更新为例。EntityUpdateAction对于事务感知读写、“read-write”的非事务感知读写,还有“nonstrict-read-write”的非事务感知读写相应有如下调用序列:

  • 在一个JTA事务中更新数据库;在同一个事务中更新缓存。
  • 软锁缓存;在一个事务中更新数据库;在上一个事务成功完成后更新缓存;否则释放软锁。
  • 软锁只是一种特定的缓存值失效表述方式,在它获得新数据库值前阻止其他事务读写缓存。那些事务会转而直接读取数据库。

    缓存必须支持锁;事务支持则不是必须的。如果缓存是一个集群,“更新缓存”的调用会将新值推送给所有副本,这通常被称为“推(push)”更新策略。

  • 在一个事务中更新数据库;在上一个事务完成前就清除缓存;为了安全起见,无论事务成功与否,在事务完成后再次清除缓存。
  • 既不需要支持缓存锁,也不需要支持事务。如果是缓存集群,“清除缓存”调用会让所有副本都失效,这通常被称为“拉(pull)”更新策略。

对于实体的删除或插入动作,或者集合变更,调用序列都是相似的。

实际上,最后两个异步调用序列仍能保证数据库和缓存的一致性(基本就是“read committed”的隔离了级别),这要归功于第二个序列中的软锁和“更新数据库”后的“更新缓存”,还有最后一个调用序列中的悲观“清除缓存”。

基于上述分析,我们的建议是: 

  • 如果数据是只读的,例如引用数据,那么总是使用“read-only”策略,因为它是最简单、最高效的策略,也是集群安全的策略。
  • 除非你真的想将缓存更新和数据库更新放在一个JTA事务里,否则不要使用“transactional”策略,因为JTA需要漫长的两阶段提交处理,这导致它基本是性能最差的策略。
  • 依笔者看来,二级缓存并非一级数据源,因此使用JTA也未必合理。实际上最后两个调用序列在大多数场景下是个不错的替代方案,这要归功于它们的数据一致性保障。

  • 如果你的数据读很多或者很少有并发缓存访问和更新,那么可以使用“nonstrict-read-write”策略。感谢它的轻量级“拉”更新策略,它通常是性能第二好的策略。
  • 如果你的数据是又读又写的,那么使用“read-write”策略。这通常是性能倒数第二的策略,因为它要求有缓存锁,缓存集群中使用重量级的“推”更新策略。

范例9

以下是一个ISO收费类型的HBM文件片段:

<class name="IsoChargeType">
   <property name="isoId" column="ISO_ID" not-null="true"/>

   <many-to-one name="estimateMethod" fetch="join" lazy="false"/>

   <many-to-one name="allocationMethod" fetch="join" lazy="false"/>

   <many-to-one name="chargeTypeCategory" fetch="join" lazy="false"/>

</class>

一些用户只需要ISO收费类型本身;一些用户既需要ISO收费类型,还需要它的三个关联对象。简单起见,开发者会立即加载所有三个关联对象。如果项目中没人负责Hibernate调优,这是很常见的。

4.7.1节中讲过了最好的方法。因为所有的关联对象都是只读引用数据,另一种方法是使用延迟抓取,打开这些对象的二级缓存以避免N+1问题。实际上前一种方法也能从引用数据缓存中获益。

因为大多数项目都有很多被其他数据引用的只读引用数据,上述两种方法都能改善全局系统性能。

4.8.2 RegionFactory

下表是新老两种方法中对应的主要类/接口:

新方法

老方法

RegionFactory

CacheProvider

Region

Cache

EntityRegionAccessStrategy

CacheConcurrencyStrategy

CollectionRegionAccessStrategy

CacheConcurrencyStrategy

第一个改进是RegionFactory构建了特定的Region,例如EntityRegion和TransactionRegion,而不是使 用一个通用的访问Region。第二个改进是对于特定缓存的“usage”属性值,Region要求构建自己的访问策略,而不是所有Region都一直使 用CacheConcurrencyStrategy的4种实现。

要使用新方法,应该设置factory_class而非provider_class配置属性。以Ehcache 2.0为例:

<property name="hibernate.cache.region.factory_class">
        net.sf.ehcache.hibernate.EhCacheRegionFactory 
</property>

其他相关的Hibernate缓存配置都和老方法一样。

新方法也能向后兼容遗留方法。如果还是只配了CacheProvider,新方法中将使用下列自说明(self-explanatory)适配器和桥隐式地调用老的接口/类:

RegionFactoryCacheProviderBridge、EntityRegionAdapter、 CollectionRegionAdapter、QueryResultsRegionAdapter、 EntityAccessStrategyAdapter和CollectionAccessStrategyAdapter

4.8.3 查询缓存

二级缓存也能缓存查询结果。如果查询开销很大而且要重复运行,这也会很有帮助。

4.9批量处理调优

大多数Hibernate的功能都很适合那些每个事务都通常只处理少量数据的OLTP系统。但是,如果你有一个数据仓库或者事务需要处理大量数据,那么就另当别论了。

4.9.1使用有状态会话的非DML风格批处理

如果你已经在使用常规会话了,那这是最自然的方法。你需要做三件事:

  • 配置下列3个属性以开启批处理特性:
  •   hibernate.jdbc.batch_size 30
      hibernate.jdbc.batch_versioned_data true
      hibernate.cache.use_second_level_cache false

    batch_size设置为正值会开启JDBC2的批量更新,Hibernate的建议值是5到30。基于我们的测试,极低值和极高值性能都很差。只要取值在合理范围内,区别就只有几秒而已。如果网络够快,这个结果是一定的。

    第二个配置设为true,这要求JDBC驱动在executeBatch()方法中返回正确的行数。对于Oracle用户而言,批量更新时不能将其设为true。请阅读Oracle的《JDBC Developer’s Guide and Reference》中的“标准批处理的Oracle实现中的更新计数”(Update Counts in the Oracle Implementation of Standard Batching)以获得更多详细信息。因为它对批量插入来说还是安全的,所以你可以为批量插入创建单独的专用数据源。最后一个配置项是可选的,因为你可以在会话中显式关闭二级缓存。

  • 像如下范例中那样定期刷新(flush)并清除一级会话缓存:
  •  Session session = sessionFactory.openSession();
     Transaction tx = session.beginTransaction();

     for ( int i=0; i<100000; i++ ) {
         Customer customer = new Customer(.....);
         //if your hibernate.cache.use_second_level_cache is true, call the following:
         session.setCacheMode(CacheMode.IGNORE);
         session.save(customer);
         if (i % 50 == 0) { //50, same as the JDBC batch size
         //flush a batch of inserts and release memory:
         session.flush();
         session.clear();
         }
     }
     tx.commit();
     session.close();

    批处理通常不需要数据缓存,否则你会将内存耗尽并大量增加GC开销。如果内存有限,那这种情况会很明显。

  • 总是将批量插入嵌套在事务中。

每次事务修改的对象数量越少就意味着会有更多数据库提交,正如4.5节所述每次提交都会带来磁盘相关的开销。

另一方面,每次事务修改的对象数量越多就意味着锁定变更时间越长,同时数据库需要更大的redo log。

4.9.2使用无状态会话的非DML风格批处理

无状态会话执行起来比上一种方法更好,因为它只是JDBC的简单包装,而且可以绕开很多常规会话要求的操作。例如,它不需要会话缓存,也不和任何二级缓存或查询缓存有交互。
然而它的用法并不简单。尤其是它的操作并不会级联到所关联的实例上;你必须自己来处理它们。

4.9.3 DML风格

使用DML风格的插入、更新或删除,你直接在数据库中操作数据,这和前两种方法在Hibernate中操作数据的情况有所不同。

因为一个DML风格的更新或删除相当于前两种方法中的多个单独的更新或删除,所以如果更新或删除中的WHERE子句暗示了恰当的数据库索引,那么使用DML风格的操作能节省网络开销,执行得更好。

强烈建议结合使用DML风格操作和无状态会话。如果使用有状态会话,不要忘记在执行DML前清除缓存,否则Hibernate将会更新或清除相关缓存(见下面的范例10)。

4.9.4批量加载

如果你的HQL或Criteria会返回很多数据,那么要注意两件事:

  • 用下列配置开启批量抓取特性:
  • hibernate.jdbc.fetch_size 10

    fetch_size设置为正值将开启JDBC批量抓取特性。相对快速网络,在慢速网络中这一点更为重要。Oracle建议的经验值是10。你应该基于自己的环境进行测试。

  • 在使用上述任一方法时都要关闭缓存,因为批量加载一般是一次性任务。受限于内存容量,向缓存中加载大量数据通常也意味着它们很快会被清除出去,这会增加GC开销。

范例10

我们有一个后台任务,分段加载大量的IsoDeal数据用于后续处理。我们还会在分段数据交给下游系统处理前将其更新为处理中状态。最大的一段有50万行数据。以下是原始代码中截取出来的一段:

Query query = session.createQuery("FROM IsoDeal d WHERE chunk-clause");
query.setLockMode("d", LockMode.UPGRADE); //for Inprocess status update
List<IsoDeal> isoDeals = query.list();
for (IsoDeal isoDeal : isoDeals) { //update status to Inprocess
   isoDeal.setStatus("Inprocess");
}
return isoDeals;

包含上述代码的方法加上了Spring 2.5声明式事务的注解。加载并更新50万行数据大约花了10分钟。我们识别出了以下这些问题:

  • 由于会话缓存和二级缓存的原因,系统会频繁地内存溢出。
  • 就算没有内存溢出,当内存消耗很高时GC的开销也会很大。
  • 我们还未设置fetch_size。
  • 就算我们设置了batch_size,for循环也创建了太多update SQL语句。

不幸的是Spring 2.5不支持Hibernate无状态会话,所以我们只能关闭二级缓存;设置fetch_size;用DML风格的更新来代替for循环,以此改善性能。

但是,执行时间还是要6分钟。将Hibernate的日志级别调成trace后,我们发现是更新会话缓存造成了延时。通过在DML更新前清除会话缓存,我们将时间缩短到了4分钟,全部都是将数据加载到会话缓存中花费的时间。

4.10 SQL生成调优

本节将向你展示如何减少SQL生成的数量。

4.10.1 N+1抓取问题

“select抓取”策略会导致N+1问题。如果“连接抓取”策略适合你的话,你应该始终使用该策略避免N+1问题。

但是,如果“连接抓取”策略执行效果不理想,就像4.7.2节中那样,你可以使用“subselect抓取”、“批量抓取”或“延迟集合抓取”来减少所需的额外SQL语句数。

4.10.2 Insert+Update问题

范例11

我们的ElectricityDeal与DealCharge有单向one-to-many关联,如下列HBM文件片段所示:

<class name="ElectricityDeal"
       select-before-update="true" dynamic-update="true"

       dynamic-insert="true">
    <id name="key" column="ID">

        <generator class="sequence">
            <param name="sequence">SEQ_ELECTRICITY_DEALS</param>

        </generator>
    </id>
    …
    <set
name="dealCharges" cascade="all-delete-orphan">

        <key column="DEAL_KEY" not-null="false" update="true"

             on-delete="noaction"/>
        <one-to-many class="DealCharge"/>
    </set> </class>

在“key”元素中,“not-null”和“update”对应的默认值是false和true,上述代码为了明确这些取值,将它们写了出来。

如果你想创建一个ElectricityDeal和十个DealCharge,会生成如下SQL语句:

  • 1句ElectricityDeal的插入语句;
  • 10句DealCharge的插入语句,其中不包括外键“DEAL_KEY”;
  • 10句DealCharge字段“DEAL_KEY”的更新语句。

为了消除那额外的10句更新语句,可以在那10句DealCharge插入语句中包含“DEAL_KEY”,你需要将“not-null”和“update”分别修改为true和false。

另一种做法是使用双向或many-to-one关联,让DealCharge来管理关联。

4.10.3 更新前执行select

在范例11中,我们为ElectricityDeal加上了select-before-update,这会对瞬时(transient)对象或分离(detached)对象产生额外的select语句,但却能避免不必要的数据库更新。

你应该做出一些权衡,如果对象没多少属性,不需要防止不必要的数据库更新,那么就不要使用该特性,因为你那些有限的数据既没有太多网络传输开销,也不会带来太多数据库更新开销。

如果对象的属性较多,例如是一张大的遗留表,那你应该开启该特性,和“dynamic-update”结合使用以避免太多数据库更新开销。

4.10.4 级联删除

在范例11中,如果你想删除1个ElectricityDeal和它的100个DealCharge,Hibernate会对DealCharge做100次删除。

如果将“on-delete”修改为“cascade”,Hibernate不会执行DealCharge的删除动作;而是让数据库根据ON CASCADE DELETE约束自动删除那100个DealCharge。不过,需要让DBA开启ON CASCADE DELETE约束,大多数DBA不愿意这么做,因为他们想避免父对象的意外删除级联到它的依赖对象上。此外,还要注意,该特性会绕过Hibernate对 版本数据(versioned data)的常用乐观锁策略。

4.10.5 增强的序列标识符生成器

范例11中使用Oracle的序列作为标识符生成器。假设我们保存100个ElectricityDeal,Hibernate会将下面的SQL语句执行100次来获取下一个可用的标识符:

select SEQ_ELECTRICITY_DEALS.NEXTVAL from dual; 

如果网络不是很快,那这无疑会降低效率。3.2.3及后续版本中增加了一个增强的生成器“SequenceStyleGenerator”,它带了两个优化器:hilo和pooled。尽管HRD的第5章“基础O/R映射” 讲到了这两个优化器,不过内容有限。两个优化器都使用了HiLo算法,该算法生成的标识符等于Hi值加上Lo值,其中Hi值代表组号,Lo值顺序且重复地从1迭代到最大组大小,组号在Lo值“转回到”1时加1。

假设组大小是5(可以用max_lo或increment_size参数来表示),下面是个例子:

  • hilo优化器
  • 组号取自数据库序列的下一个可用值,Hi值由Hibernate定义,是组号乘以increment_size参数值。

  • pooled优化器
  • Hi值直接取自数据库序列的下一个可用值。数据库序列的增量应该设置为increment_size参数值。

直到内存组中的值耗尽后,两个优化器才会去访问数据库,上面的例子每5个标识值符访问一次数据库。使用hilo优化器时,你的序列不能再被其他应用程序使用,除非它们使用与Hibernate相同的逻辑。使用pooled优化器,在其他应用程序使用同一序列时则相当安全。

两个优化器都有一个问题,如果Hibernate崩溃,当前组内的一些标识符值就会丢失,然而大多数应用程序都不要求拥有连续的标识符值(如果你的数据库,比方说Oracle,缓存了序列值,当它崩溃时你也会丢失标识符值)。

如果在范例11中使用pooled优化器,新的id配置如下:

<id name="key" column="ID">
<generator class="org.hibernate.id.enhance.SequenceStyleGenerator">
<param name="sequence_name">SEQ_ELECTRICITY_DEALS</param>

<param name="initial_value">0</param>
<param name="increment_size">100</param>

<param name="optimizer ">pooled</param>
</generator>
</id>

5 总结

本文涵盖了大多数你在Hibernate应用程序调优时会觉得很有用的调优技巧,其中的大多数时间都在讨论那些行之有效却缺乏文档的调优主题,例如继承映射、二级缓存和增强的序列标识符生成器。

它还提到了一些Hibernate调优所必需的数据库知识。一些范例中包含了你可能遇到的问题的实际解决方案。

除此之外,值得一提的是Hibernate也可以和In-Memory Data Grid(IMDG)一起使用,例如Oracle的Coherance或GigaSpaces IMDG,这能让你的应用程序达到毫秒级别。

6 资源

[1] Latest Hibernate Reference Documentation on jboss.com

[2] Oracle 9i Performance Tuning Guide and Reference

[3] Performance Engineering on Wikipedia

[4] Program Optimization on Wikipedia

[5] Pareto Principle (the 80/20 rule) on Wikipedia

[6] Premature Optimization on acm.org

[7] Java Performance Tuning by Jack Shirazi

[8] The Law of Leaky Abstractions by Joel Spolsky

[9] Hibernate’s StatisticsService Mbean configuration with Spring

[10] JProbe by Quest Software

[11] Java VisualVM

[12] Column-oriented DBMS on Wikipedia

[13] Apache DBCP BasicDataSource

[14] JDBC Connection Pool by Oracle

[15] Connection Failover by Oracle

[16] Last Resource Commit Optimization (LRCO)

[17] GigaSpaces for Hibernate ORM Users

关于作者

Yongjun Jiao是SunGard Consulting Services的技术主管。过去10年中他一直是专业软件开发者,他的专长包括Java SE、Java EE、Oracle和应用程序调优。他最近的关注点是高性能计算,包括内存数据网格、并行计算和网格计算。

Stewart Clark是SunGard Consulting Services的负责人。过去15年中他一直是专业软件开发者和项目经理,他的专长包括Java核心编程、Oracle和能源交易。

查看英文原文:Revving Up Your Hibernate Engine

转自:http://www.infoq.com/cn/articles/hibernate_tuning-ii



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/03/1288789180222.html
posted @ 2010-11-03 21:00 88250 阅读(187) | 评论 (0)编辑 收藏

Hibernate LogoInfoQ Logo

Hibernate是 最流行的对象关系映射(ORM)引擎之一,它提供了数据持久化和查询服务。在你的项目中引入Hibernate并让它跑起来是很容易的。但是,要让它跑得 好却是需要很多时间和经验的。通过我们的使用Hibernate 3.3.1和Oracle 9i的能源项目中的一些例子,本文涵盖了很多Hibernate调优技术。其中还提供了一些掌握Hibernate调优技术所必需的数据库知识。

我们假设读者对Hibernate有一个基本的了解。如果一个调优方法在Hibernate 参考文档(下文简称HRD)或其他调优文章中有详细描述,我们仅提供一个对该文档的引用并从不同角度对其做简单说明。我们关注于那些行之有效,但又缺乏文档的调优方法。

作者 Yongjun Jiao and Stewart Clark 译者 丁雪丰 发布于 2010年10月26日 上午12时0分

1.引言

Hibernate是最流行的对象关系映射(ORM)引擎之一,它提供了数据持久化和查询服务。在你的项目中引入Hibernate并让它跑起来是很容易的。但是,要让它跑得好却是需要很多时间和经验的。通过我们的使用Hibernate 3.3.1和Oracle 9i的能源项目中的一些例子,本文涵盖了很多Hibernate调优技术。其中还提供了一些掌握Hibernate调优技术所必需的数据库知识。

我们假设读者对Hibernate有一个基本的了解。如果一个调优方法在Hibernate 参考文档(下文简称HRD)或其他调优文章中有详细描述,我们仅提供一个对该文档的引用并从不同角度对其做简单说明。我们关注于那些行之有效,但又缺乏文档的调优方法。

2.Hibernate性能调优

调优是一个迭代的、持续进行的过程,涉及软件开发生命周期(SDLC)的所有阶段。在一个典型的使用Hibernate进行持久化的Java EE应用程序中,调优会涉及以下几个方面:

  • 业务规则调优
  • 设计调优
  • Hibernate调优
  • Java GC调优
  • 应用程序容器调优
  • 底层系统调优,包括数据库和OS。

没有一套精心设计的方案就去进行以上调优是非常耗时的,而且很可能收效甚微。好的调优方法的重要部分是为调优内容划分优先级。可以用Pareto定律(又称“80/20法则”)来解释这一点,即通常80%的应用程序性能改善源自头20%的性能问题[5]

相比基于磁盘和网络的访问,基于内存和CPU的访问能提供更低的延迟和更高的吞吐量。这种基于IO的Hibernate调优与底层系统IO部分的调优应该优先于基于CPU和内存的底层系统GC、CPU和内存部分的调优。

范例1

我们调优了一个选择电流的HQL查询,把它从30秒降到了1秒以内。如果我们在垃圾回收方面下功夫,可能收效甚微——也许只有几毫秒或者最多几秒,相比HQL的改进,GC方面的改善可以忽略不计。

好的调优方法的另一个重要部分是决定何时优化[4]

积极优化的提倡者主张开始时就进行调优,例如在业务规则和设计阶段,在整个SDLC都持续进行优化,因为他们认为后期改变业务规则和重新设计代价太大。

另一派人提倡在SDLC末期进行调优,因为他们抱怨前期调优经常会让设计和编码变得复杂。他们经常引用Donald Knuth的名言“过早优化是万恶之源 [6]

为了平衡调优和编码需要一些权衡。根据笔者的经验,适当的前期调优能带来更明智的设计和细致的编码。很多项目就失败在应用程序调优上,因为上面提到的“过早优化”阶段在被引用时脱离了上下文,而且相应的调优不是被推迟得太晚就是投入资源过少。

但是,要做很多前期调优也不太可能,因为没有经过剖析,你并不能确定应用程序的瓶颈究竟在何处,应用程序一般都是这样演化的。

对我们的多线程企业级应用程序的剖析也表现出大多数应用程序平均只有20-50%的CPU使用率。剩余的CPU开销只是在等待数据库和网络相关的IO。

基于上述分析,我们得出这样一个结论,结合业务规则和设计的Hibernate调优在Pareto定律中20%的那个部分,相应的它们的优先级更高。

一种比较实际的做法是:

  1. 识别出主要瓶颈,可以预见其中多数是Hibernate、业务规则和设计方面的(其数量视你的调优目标而定;但三到五个是不错的开端)。
  2. 修改应用程序以便消除这些瓶颈。
  3. 测试应用程序,然后重复步骤1,直到达到你的调优目标为止。

你能在Jack Shirazi的《Java Performance Tuning》 [7]一书中找到更多关于性能调优阶段的常见建议。

下面的章节中,我们会按照调优的大致顺序(列在前面的通常影响最大)去解释一些特定的调优技术。

3. 监控和剖析

没有对Hibernate应用程序的有效监控和剖析,你无法得知性能瓶颈以及何处需要调优。

3.1.1 监控SQL生成

尽管使用Hibernate的主要目的是将你从直接使用SQL的痛苦中解救出来,为了对应用程序进行调优,你必须知道Hibernate生成了哪些 SQL。JoeSplosky在他的《The Law of Leaky Abstractions》一文中详细描述了这个问题。

你可以在log4j中将org.hibernate.SQL包的日志级别设为DEBUG,这样便能看到生成的所有SQL。你还可以将其他包的日志级别设为DEBUG,甚至TRACE来定位一些性能问题。

3.1.2 查看Hibernate统计

如果开启hibernate.generate.statistics,Hibernate会导出实体、集合、会话、二级缓存、查询和会话工厂的统计信息,这对通过SessionFactory.getStatistics()进行的调优很有帮助。为了简单起见,Hibernate还可以使用MBean“org.hibernate.jmx.StatisticsService”通过JMX来导出统计信息。你可以在这个网站找到配置范例

3.1.3 剖析

一个好的剖析工具不仅有利于Hibernate调优,还能为应用程序的其他部分带来好处。然而,大多数商业工具(例如JProbe [10])都很昂贵。幸运的是Sun/Oracle的JDK1.6自带了一个名为“Java VisualVM” [11]的调试接口。虽然比起那些商业竞争对手,它还相当基础,但它提供了很多调试和调优信息。

4. 调优技术

4.1 业务规则与设计调优

尽管业务规则和设计调优并不属于Hibernate调优的范畴,但此处的决定对后面Hibernate的调优有很大影响。因此我们特意指出一些与Hibernate调优有关的点。

在业务需求收集与调优过程中,你需要知道:

  • 数据获取特性包括引用数据(reference data)、只读数据、读分组(read group)、读取大小、搜索条件以及数据分组和聚合。
  • 数据修改特性包括数据变更、变更组、变更大小、无效修改补偿、数据库(所有变更都在一个数据库中或在多个数据库中)、变更频率和并发性,以及变更响应和吞吐量要求。
  • 数据关系,例如关联(association)、泛化(generalization)、实现(realization)和依赖(dependency)。

基于业务需求,你会得到一个最优设计,其中决定了应用程序类型(是OLTP还是数据仓库,亦或者与其中某一种比较接近)和分层结构(将持久层和服务 层分离还是合并),创建领域对象(通常是POJO),决定数据聚合的地方(在数据库中进行聚合能利用强大的数据库功能,节省网络带宽;但是除了像 COUNT、SUM、AVG、MIN和MAX这样的标准聚合,其他的聚合通常不具有移植性。在应用服务器上进行聚合允许你应用更复杂的业务逻辑;但你需要 先在应用程序中载入详细的数据)。

范例2

分析员需要查看一个取自大数据表的电流ISO(Independent System Operator)聚合列表。最开始他们想要显示大多数字段,尽管数据库能在1分钟内做出响应,应用程序也要花30分钟将1百万行数据加载到前端UI。经 过重新分析,分析员保留了14个字段。因为去掉了很多可选的高聚合度字段,从剩下的字段中进行聚合分组返回的数据要少很多,而且大多数情况下的数据加载时 间也缩小到了可接受的范围内。

范例3

过24个“非标准”(shaped,表示每小时都可以有自己的电量和价格;如果所有24小时的电量和价格相同,我们称之为“标准”)小时会修改小时电流交易,其中包括2个属性:每小时电量和价格。起初我们使用Hibernate的select-before-update特性,就是更新24行数据需要24次选择。因为我们只需要2个属性,而且如果不修改电量或价格的话也没有业务规则禁止无效修改,我们就关闭了select-before-update特性,避免了24次选择。

4.2继承映射调优

尽管继承映射是领域对象的一部分,出于它的重要性我们将它单独出来。HRD [1]中的第9章“继承映射”已经说得很清楚了,所以我们将关注SQL生成和针对每个策略的调优建议。

以下是HRD中范例的类图:


4.2.1 每个类层次一张表

只需要一张表,一条多态查询生成的SQL大概是这样的:

select id, payment_type, amount, currency, rtn, credit_card_type from payment

针对具体子类(例如CashPayment)的查询生成的SQL是这样的:

select id, amount, currency from payment where payment_type=’CASH’ 

这样做的优点包括只有一张表、查询简单以及容易与其他表进行关联。第二个查询中不需要包含其他子类中的属性。所有这些特性让该策略的性能调优要比其他策略容易得多。这种方法通常比较适合数据仓库系统,因为所有数据都在一张表里,不需要做表连接。

主要的缺点整个类层次中的所有属性都挤在一张大表里,如果有很多子类特有的属性,数据库中就会有太多字段的取值为null,这为当前基于行的数据库 (使用基于列的DBMS的数据仓库处理这个会更好些)的SQL调优增加了难度。除非进行分区,否则唯一的数据表会成为热点,OLTP系统通常在这方面都不 太好。

4.2.2每个子类一张表

需要4张表,多态查询生成的SQL如下:

select id, payment_type, amount, currency, rtn, credit_card type,
        case when c.payment_id is not null then 1
     when ck.payment_id is not null then 2
     when cc.payment_id is not null then 3
     when p.id is not null then 0 end as clazz

from payment p left join cash_payment c on p.id=c.payment_id left join
   cheque_payment ck on p.id=ck.payment_id left join

   credit_payment cc on p.id=cc.payment_id;

针对具体子类(例如CashPayment)的查询生成的SQL是这样的:

select id, payment_type, amount, currency
from payment p left join cash_payment c on p.id=c.payment_id;

优点包括数据表比较紧凑(没有不需要的可空字段),数据跨三个子类的表进行分区,容易使用超类的表与其他表进行关联。紧凑的数据表可以针对基于行的 数据库做存储块优化,让SQL执行得更好。数据分区增加了数据修改的并发性(除了超类,没有热点),OLTP系统通常会更好些。

同样的,第二个查询不需要包含其他子类的属性。

缺点是在所有策略中它使用的表和表连接最多,SQL语句稍显复杂(看看Hibernate动态鉴别器的长CASE子句)。相比单张表,数据库要花更多时间调优数据表连接,数据仓库在使用该策略时通常不太理想。

因为不能跨超类和子类的字段来建立复合索引,如果需要按这些列进行查询,性能会受影响。任何子类数据的修改都涉及两张表:超类的表和子类的表。

4.2.3每个具体类一张表

涉及三张或更多的表,多态查询生成的SQL是这样的:

select p.id, p.amount, p.currency, p.rtn, p. credit_card_type, p.clazz
from (select id, amount, currency, null as rtn,null as credit_card type,
1 as clazz from cash_payment union all

select id, amount, null as currency, rtn,null as credit_card type,
2 as clazz from cheque_payment union all

select id, amount, null as currency, null as rtn,credit_card type,
3 as clazz from credit_payment) p;

针对具体子类(例如CashPayment)的查询生成的SQL是这样的:

select id, payment_type, amount, currency from cash_payment; 

优点和上面的“每个子类一张表”策略相似。因为超类通常是抽象的,所以具体的三张表是必须的[开头处说的3张或更多的表是必须的],任何子类的数据修改只涉及一张表,运行起来更快。

缺点是SQL(from子句和union all子查询)太复杂。但是大多数数据库对此类SQL的调优都很好。

如果一个类想和Payment超类关联,数据库无法使用引用完整性(referential integrity)来实现它;必须使用触发器来实现它。这对数据库性能有些影响。

4.2.4使用隐式多态实现每个具体类一张表

只需要三张表。对于Payment的多态查询生成三条独立的SQL语句,每个对应一个子类。Hibernate引擎通过Java反射找出Payment的所有三个子类。

具体子类的查询只生成该子类的SQL。这些SQL语句都很简单,这里就不再阐述了。

它的优点和上节类似:紧凑数据表、跨三个具体子类的数据分区以及对子类任意数据的修改都只涉及一张表。

缺点是用三条独立的SQL语句代替了一条联合SQL,这会带来更多网络IO。Java反射也需要时间。假设如果你有一大堆领域对象,你从最上层的Object类进行隐式选择查询,那该需要多长时间啊!

根据你的映射策略制定合理的选择查询并非易事;这需要你仔细调优业务需求,基于特定的数据场景制定合理的设计决策。

以下是一些建议:

  • 设计细粒度的类层次和粗粒度的数据表。细粒度的数据表意味着更多数据表连接,相应的查询也会更复杂。
  • 如非必要,不要使用多态查询。正如上文所示,对具体类的查询只选择需要的数据,没有不必要的表连接和联合。
  • “每个类层次一张表”对有高并发、简单查询并且没有共享列的OLTP系统来说是个不错的选择。如果你想用数据库的引用完整性来做关联,那它也是个合适的选择。
  • “每个具体类一张表”对有高并发、复杂查询并且没有共享列的OLTP系统来说是个不错的选择。当然你不得不牺牲超类与其他类之间的关联。
  • 采用混合策略,例如“每个类层次一张表”中嵌入“每个子类一张表”,这样可以利用不同策略的优势。随着你项目的进化,如果你要反复重新映射,那你可能也会采用该策略。
  • “使用隐式多态实现每个具体类一张表”这种做法并不推荐,因为其配置过于繁缛、使用“any”元素的复杂关联语法和隐式查询的潜在危险性。

范例4

下面是一个交易描述应用程序的部分领域类图:

开始时,项目只有GasDeal和少数用户,它使用“每个类层次一张表”。

OilDeal和ElectricityDeal是后期产生更多业务需求后加入的。没有改变映射策略。但是ElectricityDeal有太多自己的属性,因此有很多电相关的可空字段加入了Deal表。因为用户量也在增长,数据修改变得越来越慢。

重新设计时我们使用了两张单独的表,分别针对气/油和电相关的属性。新的映射混合了“每个类层次一张表”和“每个子类一张表”。我们还重新设计了查询,以便允许针对具体交易子类进行选择,消除不必要的列和表连接。

4.3 领域对象调优

基于4.1中对业务规则和设计的调优,你得到了一个用POJO来表示的领域对象的类图。我们建议:

4.3.1 POJO调优

  • 从读写数据中将类似引用这样的只读数据和以读为主的数据分离出来。
    只读数据的二级缓存是最有效的,其次是以读为主的数据的非严格读写。将只读POJO标识为不可更改的(immutable)也是一个调优点。如果一个服务层方法只处理只读数据,可以将它的事务标为只读,这是优化Hibernate和底层JDBC驱动的一个方法。
  • 细粒度的POJO和粗粒度的数据表。
    基于数据的修改并发量和频率等内容来分解大的POJO。尽管你可以定义一个粒度非常细的对象模型,但粒度过细的表会导致大量表连接,这对数据仓库来说是不能接受的。
  • 优先使用非final的类。
    Hibernate只会针对非final的类使用CGLIB代理来实现延时关联获取。如果被关联的类是final的,Hibernate会一次加载所有内容,这对性能会有影响。
  • 使用业务键为分离(detached)实例实现equals()和hashCode()方法。
    在多层系统中,经常可以在分离对象上使用乐观锁来提升系统并发性,达到更高的性能。
  • 定义一个版本或时间戳属性。
    乐观锁需要这个字段来实现长对话(应用程序事务)[译注:session译为会话,conversion译为对话,以示区别]。
  • 优先使用组合POJO。
    你的前端UI经常需要来自多个不同POJO的数据。你应该向UI传递一个组合POJO而不是独立的POJO以获得更好的网络性能。
    有两种方式在服务层构建组合POJO。一种是在开始时加3.2载所有需要的独立POJO,随后抽取需要的属性放入组合POJO;另一种是使用HQL投影,直接从数据库中选择需要的属性。
    如果其他地方也要查找这些独立POJO,可以把它们放进二级缓存以便共享,这时第一种方式更好;其他情况下第二种方式更好。

4.3.2 POJO之间关联的调优

  • 如果可以用one-to-one、one-to-many或many-to-one的关联,就不要使用many-to-many。
  • many-to-many关联需要额外的映射表。
    尽管你的Java代码只需要处理两端的POJO,但查询时,数据库需要额外地关联映射表,修改时需要额外的删除和插入。
  • 单向关联优先于双向关联。
    由于many-to-many的特性,在双向关联的一端加载对象会触发另一端的加载,这会进一步触发原始端加载更多的数据,等等。
    one-to-many和many-to-one的双向关联也是类似的,当你从多端(子实体)定位到一端(父实体)
    这样的来回加载很耗时,而且可能也不是你所期望的。
  • 不要为了关联而定义关联;只在你需要一起加载它们时才这么做,这应该由你的业务规则和设计来决定(见范例5)。
    另外,你要么不定义任何关联,要么在子POJO中定义一个值类型的属性来表示父POJO的ID(另一个方向也是类似的)。
  • 集合调优
    如果集合排序逻辑能由底层数据库实现,就使用“order-by”属性来代替“sort”,因为通常数据库在这方面做得比你好。
    集合可以是值类型的(元素或组合元素),也可以是实体引用类型的(one-to-many或many-to-many关联)。对引用类型集合的调优主要是调优获取策略。对于值类型集合的调优,HRD [1]中的20.5节“理解集合性能”已经做了很好的阐述。
  • 获取策略调优。请见4.7节的范例5

范例5

我们有一个名为ElectricityDeals的核心POJO用于描述电的交易。从业务角度来看,它有很多many-to-one关联,例如和 Portfolio、Strategy和Trader等的关联。因为引用数据十分稳定,它们被缓存在前端,能基于其ID属性快速定位到它们。

为了有好的加载性能,ElectricityDeal只映射元数据,即那些引用POJO的值类型ID属性,因为在需要时,可以在前端通过portfolioKey从缓存中快速查找Portfolio:

<property name="portfolioKey" column="PORTFOLIO_ID" type="integer"/> 

这种隐式关联避免了数据库表连接和额外的字段选择,降低了数据传输的大小。

4.4 连接池调优

由于创建物理数据库连接非常耗时,你应该始终使用连接池,而且应该始终使用生产级连接池而非Hibernate内置的基本连接池算法。

通常会为Hibernate提供一个有连接池功能的数据源。Apache DBCP的BasicDataSource[13]是一个流行的开源生产级数据源。大多数数据库厂商也实现了自己的兼容JDBC 3.0的连接池。举例来说,你也可以使用Oracle ReaApplication Cluster [15]提供的JDBC连接池[14]以获得连接的负载均衡和失败转移。

不用多说,你在网上能找到很多关于连接池调优的技术,因此我们只讨论那些大多数连接池所共有的通用调优参数:

  • 最小池大小:连接池中可保持的最小连接数。
  • 最大池大小:连接池中可以分配的最大连接数。
    如果应用程序有高并发,而最大池大小又太小,连接池就会经常等待。相反,如果最小池大小太大,又会分配不需要的连接。
  • 最大空闲时间:连接池中的连接被物理关闭前能保持空闲的最大时间。
  • 最大等待时间:连接池等待连接返回的最大时间。该参数可以预防失控事务(runaway transaction)。
  • 验证查询:在将连接返回给调用方前用于验证连接的SQL查询。这是因为一些数据库被配置为会杀掉长时间空闲的连接,网络或数据库相关的异常也可能会杀死连接。为了减少此类开销,连接池在空闲时会运行该验证。

4.5事务和并发的调优

短数据库事务对任何高性能、高可扩展性的应用程序来说都是必不可少的。你使用表示对话请求的会话来处理单个工作单元,以此来处理事务。

考虑到工作单元的范围和事务边界的划分,有3中模式:

  • 每次操作一个会话。每次数据库调用需要一个新会话和事务。因为真实的业务事务通常包含多个此类操作和大量小事务,这一般会引起更多数据库活动(主要是数据库每次提交需要将变更刷新到磁盘上),影响应用程序性能。这是一种反模式,不该使用它。
  • 使用分离对象,每次请求一个会话。每次客户端请求有一个新会话和一个事务,使用Hibernate的“当前会话”特性将两者关联起来。
    在一个多层系统中,用户通常会发起长对话(或应用程序事务)。大多数时间我们使用Hibernate的自动版本和分离对象来实现乐观并发控制和高性能。
  • 带扩展(或长)会话的每次对话一会话。在一个也许会跨多个事务的长对话中保持会话开启。尽管这能把你从重新关联中解脱出来,但会话可能会内存溢出,在高并发系统中可能会有旧数据。

你还应该注意以下几点。 

  • 如果不需要JTA就用本地事务,因为JTA需要更多资源,比本地事务更慢。就算你有多个数据源,除非有跨多个数据库的事务,否则也不需要 JTA。在最后的一个场景下,可以考虑在每个数据源中使用本地事务,使用一种类似“Last Resource Commit Optimization”[16]的技术(见下面的范例6)。
  • 如果不涉及数据变更,将事务标记为只读的,就像4.3.1提到的那样。
  • 总是设置默认事务超时。保证在没有响应返回给用户时,没有行为不当的事务会完全占有资源。这对本地事务也同样有效。
  • 如果Hibernate不是独占数据库用户,乐观锁会失效,除非创建数据库触发器为其他应用程序对相同数据的变更增加版本字段值。

范例6

我们的应用程序有多个在大多数情况下只和数据库“A”打交道的服务层方法;它们偶尔也会从数据库“B”中获取只读数据。因为数据库“B”只提供只读数据,我们对这些方法在这两个数据库上仍然使用本地事务。

服务层上有一个方法设计在两个数据库上执行数据变更。以下是伪代码:

//Make sure a local transaction on database A exists
@Transactional (readOnly=false, propagation=Propagation.REQUIRED)
public void saveIsoBids() {
//it participates in the above annotated local transaction
insertBidsInDatabaseA();

//it runs in its own local transaction on database B
insertBidRequestsInDatabaseB(); //must be the last operation

因为insertBidRequestsInDatabaseB()是saveIsoBids ()中的最后一个方法,所以只有下面的场景会造成数据不一致:

在saveIsoBids()执行返回时,数据库“A”的本地事务提交失败。

但是,就算saveIsoBids()使用JTA,在两阶段提交(2PC)的第二个提交阶段失败的时候,你还是会碰到数据不一致。因此如果你能处理好上述的数据不一致性,而且不想为了一个或少数几个方法引入JTA的复杂性,你应该使用本地事务。

(未完待续)

关于作者

Yongjun Jiao是SunGard Consulting Services的技术主管。过去10年中他一直是专业软件开发者,他的专长包括Java SE、Java EE、Oracle和应用程序调优。他最近的关注点是高性能计算,包括内存数据网格、并行计算和网格计算。

Stewart Clark是SunGard Consulting Services的负责人。过去15年中他一直是专业软件开发者和项目经理,他的专长包括Java核心编程、Oracle和能源交易。

[译注:由于原文较长,中译版分两次发布]

查看英文原文:Revving Up Your Hibernate Engine

转自:http://www.infoq.com/cn/articles/hibernate_tuning



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/03/1288788936673.html
posted @ 2010-11-03 20:56 88250 阅读(187) | 评论 (0)编辑 收藏

 

项目新闻

社区反馈: NetBeans IDE对Git的支持

你是否对NetBeans IDE中的Git支持感兴趣? NetBeans PHP 和 Git支持小组希望你使用案例并进行反馈. 在这里学习Git支持,并发邮件给项目组:git at versioncontrol dot netbeans dot org.

插件: 太空侵入者

你是不是想在NetBeans IDE中玩 太空侵入者 ,感谢来自丹麦的Allan Gregersen ,现在你可以做到了.

文章

NetBeans平台与丹麦智能住宅

Allan Gregersen 将告诉一个应用程序用来控制能量消耗设备的每日使用,目的是来降低住宅的总的能源消耗.

NetBeans平台里的音乐播放器

Carlos Hoces 将介绍一个开源的管理和播放音乐的桌面程序 .

博客

技术贴士:在NetBeans 6.9.1中无缝集成终端

Adam Bien分享怎样在NetBeans IDE中打开和运行多个终端

"NetBeans平台"预览

"这本书真的写的不错,用语通俗易懂,样例精确覆盖本书的目的"

练习

NetBeans平台:没有幻灯片,只有代码

Toni Epple 来介绍NetBeans平台,不使用幻灯片.由Jaroslav Tulach 讲述Netbeans历史开始.

如何集成本地浏览器

一步一步叫你如何在你的NetBeans平台工程上增加一个SWT浏览器.

如何编写类型安全的JPA2 标准查询

Arun Gupta 讨论了如何从实体类里自动创建JPA2的元模型类,并作为JPA2标准查询的基础.

发布本期时事通讯的是: D. L. 88250


本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/03/1288746112416.html
posted @ 2010-11-03 09:02 88250 阅读(113) | 评论 (0)编辑 收藏

罪犯,在没有犯罪前,他和我们一样,是一个普通人。他也曾想,通过自己的勤劳过上好日子、过上幸福的生活,然而,残酷的社会、残酷的现实……

中国第一悍匪——白宝山(绰号:浪漫杀手自由人)
很难想象,这个中国历史上最强悍的匪徒,在“升满级”之前,竟是一个智商极低、胸无大志的损贼。内裤、床单、衣服、自行车,把偷来的这些“垃圾”变卖,养家糊口。最后一次行窃,因偷农户院内的两斤玉米未遂,被事主发现,结果被判有期徒刑11年。
在这个神奇的国家,勤劳令他致穷。身为一个有责任感的好父亲,他甚至不能让他的两个孩子吃上一顿肉。所以,他被迫去偷。那么,他为什么,从小偷小摸,发展到杀人如麻呢?
96 年刑满出狱,回到北京老家。头等大事,就是补办户口,因为,没有户口和身份证,他在北京就是黑人,什么事都做不成。本想,老老实实赚钱的他,在办理户口的 过程中,多次被派出所的民警勒索,“不拿出一千块钱,就不给你办户口,爱哪告哪告去!”白哥说,“我刚出狱,没有收入,连饭都吃不上,哪有钱给你?!” (事实证明,不拿钱打点,还真就办不成户口。白哥在死前,也没能办上户口。)
此时,白哥终于觉醒了。练成《天蚕变》,脱茧而出,重做新人!
他的情妇,劝他把枪扔了,打消邪念,好好生活。他说,“没有枪,我就没法生活!”一种王者的霸气,一种令人心碎的悲壮。
单从技术角度上看,他的计划是天衣无缝的。他的失败,是因为两个女人,一个是他的情妇,一个是他的母亲。没杀掉情妇,这充分显示出他温情的一面,而情妇出卖了他;在母亲家中,他被4个民警堵上,以他的战斗力完全可以杀出一条血路,而身为孝子,他不忍心当着母亲的面杀人。
白宝山,死了。他的故事,成为了人们茶余饭后的话题。有人说,他曾在香港出现;有人说,他潜逃美国;还有人说,他加入了义军……

战绩:
1993年服刑期间,用铁锤将狱友砸死,后将尸体掩埋。
1994年,用同样的手段,干死另一个狱友。(由于,计划周详,加之心里素质过硬,狱方没有找到他作案的证据和破绽。虽有重大作案嫌疑,但狱方最终不得不按照法律规定,将他刑满释放。)
1996年,用铁棍砸死一个武警,抢走步枪一支。
同年4月7日,在北京装甲兵司令部门前,向一哨兵连开两枪,走人。而后,遭遇6个巡警,双方枪战,干掉3个pol.ice,白哥毫发未伤,成功脱险。事隔15天,也就是4月22日,在八一射击场,枪杀一个武警。
同年,7月26日,在某师高炮团兵营门前,击毙两名解放军战士,抢走81步枪一支。
同年,12月6日,在光天化日之下、在人声鼎沸的繁华地段,枪杀一女烟草批发商、枪伤多人,抢现金6万5千元,而后回家睡觉。
1997年,白哥去新疆发展事业。在奎屯军事培训中心,作案未遂,被一战士发现,白哥被迫撤离。路遇pol.ice盘查,白哥鸣枪示警,pol.ice逃跑。然后,在戈壁滩上,步行20多个小时,途中将一路人枪杀。
同年,7月5日,进入141团场军械库。不料,该库早已废弃,仅有两只狼狗看守,于是,将狼狗击毙。
同年,7月29日(当然了,也是在大白天),枪杀一人,抢得该人的摩托车。10天后,骑该车进入147团警务区宿舍,枪杀两个正在看电视的pol.ice,缴获五四式手枪一支。
同年,8月19日,在边疆宾馆门前(又是在光天化日之下、在人声鼎沸的繁华地段),枪杀7人、伤5人,抢得现金140万,而后,返回147团场(也就是杀pol.ice那个地方)。

战斗数据分析:
智力★★★★★
体力★★★★★
耐力★★★★★(距部队门前仅30米的草丛,潜伏4个多小时纹丝不动,连训练有素的战士都没有发现;在酷热的戈壁滩上、在没有任何水源和食物的情况下,行走20多个小时……)
防御★★★★★(抗击打能力)
灵活度★★★★★(躲闪攻击的速度)
心理素质★★★★★(超级冷静、谨慎、聪明、残忍。)
徒手搏击★★★★★(不拿任何武器情况下的攻击能力。)
常规武器★★★★★(对使用刀具、斧头、锤子等武器的技巧和熟练度。)
高级武器★★★★★(对使用手枪、步枪等武器的技巧和熟练度。简单地说,就是枪法。)
单兵作战能力★★★★★(单枪匹马,多次去部队杀死军人;去pol.ice局,杀死pol.ice……)

中国第二悍匪——呼兰大侠(此案至今未破,无法确认该人的真实姓名。)

1986年3月28日夜 黑龙江省呼兰县公检法家属楼
当晚,有52人惨死家中,均是一刀致命。其中,27人为公检法的工作人员,其余25人是其家属(包括老人、妇女和儿童)。凶手,用匕首,在死者家中的墙上,留下名号——“呼兰大侠”。
在这个平静的小县城,这起案件的概念和效果,可想而知。县公共安全专家局,迅速勘察、封锁现场,并立即向上级通报。
同年,4月2日,328专案组正式成立,共计672人(其中包括,北京派来的专家组,省厅的骨干力量,以及全国各地的精英)。
经过两年多(确切的说,是两年六个月二十三天)的调查、取证、研究、分析、排查、走访,专案组没有得到任何有价值的线索,案情毫无进展(此后,该案永久封存,停止一切调查。)。
1986 年4月6日夜(也就是专案组成立的第4天),北京方面派来的痕迹鉴定专家赵某、王某,在呼兰县公共安全专家局招待所被杀。县公共安全专家局副局长郑某及其 刑警队的3个刑警,惨死家中,连带家属4人。另,两个专案组成员(职务不详),在住所被杀。案发现场,墙壁上,四个字——“呼兰大侠”。(与328案件相 同,凶手为一人作案。刀法纯熟,一刀致命。)
同年4月7日至9月15日期间,在呼兰、哈尔滨、阿城三地,先后有人遇害。其中,民警37人、刑警 12人、及其家属56人。与前次案件不同,部分死者并非死于家中,而是在下班回家的途中,被凶手从身后偷袭,一刀刺穿颈部,而后,凶手持刀在死者的背部留 下名号。经刀痕比对、鉴定,多次凶案的凶器为同一把匕首,也就是说……
一时间,整个黑龙江省的pol.ice,没人敢穿警服上班。在这段危险时期,公共安全专家干警给老百姓一种很“休闲”的感觉(都穿便装)。
呼兰县公共安全专家局某退休领导,曾扬言,“别说抓到凶手。谁能提供凶器(那把匕首)的线索,我个人,悬赏10万元!”同年9月26日,这位领导惨死家 中。凶手,用匕首,在墙上留下一行字,然后,将匕首扎进墙里,“杨局长,你太令我失望了。这把刀,还是留给你们作纪念吧!”
从此,呼兰大侠,销声匿迹,弃刀归隐。

战斗数据分析:
智力★★★★★
体力★★★★★
耐力★★★★★
防御★★★★★
灵活度★★★★★
心理素质★★★★★
徒手搏击★★★★★
常规武器★★★★★
高级武器?????(此人,未使用过枪械作案,所以,枪法情况不得而知。这是他的排名屈尊于白哥的唯一原因。)
单兵作战能力★★★★★

中国第三悍匪——田明建(绰号:枪神)

1964年9月20日 河南省淮滨县张庄(还有一种说法是息县夏庄)
那天,乌云密布,暴风骤雨。一道厉闪划破长空,“咔嚓”一个炸雷——枪神出世。

对于农村出身的、毫无关系和背景的穷苦百姓来说,要想出人头地,只有走一条路——参军。
田建明,17岁那年入伍参军,那是他第一次有机会摸枪。当枪分发到新兵的手上时,所有的新兵都很兴奋,只有田哥表现得很平静。他抚摸着那支枪,仿佛它不是 枪,而是一个人、是一个老朋友,他甚至幻想着与枪进行语言交流,“不要再叫了,不再叫了……”战友调侃他,“你听见,枪冲你叫唤了?”“它是想跟我说 话。”,田哥正颜厉色地解释道。

1981年3月19日上午9点30分 新兵实弹射击考核
田建明的成绩最差。击发10枪,9枪打空,未击中标靶,仅有一枪正中靶心。教官很疑惑,“那一枪是蒙的?太巧合了吧?”,于是,便让田哥再试一次(又打了10枪)。结果,10枪均未击中标靶。
那教官,先是狠狠地踹了田哥两脚,然后,出于好奇,不由自主地走近标靶,欣赏着罕见的标准神射。这一看,还真就看出了门道。原来,田哥的第一枪,正中靶 心。随后的19枪,从一枪击出的弹洞穿过。教官,以老年痴呆般的表情,傻傻地盯着标靶,眼都不眨的看了许久,从牙缝里挤出两个字,“天才!”

当时兵役的是四年制。也就是说,四年内得不到升迁,就自动退伍。由于,田哥的军事素质极高、个方面成绩优异(尤其是枪法),所以,受到恩师赵涛波(那个教官)的提拔、重用,被保送西安陆军学院深造。从此,一步登天,实现了从士兵到军官的质的飞跃。

1988年6月,田建明以优异的成绩,毕业于西安陆军学院。同年7月,被调往号称“地上最强”的精锐部队就职,担任北京卫戍区第三师中尉。
此时,田真人的枪法,已达到了化境。自创一招“双龙奔月”,技压群雄,天下无敌!
双龙奔月:
81式步枪,7.62mm钢芯子弹,速度750m/s;54式手枪,同是7.62mm子弹,速度420m/s。
左、右手,各拿54式手枪和81式步枪。第一枪,由54式手枪击出;第二枪,由81式步枪击出。第一颗子弹射出,随即,第二颗子弹射出,击中第一颗子弹的尾部,两弹前后串连、先后正中目标。

这样一个,技术过硬、事业蒸蒸日上,家庭幸福、婚姻美满的青年军官,为什么会叛兵为匪呢?
因为,希望。希望破没,就等于是绝望。人在绝望的时候、在对生命没有任何留恋的时候,什么事都能干得出来。
他有三个心愿:
1、希望,他媳妇能再怀孕,生个儿子。
2、把家属,从农村老家,接到部队随军,以解相思、牵挂之苦。
3、在事业有一番作为。

可以说,他的一生,都在为三个目标而奋斗。但,他的希望,在同一天,完全破没。
1994年9月19日,发生了两件事:
1、他怀孕7个月妻子,被当地计生办强制做人流手术,导致一尸两命(是个男婴)。
计生办的说法是,“执行计划生育政策。”但,田哥他媳妇,生的第一胎已经夭折,这次生的是第二胎。由于,计生办主任王兴业与田的父亲,个人之间有过节,所以……
2、田哥,为人忠厚、正直(不贪污、受贿、同流合污),所以,他与其他军官,尤其是高级军官的关系很紧张。
政委张某、参谋长王某、指导员刘某等,借职权之便作梗、给他穿小鞋。就在当天,上级领导警告他,“尽快收拾好行装,准备回家务农!”

是的!田哥,已经准备好了。这样的枪法,还用准备什么呢?
19日晚,田哥从武器库中取出家伙(81式、54式),并藏在检阅台下。
其实,事发的前一天,就已经出现征兆了。田对枪说,“不要再叫了,不要再叫了……”武器库的库管,觉得田的精神状态有些异常,便试探性的问,“枪,在叫?”田哥正颜厉色地解释道,“它是在,本能的保护主人。”

1994年9月20日(是田建明30岁的生日)
像往常一样,4个军官(其中3个是田的仇家),检阅士兵出操。由于,田已被停职,所以,他自由活动至检阅台的藏枪处,没被人怀疑。
4 军官,向田的方向贴近,距离他10多米处,正准备离去,田突然发出军令“卧倒!”士兵,习惯性地执行命令(虽然,田已停职,但,士兵还是服从命令)。当然 了,此军令对军官无效。那4个军官,一时没反应过来,傻傻呼呼地站那发愣,就在这时,4声枪响,政委张某、参谋长王某、指导员刘某、连长曲某当场毙命,均 一枪爆头。随后,田哥提枪便走,劫持了一辆吉普车,直奔tian~an-door广场。5个军官,死了4个,1个叛逃。军营,群龙无首,一片大乱,溃不成 军。
车行驶至建国门附近,司机耍滑,将车撞到树上,弃车逃命。这种小角色,田哥连看都没看,仅凭直觉,放出一枪,将司机爆头。而后,下车,向迎面来的一辆出租 车冲去,司机见状不好,一脚油门。可惜,车速没有子弹快,隔着风挡玻璃,司机被一枪爆头。田哥,又将枪口转向路上的行人……
81式步枪,单发、精确点射,在节省子弹的情况下,造成了重大伤亡(确实地说,没有伤,只有亡。)。死难者,包括伊朗大使馆政务秘书尤素福和他的儿子,以及20多个平民百姓。
由于,案发地在使馆区,政治敏感度极高,当局十分重视。pol.ice、武警,甚至特警,陆续赶到现场,与田哥枪战。虽众寡悬殊,但枪案造成交通拥堵,司 机纷纷弃车逃命,形成了一个“汽车胡同”,这恰好发挥了田哥的巷战特长。地形适合、弹药充足、活靶子乱串,这对田哥而言,可说是如鱼得水、如虎添翼。
当时,一个加拿大记者,将枪战的部分现场实况,转播回国。其中,田哥双枪齐射、单手换弹夹、凌空飞枪等绝技,让电视机前老外目瞪口呆、舌头伸出多长。至今,这等绝技,国外的特种部队仍在学习和效仿。

直至10点23分,枪战已持续近两个半小时。特勤、武警支队、区公共安全专家局防暴队,遭到重创,伤亡惨重,无法再进行作战任务;特警2支队、5支队,全军覆没……
当时,一个姓赵的队长,趴在军用吉普车的驾驶座上,带着哭腔地用对讲机向上级汇报工作,“请求支援!请求支援……”
11点56分,田建明仅剩下一颗子弹。他将枪口,对准自己的头部,点燃一支烟,吸了几口,而后,自尽身亡(至此,我军已出动6000多人)。
悍匪枪声骤停,我军不明敌情,于是,也停止射击。一时间,激烈的枪战,静了下来。双方都不开枪,又无人敢上前去看个究竟。
半小时后,我军战士,冒着”生命危险“,勘察敌情,得知悍匪已死。战士们,突然士气高涨、来了精神,飞奔上前,几十把枪对准匪徒,防止他再活过来。
据一位当事人回忆,田建明死不瞑目,瞪着眼睛,紧紧地握住那支枪,他们费了好大劲才把田和枪分开。据传说,事后,检验这支枪,按动扳机,它会发出一阵悲鸣……

战斗数据分析:
智力★★★
体力★★★★★
耐力★★★★★
防御★★★★★
灵活度★★★★★
心理素质★★★
徒手搏击★★★★★
常规武器★★★★★
高级武器★★★★★
单兵作战能力★★★★★

 

转自:http://luo.bo/2169/



本文是使用 B3log Solo简约设计の艺术 进行同步发布的
原文地址:http://b3log-88250.appspot.com/articles/2010/11/01/1288627973856.html
posted @ 2010-11-02 00:13 88250 阅读(238) | 评论 (0)编辑 收藏