【Nginx】nginx应用入门

http服务器产品

  • lis
  • lighttpd
  • apache
  • tomcat
  • nginx

nginx的优点

  1. 开源
  2. 轻量级
  3. 高性能
  4. 易扩展
  5. 稳定
  6. 模块化
  7. 热更新

nginx下载与编译

环境:CentOS7

1 下载

下载nginx源码:

wget https://github.com/nginx/nginx

nginx编译需要pcre,下载pcre:

wget https://github.com/PhilipHazel/pcre2

nginx编译需要zlib,下载zlib:

wget https://github.com/madler/zlib
2 解压

解压pcre:

tar -zxvf pcre-8.41

解压zlib:

tar -zxvf zlib-1.2.11

解压nginx:

tar -zxvf nginx-1.14.0.tar.gz -C /usr/local/src/
3 编译

编译pcre:

./configure && make && make install

编译zlib:

./configure && make && make install

编译nginx:

./configure && make && make install

nginx启动与停止

启动nginx:

cd /usr/local/nignx #进入nginx目录
./sbin/nginx -c conf/nginx.conf #以conf/nginx.conf文件作为配置文件,启动./sbin/nginx程序

关闭nginx:

cd /usr/local/nginx
./sbin/nginx -s stop

重新载入配置文件:

cd /usr/local/nginx
./sbin/nginx -s reload            

nginx启动流程

启动./sbin/nginx流程是,先启动master进程,读取配置,根据配置信息启动slave进程。

nginx主要应用场景

【1】反向代理

反向代理应该是 Nginx 做的最多的一件事了,什么是反向代理呢,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。
下面贴上一段简单的实现反向代理的代码:

server { 
 	listen 80; 
 	server_name localhost; 
 	client_max_body_size 1024M;
 	location / {
 		proxy_pass http://localhost:8080;
 		proxy_set_header Host $host:$server_port;
 	}
 }

保存配置文件后启动 Nginx,这样当我们访问 localhost 的时候,就相当于访问localhost:8080了。

【2】负载均衡

1、RR 轮转(默认)
2、权重
3、ip_hash
4、fair(第三方)
5、url_hash(第三方)

【3】http服务器

Nginx 本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用 Nginx 来做服务器,同时现在也很流行动静分离,就可以通过 Nginx 来实现,首先看看 Nginx 做静态资源服务器

server {
	listen 80; 
	server_name localhost; 
 	client_max_body_size 1024M;
 	location / {
 		root /usr/local/nginx/html/www;
 		index index.html;
 	}
 }

这样如果访问 http://localhost 就会默认访问到 html/www 目录下面的 index.html,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。

【4】动静分离

动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。

upstream test{ 
	 server localhost:8080; 
	 server localhost:8081; 
 }
 
server { 
	listen 80; 
 	server_name localhost; 
 	location / { 
 		root root /usr/local/nginx/html/www; 
 		index index.html; 
	 } 
 	# 所有静态请求都由 nginx 处理,存放目录为 html
 	location ~ .(gif|jpg|jpeg|png|bmp|swf|css|js)$ { 
		root /var/www; 
	}
	# 所有动态请求都转发给 tomcat 处理 
 	location ~ .(jsp|do)$ { 
		proxy_pass http://test; 
 	} 
 	error_page 500 502 503 504 /50x.html; 
 	location = /50x.html { 
 		root /var/www; 
 	} 
 }
 

这样我们就可以吧 HTML 以及图片和 css 以及 js 放到 html/www 目录下,而 tomcat 只负责处理 jsp 和请求,例如当我们后缀为 gif 的时候,Nginx 默认会从 html/www 获取到当前请求的动态图文件返回,当然这里的静态文件跟 Nginx 是同一台服务器,我们也可以在另外一台服务器,然后通过反向代理和负载均衡配置过去就好了,只要搞清楚了最基本的流程,很多配置就很简单了,另外 localtion 后面其实是一个正则表达式,所以非常灵活

【5】正向代理

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

 resolver 114.114.114.114 8.8.8.8;
 server {
 	resolver_timeout 5s;
 	listen 81;
 	access_log /var/www/access.log;
 	error_log /var/www/error.log;
 	location / {
 		proxy_pass http://$host$request_uri;
 	}
 }

