分类 猪在写代码 下的文章

【译】Emiller Nginx模块开发指南(第二部分)

由于格式问题,这篇文章看起来可能会不太舒服,可以直接阅读我的google doc:

中文版       中英对照版

2. Components of an Nginx Module

2. nginx模块的各个组件

 

As I said, you have a lot of flexibility when it comes to making an Nginx module. This section will describe the parts that are almost always present. It's intended as a guide for understanding a module, and a reference for when you think you're ready to start writing a module.

正如我所说的,开发一个nginx模块的时候,具有非常非常强的灵活性。这部分就介绍一下这些东西。类似于理解模块的一个指南或者是你觉得你已经准备好开始开发模块的时候的一个参考资料。(译注:这一部分是最重要的,而且在日后的开发中,这部分可以当作字典来用)

 

2.1. Module Configuration Struct(s)

2.1. 模块配置结构

- 阅读剩余部分 -

【译】Emiller Nginx模块开发指南(第一部分)

这篇文章被认为是nginx模块开发的标准教程,因此翻译过来希望对大家有所帮助。

原文链接:http://www.evanmiller.org/nginx-modules-guide.html

这一部分介绍了nginx的一些基础知识,对已经熟悉nginx的开发者帮助不大,但如果初识nginx,建议还是好好读一下,并且最好能有所扩展。

 

由于格式问题,这篇文章看起来可能会不太舒服,可以直接阅读我的google doc:

中文版       中英对照版

Emiller's Guide To Nginx Module Development

Emiller Nginx模块开发指南

By Evan Miller    作者:Evan Miller

 

DRAFT: August 13, 2009 (changes)

Bruce Wayne: What's that?

Lucius Fox: The Tumbler? Oh... you wouldn't be interested in that.

To fully appreciate Nginx, the web server, it helps to understand Batman, the comic book character.

Batman is fast. Nginx is fast. Batman fights crime. Nginx fights wasted CPU cycles and memory leaks. Batman performs well under pressure. Nginx, for its part, excels under heavy server loads.

But Batman would be almost nothing without the Batman utility belt.

作者上来先来了一段废话说nginx巨像蝙蝠侠,都很快什么什么的,而且nginx还能把cpu和内存处理的巨牛B,并且在巨大的压力下还能很happy的工作。但是蝙蝠侠是要靠一个腰带的,没了腰带蝙蝠侠就不行了。

 

Figure 1: The Batman utility belt, gripping Christian Bale's love handles.

特点1:蝙蝠侠腰带什么的

 

At any given time, Batman's utility belt might contain a lock pick, several batarangs, bat-cuffs, a bat-tracer, bat-darts, night vision goggles, thermite grenades, smoke pellets, a flashlight, a kryptonite ring, an acetylene torch, or an Apple iPhone. When Batman needs to tranquilize, blind, deafen, stun, track, stop, smoke out, or text-message the enemy, you better believe he's reaching down for his bat-belt. The belt is so crucial to Batman's operations that if Batman had to choose between wearing pants and wearing the utility belt, he would definitely choose the belt. In fact, he *did* choose the utility belt, and that's why Batman wears rubber tights instead of pants (Fig. 1).

对蝙蝠侠腰带感兴趣的同学,请去看电影,这一段不翻译,主要原因是看不懂。。。

- 阅读剩余部分 -

我这么看一个优秀架构的形成

题记:其实一直都对软件架构这个东西有点想法,但是迟迟没有想的太明白所以未敢写些东西,怕露怯了,惹了大家的笑话。近日,读了些书,从中有所得;也跟了几个项目,也有所得,有与人聊了些这方面的东西,并加以考虑,所以试着写下此文,汇报一些个人的想法。既是想写些想法,那么少聊术,而多谈道,姑且认为是我发的一些少年狂吧。

首先,有一点原则须之出来:

没有适合你的软件模型

软件工程领域有许许多多的模型,无论是架构,还是开发流程,但作为一个工程师,我们须有这样的原则。因为模型都是前人们在若干次实践中抽象出来,并加以优化的一种实验室状态,其来源就注定这个模型不可能适应一个实际项目。因此在实践过程中,当我们遇到了与模型冲突的情况,正确的做法是修改模型,调整一个适合当下项目的流程或架构出来,然后继续走下去。倘若,试图改变自己,让自己以一种非健康的姿态去遵循模型的规定,那么这次开发想必是已经开始走上歧途了。

