nginx源码学习0

因为前段时间想写个http proxy。自己实验了一下,原理很简单,浏览器把http头发送到指定的代理服务器端口,其中第一行GET/POST 后面跟的是完整的url地址。

自己用python2和nodejs都实现了一遍,代码都不超过50行。但有一些问题我实在解决不了,例如http1.1的流水线处理,http1.1的长连接的具体原理。还有目前我的proxy构架都是单服务器端的,也就是希望client端直接连接我的服务。以前看到GAP的构架是一个本地服务端和一个远程服务端感觉还很奇怪,现在我知道如果不能直接通过端口连接服务的话,用http把请求传到远程服务上是唯一能实现的代理方法。然而这个方法我总归不太喜欢,我对网络编程的理解只处于最初级的阶段,想起来nginx来,就把源码下下来看。

nginx的源码还是很清晰的,虽然作者貌似极度不喜欢写注释,但基本不考虑windows也让nginx的代码少了很多令人讨厌的条件编译。配上ctags和vim,至少我在代码导航上没有任何困难。

 

由于是第一次看这种大项目的源码,经验还是又从头积累。例如很多项目都是实现了自己的内存池,基础数据结构之类的,那么先看这些部分就是比较好的选择,从较高的高度来理解一个函数的作用,也就是所谓抽象也是阅读代码中必须的。

 

内存对其:
nginx中很多数据结构都是要求强制对其的,好处是cpu可以以最少的次数从内存中取出数据,坏处是浪费少许内存。time & space tradeoff,如何权衡看具体的应用了,像web服务器这类的高负载高响应程序当然选择时间了。

#define ngx_align(d, a) (((d + (a-1)) & ~(a-1))

方法很巧妙,可能这也是c代码中的惯例方法,但对于我是第一次接触,所以看到这段代码还懵了一段时间。

两个参数d和a,d代表数据,a代表对其单位。假设a是8,那么用二进制表示就是1000,a-1就是0111. d + a-1之后在第四位可能进位一次(如果d的前三位不为000,则会进位。反之,则不会),~(a-1)是1111...1000,&之后的结过就自然在4位上对其了。注意二进制中第四位的单位是8,也就是以8为单位对其。

可以用python验证一下

>>> a = 17

>>> d = 8

>>> (a + d-1) & ~(d-1)

>>> 24

>>> bin(_)

>>> '0b11000'

>>> bin(d-1)

>>> '0b0111'