resolver 是配置正向代理的 DNS 服务器,listen 是正向代理的端口,配置好了就可以在 ie上
面或者其他代理插件上面使用服务器 ip+端口号进行代理了。

正向代理和反向代理的区别

正向代理:代课客户端。用途:比如VPN,访问外网时,nginx把客户端的ip修改成了自己的ip去访问外网。

反向代理:代理服务器。用途:比如公网IP费用和带宽很贵,可以考虑只够买一个公网IP,这个公网IP上的路由器(网关)做一个端口映射,映射到局域网的装有nginx的一个机器(代理服务器,也叫做网关服务器), 利用代理服务器(网关服务器)代器局域网内其他服务器机器,实现了一个机器代理后面多个服务器的反向代理。

在这里插入图片描述

代理和重定向的区别

代理:客户端浏览器与代理服务器建立连接,代理服务器与被代理的服务器连接,获取到信息后,由代理服务器发给客户端浏览器。因此客户端浏览器地址上显示的仅仅是代理服务器的ip地址。

重定向:客户端浏览器与代理服务器建立连接后,代理服务器发出重定向的网址给客户端,客户端根据网址跟重定向的服务器建立连接。因此重定向后客户端浏览器地址上显示的是web服务器的ip地址而不是代理服务器的ip地址。

在这里插入图片描述
返回特定状态码:

一些网站 URI 需要立即返回具有特定错误或重定向代码的响应,例如当页面被暂时移动或永久移动时。 最简单的方法是使用 return 指令。 例如返回未找到的 404 状态码:

location /wrong/url {
	return 404;
}

返回重定向URL:
返回的第一个参数是响应代码。可选的第二个参数可以是重定向的 URL(代码 301,302,303 和 307)或在响应体中返回文本。 例如:

location /permanently/moved/url {
	return 301 http://www.example.com/moved/here;
}

返回指令可以包含在 location 和 server 上下文中。

nginx配置解析

基础配置解析与nginx监听端口行为

配置:

worker_processes 4;

events {
	worker_connections 1024;
}

# smtp协议
smtp {
}

# http协议
http {
	
	# http协议可以有多个server
	server {
		listen 8888;
	}

	server {
		listen 8889;
	}

	server {
		listen 8890;
	}
	
	server {
		listen 8891;
	}
	
}

行为:

# netstat -nap | grep 8888
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      2081/nginx: master 
# netstat -nap | grep 8889
tcp        0      0 0.0.0.0:8889            0.0.0.0:*               LISTEN      2081/nginx: master 
# netstat -nap | grep 8890
tcp        0      0 0.0.0.0:8890            0.0.0.0:*               LISTEN      2081/nginx: master 
# netstat -nap | grep 8888
tcp        0      0 0.0.0.0:8891            0.0.0.0:*               LISTEN      2081/nginx: master 

可以如上看到监听8888、8889、8890、8891这四个端口的都是nginx:master进程监听。

原理解析:
1、listen操作是在master进程。一个进程如何监听多个端口?进程申请的epoll管理所有端口,这就是IO多路复用的解决方案。
2、listen操作完后,master进程进行fork出子进程。因此所有子进程也都持有父进程中listen后返回的同一个fd。
3、当有fd新来请求,master不去具体响应请求,而是由worker进程去响应accept、read、send等操作。
4、因为所有子进程都持有和父进程同一个fd,当一个fd新来请求,那么所有子进程会去抢夺响应这个请求,此时发生“惊群”现象。解决“惊群”现象:在共享内存中实现一把全局锁,所有子进程去共享内存中抢夺锁的拥有权,拥有锁的子进程可以获得处理fd请求的权力。

访问静态资源配置示例

配置:

worker_processes 4;	#开启进程数

events {
        worker_connections 1024;	#每个进程允许并发连接数
}

http {
 		#开启服务
        server {
                listen 8888;

		·		#一个http请求对应一个location,get资源的路径
                location / {
                        root /usr/local/nginx/html;
                }
                #root是根路径,访问完整路径是root+location后面带的路径。比如这里访问的完整路径就是/usr/local/nginx/images;
                location /images/ {
                        root /usr/local/nginx/;
                }
                # ~ \. 是正则表达式中表示任意前缀的意思
                location ~ \.(mp3|mp4) {
                        root /usr/local/nginx;
                }
        }
}

