`
xiqiao1229
  • 浏览: 12787 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Ningx代码研究(一)

阅读更多

Updated Aug 19, 2009 byRainX1982
  NginxCodeReview  
Ningx代码研究.

 

 

概述

Nginx  ("engine x") 是一个高性能的 HTTP  反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器 
 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的Rambler.ru 站点开发的,它已经在该站点运行超过四年多了。
Igor 将源代码以类BSD许可证的形式发布。自Nginx 发布四年来,Nginx 已经因为它的稳定性、丰富的功能集
、示例配置文件和低系统资源的消耗而闻名了。目前国内各大门户网站已经部署了Nginx
如新浪、网易、腾讯等;国内几个重要的视频分享网站也部署了Nginx,如六房间、酷6等。
新近发现Nginx 技术在国内日趋火热,越来越多的网站开始部署Nginx 

- from http://wiki.nginx.org/NginxChs

我们研究nginx的源代码的动机是为了完成分段反向代理项目的开发,由于分段反向代理的需求要求对web server的并发性很强,并且是给予http协议的基础上进行的, 所以我们选择了使用Nginx的模块的形式进行开发。

我们发现目前学习nginx的例子很少,主要是emiller的模块开发介绍这篇文章, 但是单独研究这篇文章发现很多晦涩难懂的地方,而目前还没有其他更好的文章来对这些地方做解释, 有些东西必须要通过源代码的研读才可以了解的更加清楚,所以我们决定开始进行代码研究计划,以便于更好的完成开发任务

根据目前的状况,我们决定使用最新的稳定版本进行研究,故而选择 0.7.61 版作为调研对象。

http://sysoev.ru/nginx/nginx-0.7.61.tar.gz

研究计划

下面是王晓哲帮助制定的调研计划

  • 学习emiller的文章
  • 熟悉nginx的基本数据结构 1w
  • 了解nginx的core module 的结构和运行机制, 同时参考 event 和 os module 的实现 1w
  • 了解nginx的http core module 的结构和运行机制 1w
  • 学习handler 类型module的编写 2d
  • 学习filter 类型module的编写 2d
  • upstream类型module的编写 1w

参与人员

徐景(rainx), 王晓哲(chaoslawful)

研究文档

学习emiller的文章

http://www.evanmiller.org/nginx-modules-guide.html

熟悉nginx的基本数据结构

nginx 代码的目录结构

解开nginx的代码后,在src目录下发现有如下的几个目录

core  event  http  mail  misc  os

其中 :

  • core : 该目录存放core module的代码,也是nginx服务的入口
  • http : http core module 的代码,nginx作为web/http proxy server运行时的核心模块
  • mail : mail core module 的代码,nginx作为pop3/imap/smtp proxy server运行时的核心模块 ( 不在我们本次研究范围内 )
  • event : nginx 自身对事件处理逻辑的封装
  • os : nginx对各个平台抽象逻辑的封装
  • misc : nginx 的一些utils,定义了test和profiler的一些外围模块的逻辑

为了方便了解整个结构, 我们在src目录下建立了一个子目录,叫做demo,然后根据每个章节内容的不同,分别在demo下建立子目录,存放一些学习时使用的代码,如我们目前的章节是学习基本的数据类型,所以建立basic_types子目录

rainx@rainx-laptop:~/land/nginx-0.7.61/src$ mkdir -p demo/basic_types/

nginx简单的数据类型的表示

在 core/ngx_config.h 目录里面定义了基本的数据类型的映射,大部分都映射到c语言自身的数据类型

typedef intptr_t        ngx_int_t;
typedef uintptr_t       ngx_uint_t;
typedef intptr_t        ngx_flag_t;

其中 ngx_int_t, nginx_flag_t, 都映射为 intptr_t; ngx_uint_t映射为 uintptr_t

这两个类型在/usr/include/stdint.h的定义为:

/* Types for `void *' pointers.  */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int                intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned long int       uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int                     intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned int            uintptr_t;
#endif

所以基本的操作和整形/指针类型的操作类似

建立文件

#include <stdio.h>
#include "../../core/ngx_config.h"

int main()
{
    ngx_uint_t a;
    ngx_int_t b;
    a = 1000;
    b = -1000;
    printf ("%d + %d = %d\n", a, b, a+b);
    return 0;
}

编译测试

gcc -I ../../../objs/ -I ../../os/unix/ basic_types_int.c -o basic_types_int
./basic_types_int
1000 + -1000 = 0

nginx字符串的数据类型的表示

nginx对c语言的字符串类型进行了简单的封装, core/ngx_string.h/c 里面包含这些封装的内容