在软件设计初期,选择一个相对靠谱的模型是必要的,在这个模型上加以变化,调整出一个适合具体项目的设计。进入下一步的开发工作,并试图遵循这个设计,当遇到一些特殊情况与设计不符,需要考虑是当初的设计不周全,没有考虑到当下的问题;还是开发过程中出现了不和谐的情况,有人试图通过某种方式绕过一些约定,从而以一种easy但dirty的方式去满足需求。而后再决定是设计重构还是修正工作方式。

上面提到了“设计重构”,那么我说第二个原则:

及时进行设计重构

在一个软件的开发周期中,总会遇到这样那样的问题是与当初的设计是冲突的,这也就是上面提到的不和谐。我认为,这些冲突至少有半数,甚至更多是设计不周全造成的。这并不是说,我们的架构师水平不高,或是我们对需求的掌握不准,云云。事实上这种冲突是必然发生的,试想如果一个架构设计可以从头到尾的正确,那么我们这个软件是什么呢?Hello, World! 吧。一个优秀的软件,必然有着强大的功能,而强大的功能是需要相对复杂的设计(相对复杂,这并不是说复杂度与功能正相关)支持的,复杂的设计就一定有许多隐形的陷阱存在,而工业上是决不会允许我们花上足够多的时间去找到所有陷阱的,因此设计不足必然存在。换句话说,找到陷阱的最好办法,就是踩下去。因此,永远不要害怕设计重构,敢于重构,让设计重构贯穿整个开发周期。

而且设计重构,需要这个软件的架构师,这个角色来推动。架构师是这个设计的作者,因此只有他最懂得这个设计该如何发展才不至于偏离方向。一个优秀的架构师要敢于推翻自己的设计,并拿出一个更优秀的。

好的架构师只是一个优秀架构产生的条件之一,在软件开发过程中,扮演更加重要角色的是:开发工程师。因此开发工程师的习惯也至关重要。原则三:

做一个有洁癖的工程师

作为一名开发工程师,我们需知道,代码不是为了需求而生的。代码产生,满足需求是他存在的意义,但注意,代码生存在这个架构中,他是为了充实这个架构而生。我们相信,在架构中,优雅的编码一定可以满足需求,否则参考之前的原则,我们需调整架构了。那么,作为工程师试图通过之前提到过的easy and dirty的方法去满足需求,只有一种可能:偷懒。这是一种不负责任的表现,作为一个工程师,就需要对从自己手中流出的没一行代码负责,做一个有洁癖的工程师,不要让自己的代码污染了整个设计。

每一个工程师,都小心的去维护这个架构,不试图污染他,那么这个架构必然会发展的更健康。

总结上面提到的三个原则,一个优秀的架构不是设计出来的,而是成长出来的,是在勇敢的架构师和负责人的工程师的呵护下成长出来的。

以上即使在下的一些拙见,或许经验丰富的大牛们会看出不少扯淡的地方,非常非常期待牛人们的指点。

[译]Cassandra内部架构

最近想看看Cassandra的源码,于是去看他们的wiki,先把一个概述翻了,当誓师,hoho

原文链接:http://wiki.apache.org/cassandra/ArchitectureInternals

General

概述

Configuration file is parsed by DatabaseDescriptor (which also has all the default values, if any)

DatabaseDescriptor是专门解析配制文件的,配制的默认值也跟这定义。

Thrift generates an API interface in Cassandra.java; the implementation is CassandraServer, and CassandraDaemon ties it together. 

Cassandra.java调用Thrift(一个apache的跨语言框架)产生一个API接口,CassandraServer负责实现,CassandraDaemon把二者联系起来。

CassandraServer turns thrift requests into the internal equivalents, then StorageProxy does the actual work, then CassandraServer turns it back into thrift again

CassandraServer把thrift请求丢到一个内部容器里,然后StorageProxy来完成具体的工作,CassandraServer再把它拿回到thrift。

StorageService is kind of the internal counterpart to CassandraDaemon. It handles turning raw gossip into the right internal state.

StorageService是一个类似内部CassandraDaemon的玩艺儿。它就是为了让那些还没处理过的请求待在他们应该在的位置上。