验证:

# 启动nginx
cd /usr/local/nginx
./sbin/nginx -s conf/mynginx.conf

# 查看nginx根目录资源分布
# tree
.
├── client_body_temp
├── conf
│   ├── fastcgi.conf
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── myconf.conf
│   ├── mynginx.conf
│   ├── nginx.conf
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp
├── html
│   ├── 50x.html
│   └── index.html
├── images
│   └── a.jpg
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── media
│   └── a.mp4
├── proxy_temp
├── sbin
│   ├── nginx
│   └── nginx.old
├── scgi_temp
├── test
│   └── chapter2
│       └── my.html
└── uwsgi_temp


# 访问图片
浏览器地址访问 http://192.168.184.131:8888/images/a.jpg

# 访问音频
浏览器地址访问 http://192.168.184.131:8888/media/a.mp4

# 访问my.html
浏览器地址访问 http://192.168.184.131:8888/test/chapter2/my.html
反向代理、负载均衡配置示例

配置:

worker_processes 4;	#开启进程数

events {
        worker_connections 1024;	#每个进程允许并发连接数
}

http {
        
        #nginx反向代理的服务器地址
    	#这里的负载均衡实现是RR(轮询),是默认的nginx负载均衡方案
        #upstream backend {
        #        server 192.168.184.132;
        #        server 192.168.184.133;
        #}

		#nginx反向代理的服务器地址
        #这里的负载均衡实现是ip_hash,每个请求按ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session问题
		#upstream backend {
		#		ip_hash;
        #       server 192.168.184.132;
        #       server 192.168.184.133;
        #}

		#nginx反向代理的服务器地址
        #这里的负载均衡实现是fair,接后端服务器的响应时间来分配请求,响应时间短的优先分配。
		#upstream backend {
		#	    fair;
        #       server 192.168.184.132;
        #       server 192.168.184.133;
        #}

		#nginx反向代理的服务器地址
        #这里的负载均衡实现是url_hash,按访问的url的hash结果来分配请求,使每个url定向到一个后端服务器,后端服务器为缓存时比较有效,在upstream中加入hash语句,server语句中不能写入weight等其他参数,hash_method是使用的hash算法。
		#upstream backend {
		#	    hash $require_url;
		#	    hash_method crc32;
        #       server 192.168.184.132;
        #       server 192.168.184.133;
        #}

        #nginx反向代理的服务器地址
        #这里的负载均衡实现是权重,给不同server配了一个weight,转发时根据weight转发到不同的server
		upstream backend {
                server 192.168.184.132 weight=2;
                server 192.168.184.133 weight=1;
        }
        
		#开启服务
        server {
                listen 8888;
        }
        #开启服务
        server {
                listen 8889;
        }
        #开启服务
        server {
                listen 8890;
                
                #localtion ~ \.cgi {
                #       fastcgi_pass 192.168.184.131:9000;
                #       fastcgi_index index.cgi;
                #       fastcgi_param SCRIPI_FILENAME cgi$fastcgi_script_name;
                #       include ../conf/fastcgi_params;
                #}
        }
        #开启服务
        server {
        		#监听的端口
                listen 8891;
				#匹配客户端请求
                location / {
                		#资源所在的文件路径
                        root /usr/local/nginx/html;
                        #反向代理地址
                        #proxy_pass http://192.168.184.132;
                        #反向代理地址,根据策略转发到某个服务器地址
                        proxy_pass http://backend;
                }
                #匹配客户端请求
                location /images/ {
                        root /usr/local/nginx/;
                }
                #匹配客户端请求
                location ~ \.(mp3|mp4) {
                        root /usr/local/nginx;
                }
        }
}

验证

# 分别启动192.168.184.131、192.168.184.132、192.168.184.133的机器上的nginx
cd /usr/local/nginx
./sbin/nginx -s conf/mynginx.conf

# 浏览器访问
http://192.168.184.131:8891 ##此时发生反向代理,根据权重访问到了132或者133的机器上的首页资源

nginx数据结构

请添加图片描述

nginx基础数据结构
ngx_int_t
//ngx_config.h
typedef intptr_t        ngx_int_t;	//为了兼容不同平台int的sizeof