其中定义了 ngx_str_t ,ngx_keyval_t, ngx_variable_value_t

这几个基础类型的定义如下

typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;


typedef struct {
    ngx_str_t   key;
    ngx_str_t   value;
} ngx_keyval_t;


typedef struct {
    unsigned    len:28;

    unsigned    valid:1;
    unsigned    no_cacheable:1;
    unsigned    not_found:1;
    unsigned    escape:1;

    u_char     *data;
} ngx_variable_value_t;

可以看出 ngx_str_t 在原有的uchar* 的基础上加入的字符串长度的附加信息, 初始化使用ngx_string宏进行,他的定义为:

#define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }

测试字符串的代码 demo/basic_types/basic_types_str.c

#include <stdio.h>
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "nginx.h"
#include "ngx_core.h"
#include "ngx_string.h"
#include "ngx_string.h"

volatile ngx_cycle_t  *ngx_cycle;

void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
            const char *fmt, ...)
{
}

int main()
{
    u_char* p = NULL;
    ngx_uint_t size;
    ngx_str_t dst;
    ngx_str_t mystr = ngx_string("hello, world !");
    ngx_keyval_t pair = {ngx_string("url"), ngx_string("http://rainx.cn/index.php?test=1")};
    int dst_len  =ngx_base64_encoded_length(mystr.len);
    printf("source length is %d, destination length is %d\n", mystr.len, dst_len );
    p = malloc( ngx_base64_encoded_length(mystr.len) + 1);
    dst.data = p;
    ngx_encode_base64(&dst, &mystr);
    printf("source str is %s\ndestination str is %s\n", mystr.data, dst.data);
    free(p);
    size = pair.value.len + 2 * ngx_escape_uri(NULL, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    p = malloc (size * sizeof(u_char));
    ngx_escape_uri(p, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    printf("escaped %s is : %s (%d)\noriginal url size is %d\n", pair.key.data, p, size, pair.value.len);
    free(p);
    return 0;

}

编译运行

gcc  -c -O -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Wunused-function -Wunused-variable -Wunused-value -Werror -g -I ../../../objs/ -I ../../os/unix/ basic_types_str.c -I../../core/ -I../../event/ -I../../os/ -o basic_types_str.o
gcc -o basic_types_str basic_types_str.o ../../../objs/src/core/ngx_{string,palloc}.o ../../../objs/src/os/unix/ngx_alloc.o -lcrypt -lpcre -lcrypto -lz
rainx@rainx-laptop:~/land/nginx-0.7.61/src/demo/basic_types$ ./basic_types_str 
source length is 14, destination length is 20
source str is hello, world !
destination str is aGVsbG8sIHdvcmxkICE=
escaped url is : http://rainx.cn/index.php%3ftest=1 (34)
original url size is 32

core/ngx_string.h/c 中同时也封装了一批字符/字符串处理的函数和宏,他们的使用大多数情况下和c标准库中的类似,只是在内存分配相关的函数中有一定的区别。

比如 u_char *ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src); 除了源字符串驻外,还要传入ngx_pool_t的指针作为参数,使用nginx自己的内存分配方式进行内存的分配。

除了标准的字符串操作外, nginx还实现了例如:

// base64 编码/解码函数和宏

#define ngx_base64_encoded_length(len)  (((len + 2) / 3) * 4)
#define ngx_base64_decoded_length(len)  (((len + 3) / 4) * 3)

void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);

//utf-8 编码/解码相关函数

uint32_t ngx_utf8_decode(u_char **p, size_t n);
size_t ngx_utf8_length(u_char *p, size_t n);
u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);

// urlencode和html实体的编码解码
uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
    ngx_uint_t type);
void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size);

等对于http服务有帮助的宏和函数

 

[LINK]http://code.google.com/p/nginxsrp/wiki/NginxCodeReview

分享到:
评论

