mini_ngx_实现一-简述

Catalogue
  1. 1. 简介
    1. 1.1. 相关配置
    2. 1.2. 功能简介
  2. 2. 组织代码结构
  3. 3. 编译启动

简介

github: https://github.com/brewlin/just-for-fun/mini_nginx

mini_ngx 主要是抽取出nginx主体框架实现一个mini版demo,拆分nginxcycle http event等主要模块

主要抽取的相关知识点有,连接池,内存池,模块封装,epoll模块,非阻塞socket,端口复用,log.nginx为了保证高性能挂平台会有大量的兼容性代码和细节优化代码,当前demo为了保证主流程的连贯,去掉相关优化和兼容,例如时间模块指定epoll实现,http只进行本地文件读取后响应客户端

相关配置

  1. cycle->is_daemon = 0|1; 模拟nginx是否开启守护进程
  2. cycle-modules_n = 2;cycle->modules = modules; 模拟nginx的模块架构,因为nginx所有的功能都封装为模块化,在编译期间就将所有的模块添加到一个数组中,并且在启动期间赋值给cycle->modules,因为我们只实现了两个模块http,event所以默认为2个模块
  3. 日志配置,nginx日志很强大,目前我们只实现对应的日志记录功能即可,需要手动配置

    1
    2
    3
    4
    5
    6
    //src/core/cycle.c:92

    // 打开日志文件
    cycle->log = palloc(cycle->pool,sizeof(log_t));
    cycle->log->use_logfile = 1;
    log_open(cycle->log, "./run.log")
  4. 监听端口配置,因为nginx主要完全基于nginx.conf配置,所以每个模块都是根据配置中的参数做对应的初始化操作,例如listen配置会使用http模块来添加对应socket套接字和监听,我们的demo中就没有实现配置解析,所以模拟在个个模块中配置对应的监听端口

    1
    2
    3
    4
    5
    6
    7
    //src/http/http.c:28

    //这里本来是http模块的初始化,每发现一个lisetn配置就会调用如下方法进行添加到cycle->istening链表上
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    //我们这里模仿nginx 就写死在模块初始化方法里默认监听8090端口
    serv_addr.sin_port = htons(8089)
  5. 连接池大小配置, nginx连接池大小是由event{ worker_connection 1000;}配置来决定的,同样我们在event模块初始化的时候是写在初始化方法里,模仿由配置文件中读取的连接池大小

    1
    2
    3
    4
    5
    6
    7
    8
    //src/event/event.c:74

    //初始化100个连接池
    cycle->connection_n = 100;

    //初始化epoll事件的大小内存申请
    //init epoll_create epoll_events
    event_actions.init(cycle,cycle->connection_n/2);

功能简介

image

  1. 监听8089 tcp协议
  2. 将8090 加入epoll监听可读事件
  3. http请求到来,触发epoll_wait就绪事件 分发8090socket accept接受新连接
  4. 为该连接分配内存池,并加入epoll读事件,等待客户端发送body数据
  5. http请求发送body请求,触发epoll_wait就绪事件,分发该tcp连接连接ev->handler
  6. 解析http协议,读取对应html文件内容,响应客户端
  7. 回收内存池,删除epoll事件,关闭客户端fd,回收该连接

组织代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mini_nginx
----------core 核心模块
--------------cycle.c 启动函数
--------------array.c 链表库
--------------connection.c 连接池
--------------mem_pool.c 内存池
--------------log.c 日志记录
--------------CMakeLists.txt 编译配置

----------event 事件模块
---------------event.c 核心函数
---------------epoll_module.c 主要实现
---------------event_accept.c accept
---------------CMakeLists.txt 编译配置

----------http http模块
--------------http.c 主要函数
--------------http_connection.c
--------------http_header.c
--------------request.c
--------------response.c
--------------stringutils.c
--------------CMakeLists.txt 编译配置

----------include 头文件库

----------main.c main函数
----------CMakeLists.txt 链接配置

编译启动

1
2
3
4
5
> cd /just-for-fun/mini_nginx
> cp -r www /tmp/www
> mkdir bin;cd bin
> cmake ../
> make

image

启动服务

1
> ./demo

1
2
> curl http://127.0.0.1:8089/index.html
> tailf ./run.log

image