在不同平台(如x86和x64),int所占用的字节数是不同的,在不同平台下使用强转如下就会出现问题(long变量出现无意义空字节情况)。ngx_int_t 的定义为了兼容不同平台int的sizeof。

int idx = sum;
long a = (long)idx;
ngx_str_t
//ngx_string.h
typedef struct {
    size_t      len;	//数据长度
    u_char     *data;	//数据内容指针
} ngx_str_t;

对比字符存储形式是柔性数组和字符存储形式是nginx使用的数组指针的好处坏处:

字符存储形式是柔性数组:
typedef struct {
    size_t      len;	
    u_char     data[0];	
} str_t;

字符存储形式是数组指针:
typedef struct {
    size_t      len;	
    u_char     *data;	
} str_t;
  • 字符存储形式是柔性数组的结构体在申请内存的时候,data的内容是跟在len之后的,一旦整个内存申请好后,data里面的内容长度就确定了,再更改比较困难。
  • 字符存储形式是数组指针的结构体在申请内存的时候,data的内容可以在任意地方申请(如其他的堆),用一个指针记录真正内容的地方,所以修改data内容比较容易。
ngx_list_t
//ngx_list.h
typedef struct ngx_list_part_s  ngx_list_part_t;

struct ngx_list_part_s {
    void             *elts;	//真正存放ngx_str_t数据的地方
    ngx_uint_t        nelts;	//ngx_str_t长度
    ngx_list_part_t  *next;	//下一个ngx_list_part_s 
};

typedef struct {
    ngx_list_part_t  *last;	//ngx_list_part_s结尾结点
    ngx_list_part_t   part;	//ngx_list_part_s开头结点
    size_t            size;	//每个数据的大小
    ngx_uint_t        nalloc;	//分配数据个数
    ngx_pool_t       *pool;	//指向当前list被分配内存所在的内存池
} ngx_list_t;

ngx_list_t
问:一般一个数据结构至少拥有增、删、改、查四个函数,为什么ngx_list_t 结构体数据结构只提供操作函数(void *ngx_list_push(ngx_list_t *list))?

答:

  1. ngx_list_t使用了内存池结构,而nginx的内存池使用场景是一个用户连接(socket)建立对应的一个内存池,当用户断开连接后,整个内存池一起释放,因此不需要单独的释放内存池内部的某个结构(如这里的ngx_list_t整个使用的内存)。因此不需要删除函数操作。
  2. ngx_list_t 的某个应用场景是客户端多条数据上传到nginx,nginx做一个缓存,然后隔一段时间把内容保存到数据库,因此不需要查函数和改函数。

使用示例:

//gcc -o ngx_list_main ngx_list_main.c -I ../nginx-1.13.7/src/core/ -I ../nginx-1.13.7/objs/  -I ../nginx-1.13.7/src/os/unix/ -I ../pcre-8.41/ -I ../nginx-1.13.7/src/event/ ../nginx-1.13.7/objs/src/core/ngx_list.o ../nginx-1.13.7/objs/src/core/ngx_string.o ../nginx-1.13.7/objs/src/core/ngx_palloc.o ../nginx-1.13.7/objs/src/os/unix/ngx_alloc.o

#include <stdio.h>
#include <string.h>

#include "ngx_config.h"

#include "ngx_core.h"

#include "ngx_list.h"
#include "ngx_palloc.h"
#include "ngx_string.h"

#define N	10

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, ...)
{


}


void print_list(ngx_list_t *l) {
	ngx_list_part_t *p = &(l->part);
	
	while (p) {

		int i = 0;
		for (i = 0;i < p->nelts;i ++) {
			printf("%s\n", (char*)(((ngx_str_t*)p->elts + i)->data));
		}
		p = p->next;
		printf(" -------------------------- \n");
	}

}