AbstractReplicationStrategy controls what nodes get secondary, tertiary, etc. replicas of each key range. Primary replica is always determined by the token ring (in TokenMetadata) but you can do a lot of variation with the others. RackUnaware just puts replicas on the next N-1 nodes in the ring. RackAware puts the first non-primary replica in the next node in the ring in ANOTHER data center than the primary; then the remaining replicas in the same as the primary.

AbstractReplicationStrategy控制节点等级。每一个键的副本都有顺序。主副本是由定义在TokenMetadata里的token ring决定的,但是在其他副本上你可以有很大的发挥空间。RackUnaware只负责把副本送到环上另外N-1个节点。RackAware把把第一个非主副本放到不同于主副本的另外一个数据中心的后续节点上;剩下的副本就跟主副本在一起了。

MessagingService handles connection pooling and running internal commands on the appropriate stage (basically, a threaded executorservice). Stages are set up in StageManager; currently there are read, write, and stream stages. (Streaming is for when one node copies large sections of its sstables to another, for bootstrap or relocation on the ring.) The internal commands are defined in StorageService; look for registerVerbHandlers.

MessagingService统筹链接并在合适的阶段运行内部命令(其实就是个线程池)。各个阶段由StageManager发起;目前包括读,写和流阶段。(流,是当一个节点需要拷贝一个大段数据到另外的节点时,提供环上的引导和重定位。)内部命令在StorageService中定义,参考registerVerbHandlers。

- 阅读剩余部分 -

我看“结对编程”

在公司的一个项目的第二次迭带中,团队决定尝试使用结对编程的方式。我从未尝试过这种编程方式,但仅从想像中去衡量,其实我并不喜欢这种方式,也不认为这种方式会提高我个人的工作效率,又或者对我个人成长真的有那么大的利好,以至于我们要迫不及待的去进行。但团队中几乎全部同事同时认为这是一件大好事,因此我决定还是用一天的时间去试试,去体验一把,再做定论。

当我结束一天的结对编程后,回到家里小总结了一下,虽然跟上面提到的想像中的场景不太一样,但结论仍然是:我个人对这事不太感冒。但出于这样的考虑,可能是由于初试这种工作方式,不得要领,又是戴着些许情绪的,所以结果会比较负面,我决定再去尝试一天,而且努力去适应它,但如果一天工作结束后,结果仍然很不乐观,那么我认为这是一中不好的工作方式,至少对我来说是不好的。

------------以上是周一晚上记录在google docs上的------------

今天白天我再次让自己尝试结对,一个上午的时间...我下午决定放弃结对,中午跟Team吃饭的时候,讨论到这个话题,谈到了“因人而异”,确实这个工作法真的是因人而异。

------------以上是周二晚上的记录------------

题记:今天周五,team周会,我们谈到了“结对编程”的问题,还有之前我查了一些关于“结对编程”的资料,这里我就说说我对“结对编程”这种工作方式的看法。

首先,我们要明确,“结对编程”这仍然是一个处在试验阶段的工作方法,我去查了一些学术资料,无一例外,所有的文章对“结对编程”的介绍都是持试验态度,分别介绍其优劣。另外一些文章中,虽有对“结对编程”大肆追捧的,却也在一部分,没有一边倒的迹象。但在国内的一些文章中,这个比例的确较高。

本文,我也不讲“结对编程”的优劣势,网上到处都有,稍后文章后面附上一些资料,只聊聊这一周我的感受。

在我看来,“结对编程”作为一种工作方式的诞生,是对“编程”这个工作本质的一种转移。或者说在某些变成活动中“结对”并不合适,而在另外一些则可以。“结对编程”的优势无非在于:提高代码可读性,减少项目个人依赖,降低错误率,促进个人成长。但我们看这些特性,事实上并不属于一个绝对意义,或者说纯粹意义上的编程(hack理念的编程),而是一种代码工业化的最需要具有的性质。

但这种工业化需要的性质,通过“结对”方式也不能保证达到,因为不同的程序员有着不同的工作习惯,有些人就是喜欢单独工作,不希望别人的干扰,当“结对”时,会大大降低他的工作效率和工作质量,这就适得其反了。

说道具体的工作中,往往我们容易使用一些极端做法去做事,这明显是存在问题的。例如在项目中大规模使用“结对编程”的工作方式,而没有考虑到这种仍然处在试验中的工作方式到底是否适合我们这个团队,到底是否适合团队中的每个人。

在工作方法的选择上需要因事而异,更需要因人而异,谨慎选择。

- 阅读剩余部分 -