相关推荐

    Nginx 代码研究

    我们发现目前学习nginx的例子很少,主要是emiller的模块开发介绍这篇文章, 但是单独研究这篇文章发现很多晦涩难懂的地方,而目前还没有其他更好的文章来对这些地方做解释, 有些东西必须要通过源代码的研读才可以...

    NGINX 0.1版代码

    这是NGINX的0.1版源代码,模块结构相对简单,适用于有志研究NGINX代码的童鞋进行学习。

    nginx 各个历史版本

    nginx各个阶段的历史版本源码,从0.1版本开始,可以用于研究nginx的代码框架

    nginx 源码 解析 资料大全

    收集的 nginx 源码 解析 ,非常全 architecture.png Emiller的Nginx模块开发指南.docx Nginx(en).pdf nginx@taobao.pdf nginx_internals.pdf nginx核心讲解(0.2).doc nginx核心讲解(0.4).doc ...Ningx代码研究.docx

    nginx核心讲解

    慕名对nginx的源码进行学习研究是早在2009年的事情,当时还在学校,整天呆在实验室里看动漫,时间一久就心感愧疚,觉得还是要趁有空学点东西,恰当时不知从哪里得知高性能服务器是一个很有“前途”的方向,几经搜索...

    Nginx经典模块

    为什么发现了这个插件,因为这几天公司需要在所有shtml文件后面追加一个js代码用来做统计(之前统计 代码没加齐全),在寻求解决方法的过程中找到了它认识了它最后喜欢上了它,你可能以为我用这个插件去实现了我要的...

    Nginx源码研究之nginx限流模块详解

    主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    nginx源码vs2008版

    nginx最近是越来越火,许多大型商业网站都用它作服务器,作为开发人员很有必要拿来研究一下。从网上下来的都是make版,代码看起来不是那么方便,特别是对我这种习惯vs的程序员,幸好有朋友整理了一下,在vs2008下,...

    Nginx配置实现下载文件的示例代码

    所以今天就想研究下nginx实现文件的上传下载,直接开搞,本地服务启起。这里记录下配置及踩坑记录。 一、配置 http { ... server: { # 配置下载 location /download { root D:\\download; autoindex on; ...

    详解Nginx服务器的nginx-http-footer-filter模块配置

    为什么发现了这个插件,因为这几天公司需要在所有shtml文件后面追加一个js代码用来做统计(之前统计代码没加齐全),在寻求解决方法的过程中找到了它认识了它最后喜欢上了它,你可能以为我用这个插件去实现了我要的...

    Linux上搭建nginx,及简单配置

    在上家公司都是运维安装nginx,到新公司后代码开发完成部署测试服务器要求自己装nginx,研究了好久安装好之后,到正式上线还要自己安装,索性把安装步骤自己记载下来(好大一部分都是在网站找的)。  一,安装  ...

    解析CI即CodeIgniter框架在Nginx下的重写规则

    最近研究CI框架,发现这个框架的路由功能在Nginx下有问题,报404错误,后来在网上查资料,发现需要开启PATH_INFO。在nginx7.16以后貌似就支持PATH_INFO了,只需要在配置文件中开启即可。打开nginx.conf文件,在你的...

    Answer-Prediction:代码研究员小组项目

    一个代码研究员小组项目,由四个学生在一周内完成。 Sherlock Engine是一个基于Python的应用程序,它使用多元线性回归来预测用户对下一个问题的答案。 每次用户提交答案时,对于该用户以及所有其他用户,所有后续...

    nginx try_files指令判断文件是否存在实例

    现在有这样一个需求,网站根目录下有静态文件,static目录下也有静态文件,static目录下的静态文件是程序批量生成的,我想让nginx在地址不变的前提下优先使用static目录里面的文件,如果不存在再使用根目录下的静态...

    交易所源码分享,原生安卓+ios,有安装教程!

    项目所需软件 (推荐使用宝塔安装) Nginx、php、mysql、redis、supervisor 进行部署项目 以下安装步骤仅以宝塔环境...仅限用于学习和研究目的,不得将上述内容资源用于商业或者非法用途,否则,一切后果请用户自负。

    PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径

    我在服务器上有每天切割nginx日志的习惯,所以针对每天各大搜索引擎来访,总能记录一些404页面信息,传统上我只是偶尔分析下日志,但是对于很多日志信息的朋友,人工来筛选可能不是一件容易的事情,这不我个人自己...

    外贸网站屏蔽中国IP访问的多种方法

    大家都知道的原因,做外贸站,国人喜欢研究你的站,还总是帮你进行压力测试…… 首先想到要屏蔽中国IP就会是把中国IP库加入Nginx配置文件中,然后WEB服务器对比IP来达到屏蔽。 代码如下: 在Nginx中加deny IP; 批量...

    毕业设计-浅谈nginxlua在安全中的应用.zip

    这里为你收集整理了关于毕业设计、课程设计可参考借鉴的资料一份,质量非常高,如果你投入时间去研究几天相信肯定对你有很大的帮助。到时候你会回来感谢我的。 本资源是经过本地编译测试、可打开、可运行的项目、...

    openresty_dev:OpenResty开发指南代码

    openresty_dev 这是OpenResty编程的示例代码。...注释nginx,学习研究原始码 选定的收藏夹nginx模块和资源。 带有google_perftools的nginx更好的工具 -Boost库指南的示例代码。 专业促进发展。

Global site tag (gtag.js) - Google Analytics