int main() {

	ngx_pool_t *pool = ngx_create_pool(1024, NULL);

	ngx_list_t *l = ngx_list_create(pool, N, sizeof(ngx_str_t));

	int i = 0;
	for (i = 0;i < 24;i ++) {

		ngx_str_t *ptr = ngx_list_push(l);
		
		char *buf = ngx_palloc(pool, 32);
		sprintf(buf, "King %d", i+1);

		ptr->len = strlen(buf);
		ptr->data = buf;
	}

	print_list(l);
}
ngx_table_elt_t
//ngx_hash.h
typedef struct {
    ngx_uint_t        hash;	//hash值,方便找到key所在位置
    ngx_str_t         key;	//key
    ngx_str_t         value;	//value
    u_char           *lowcase_key;	//小写key
} ngx_table_elt_t;
ngx_buf_t
//ngx_buf.h
typedef struct ngx_buf_s  ngx_buf_t;
struct ngx_buf_s {
    u_char          *pos;	//当前读取位置
    u_char          *last;	//当前读取结尾位置
    off_t            file_pos;	//文件位置
    off_t            file_last;	//文件结尾位置

    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;	//文件指针
    ngx_buf_t       *shadow;


    /* the buf's content could be changed */
    unsigned         temporary:1;

    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    unsigned         recycled:1;
    unsigned         in_file:1;
    unsigned         flush:1;
    unsigned         sync:1;
    unsigned         last_buf:1;
    unsigned         last_in_chain:1;

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    /* STUB */ int   num;
};
ngx_chain_t
//ngx_code.h
typedef struct ngx_chain_s           ngx_chain_t;
//ngx_buf.h
struct ngx_chain_s {
    ngx_buf_t    *buf;	//持有ngx_buf_t    
    ngx_chain_t  *next;	//指向下一个
};
  • nginx中用ngx_buf_t管理内存中的一个文件,用于持续化到磁盘。ngx_buf_t实例化的时候也是在ngx_pool_t里实例化的。
  • nginx中用ngx_chain_t管理一系列ngx_buf_t,用于管理内存中一系列文件,持续化到磁盘。
nginx高级数据结构
ngx_array_t
//ngx_array
//nginx实现的动态数组
typedef struct {
    void        *elts;	//具体数据内存块
    ngx_uint_t   nelts;	//已使用个数
    size_t       size;	//每个数据分配大小
    ngx_uint_t   nalloc;	//分配个数
    ngx_pool_t  *pool;	//所属内存池
} ngx_array_t;

使用示例:

// gcc -o ngx_array_main ngx_array_main.c -I ../nginx-1.13.7/src/core/ -I ../nginx-1.13.7/objs/  -I ../nginx-1.13.7/src/os/unix/ -I ../pcre-8.41/ -I ../nginx-1.13.7/src/event/ ../nginx-1.13.7/objs/src/core/ngx_list.o ../nginx-1.13.7/objs/src/core/ngx_string.o ../nginx-1.13.7/objs/src/core/ngx_palloc.o ../nginx-1.13.7/objs/src/os/unix/ngx_alloc.o ../nginx-1.13.7/objs/src/core/ngx_array.o

#include <stdio.h>
#include <string.h>

#include "ngx_config.h"

#include "ngx_core.h"
#include "ngx_list.h"
#include "ngx_palloc.h"
#include "ngx_string.h"

#define N		10

typedef struct _key {
	int id;
	char name[32];
} Key;

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, ...)
{

}

void print_array(ngx_array_t *array) {

	Key *key = array->elts;

	int i = 0;
	for (i = 0;i < array->nelts;i ++) {
		printf("%s .\n", key[i].name);
	}
}

int main() {

	ngx_pool_t *pool = ngx_create_pool(1024, NULL);

	ngx_array_t *array = ngx_array_create(pool, N, sizeof(Key));

	int i = 0;
	Key *key = NULL;
	for (i = 0;i < 25;i ++) {

		key = ngx_array_push(array);
		key->id = i+1;
		sprintf(key->name, "King %d", key->id);
		
	}

	key = ngx_array_push_n(array, 10);
	for (i = 0;i < 10;i ++) {
		key[i].id = 25+i+1;
		sprintf(key[i].name, "King %d", key[i].id);
	}

	print_array(array);
}
ngx_rbree_t
//ngx_rbtree.h
typedef struct ngx_rbtree_s  ngx_rbtree_t;
struct ngx_rbtree_s {
    ngx_rbtree_node_t     *root;
    ngx_rbtree_node_t     *sentinel;
    ngx_rbtree_insert_pt   insert;
};

使用示例:

// gcc -o ngx_array_main ngx_array_main.c -I ../nginx-1.13.7/src/core/ -I ../nginx-1.13.7/objs/  -I ../nginx-1.13.7/src/os/unix/ -I ../pcre-8.41/ -I ../nginx-1.13.7/src/event/ ../nginx-1.13.7/objs/src/core/ngx_list.o ../nginx-1.13.7/objs/src/core/ngx_string.o ../nginx-1.13.7/objs/src/core/ngx_palloc.o ../nginx-1.13.7/objs/src/os/unix/ngx_alloc.o ../nginx-1.13.7/objs/src/core/ngx_rbtree.o

#include <stdio.h>
#include <string.h>

#include "ngx_config.h"

#include "ngx_core.h"

#include "ngx_list.h"
#include "ngx_palloc.h"
#include "ngx_string.h"
#include "ngx_rbtree.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() {

	ngx_rbtree_t rbtree;
	ngx_rbtree_node_t sentinel;
	
	ngx_rbtree_init(&rbtree, &sentinel, ngx_str_rbtree_insert_value);

	ngx_str_node_t strnode[10];
	ngx_str_set(&strnode[0].str, "he");
	ngx_str_set(&strnode[1].str, "jon");
	ngx_str_set(&strnode[2].str, "Issac");
	ngx_str_set(&strnode[3].str, "tursom");
	ngx_str_set(&strnode[4].str, "will");
	ngx_str_set(&strnode[5].str, "birate");
	ngx_str_set(&strnode[6].str, "ren");
	ngx_str_set(&strnode[7].str, "stephen");
	ngx_str_set(&strnode[8].str, "ultimate");
	ngx_str_set(&strnode[9].str, "he");

	int i = 0;
	for (i = 0;i < 10;i ++) {
		strnode[i].node.key = i;
		ngx_rbtree_insert(&rbtree, &strnode[i].node);
	}

	ngx_str_t str = ngx_string("will");
	
	ngx_str_node_t *node = ngx_str_rbtree_lookup(&rbtree, &str, 0);
	if (node != NULL) {
		printf(" Exit\n");
	}
}
nginx进程通信机制
ngx_shm_t
//ngx_shmem.h
typedef struct {
    u_char      *addr;
    size_t       size;
    ngx_str_t    name;
    ngx_log_t   *log;
    ngx_uint_t   exists;   /* unsigned  exists:1;  */
} ngx_shm_t;
ngx_pool_t
//ngx_core.h
typedef struct ngx_pool_s            ngx_pool_t;

//ngx_palloc.h
typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;

struct ngx_pool_s {
    ngx_pool_data_t       d;
    size_t                max;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

使用示例:

// gcc -o ngx_array_main ngx_array_main.c -I ../nginx-1.13.7/src/core/ -I ../nginx-1.13.7/objs/  -I ../nginx-1.13.7/src/os/unix/ -I ../pcre-8.41/ -I ../nginx-1.13.7/src/event/ ../nginx-1.13.7/objs/src/core/ngx_list.o ../nginx-1.13.7/objs/src/core/ngx_string.o ../nginx-1.13.7/objs/src/core/ngx_palloc.o ../nginx-1.13.7/objs/src/os/unix/ngx_alloc.o ../nginx-1.13.7/objs/src/core/ngx_array.o

#include <stdio.h>
#include <string.h>

#include "ngx_config.h"

#include "ngx_core.h"

#include "ngx_list.h"
#include "ngx_palloc.h"
#include "ngx_string.h"

// ngx_create_pool
// ngx_palloc

typedef struct _key {
	int id;
	char name[32];
} Key;

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, ...)
{

}

void print_pool(ngx_pool_t *pool) {

	ngx_pool_t *pool_head = pool;

	while (pool) {
		printf("unused : %ld\n", pool->d.end - pool->d.last);

		pool = pool->d.next;
		printf(" ----------------- \n");
	}
}

int main() {

	ngx_pool_t *pool = ngx_create_pool(1024, NULL);

	Key *key = ngx_palloc(pool, sizeof(Key));
	key->id = 10;
	sprintf(key->name, "king %d", key->id);

	print_pool(pool);

	char *ptr = ngx_palloc(pool, 990);
	ptr[989] = 'a';

	print_pool(pool);

	ngx_destroy_pool(pool);
}

思考一下,操作上面这些数据结构,需要什么样的对应函数(增删改查)。然后看下具体的函数如何操作这些数据结构数据,怎么增删改查。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值