Tag Archives: Nginx

搭建微信订阅号后台服务

搭建微信订阅号后台服务

准备域名

任务时间:20min ~ 40min

微信公众平台需要配置服务器地址 URL 访问,在实验开始之前,我们要准备域名。

域名注册

如果您还没有域名,可以在腾讯云上选购,过程可以参考下面的视频。

  • 视频 – 在腾讯云上购买域名

域名解析

域名购买完成后, 需要将域名解析到实验云主机上,实验云主机的 IP 为:

<您的 CVM IP 地址>

在腾讯云购买的域名,可以到控制台添加解析记录,过程可参考下面的视频:

  • 视频 – 如何在腾讯云上解析域名

域名设置解析后需要过一段时间才会生效,通过 ping 命令检查域名是否生效 [?],如:

ping www.yourmpdomain.com

如果 ping 命令返回的信息中含有你设置的解析的 IP 地址,说明解析成功。

注意替换下面命令中的 www.yourmpdomain.com 为您自己的注册的域名

申请微信个人订阅号

任务时间:5min ~ 10min

在开始搭建我们的订阅号服务器之前,需要先拿到订阅号相关信息。

注册开发者账号

如果你还不是微信订阅号开发者,请先在微信公众平台注册:

https://mp.weixin.qq.com

具体注册流程可参考如下视频:

  • 视频 – 注册开发者账号

若您已注册,请点击下一步。

获取微信订阅号公众平台认证字段信息

我们需要获取3个字段:AppID Token EncodingAESKey。

登录微信公众平台,依次进入 开发 – 基本配置 可以拿到 AppID。

基本配置 – 服务器配置 – 修改配置 表单中:

URL 填第一步申请的域名;

Token 用户根据提示填写,用于后面校验服务端合法性;

EncodingAESKey 点击随机生成按钮来生成。

当点击表单提交按钮时,微信会通过 Token 来校验 URL 的合法性,这个我们在后面步骤实现,此界面暂时保留不关闭。

AppID Token EncodingAESKey 这3个参数具体的获取步骤也可以参照下面的视频

  • 视频 – 获取微信订阅号信息

搭建 HTTP 服务

任务时间:15min ~ 30min

下面的步骤,将带大家在服务器上使用 Node 和 Express 搭建一个 HTTP 服务器

安装 NodeJS 和 NPM

使用下面的命令安装 NodeJS 和 NPM

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
yum install nodejs -y

安装完成后,使用下面的命令测试安装结果

node -v

编写 HTTP Server 源码

创建工作目录

使用下面的命令在服务器创建一个工作目录:

mkdir -p /data/release/weapp

进入此工作目录

cd /data/release/weapp

创建 package.json

在刚才创建的工作目录创建 package.json,添加我们服务器包的名称和版本号,可参考下面的示例。

示例代码:/data/release/weapp/package.json
{
    "name": "weapp",
    "version": "1.0.0"
}

完成后,使用 Ctrl + S 保存文件

添加 Server 源码

在工作目录创建 app.js,使用 Express.js 来监听 5050 端口[?],可参考下面的示例代码(注:请将 app.js 文件中的token/appid/encodingAESKey等配置项替换为您的订阅号对应的取值)。

示例代码:/data/release/weapp/app.js
// 引用 express 来支持 HTTP Server 的实现
const express = require('express');

// 引用微信公共平台自动回复消息接口服务中间件
var wechat = require('wechat');

// 创建一个 express 实例
const app = express();

// 配置微信公众平台参数,在教程第二步中获取
var config = {
    token: 'your token', // 填第二步中获取的 `token`
    appid: 'your appid', // 填第二步中获取的 `appid`
    encodingAESKey: 'your encodingAESKey', // 填第二步中获取的 `encodingAESKey`
    checkSignature: true // 可选,默认为true。由于微信公众平台接口调试工具在明文模式下不发送签名,所以如要使用该测试工具,请将其设置为false 
};

app.use(express.query());

app.use('/', wechat(config, function (req, res, next) {
    res.reply({
        content: '你好,Hello World!',
        type: 'text'
    });
}));

// 监听端口,等待连接
const port = 5050;
app.listen(port);

// 输出服务器启动日志
console.log(`Server listening at http://127.0.0.1:${port}`);

本实验会以 5050 端口的打开作为实验步骤完成的依据,为了后面的实验步骤顺利进行,请不要使用其它端口号

运行 HTTP 服务

安装 PM2

在开始之前,我们先来安装 [PM2]

npm install pm2 --global

PM2 安装时间可能稍长,请耐心等候 [?]

安装 Express

我们的服务器源码里使用到了 Express 模块,下面的命令使用 NPM 来安装 Express

cd /data/release/weapp
npm install express --save

安装 Wechat

我们的服务器源码里使用到了 Wechat 模块,下面的命令使用 NPM 来安装 Wechat

cd /data/release/weapp
npm install wechat --save

启动服务

安装完成后,使用 PM2 来启动 HTTP 服务

cd /data/release/weapp
pm2 start app.js

现在,您的 HTTP 服务已经在 http://<您的 CVM IP 地址>:5050 运行

要查看服务输出的日志,可以使用下面的命令:

pm2 logs

如果要重启服务,可以使用下面的命令:

pm2 restart app

我们使用 PM2 来进行 Node 进程的运行、监控和管理

NPM 仓库在国内访问速度可能不太理想,如果实在太慢可以尝试使用 CNPM 的 Registry 进行安装:npm install pm2 -g --registry=https://r.cnpmjs.org/

搭建 nginx 对外服务

任务时间:15min ~ 30min

NodeJs只是侦听的机器上的 5050 端口,我们使用 nginx 侦听 80 端口提供对外域名服务

安装 Nginx

在 CentOS 上,可直接使用 yum 来安装 Nginx

yum install nginx -y

安装完成后,使用 nginx 命令启动 Nginx:

nginx

此时,访问 http://<您的域名> 可以看到 Nginx 的测试页面 [?]

如果无法访问,请重试用 nginx -s reload 命令重启 Nginx

配置 HTTP 反向代理

外网用户访问服务器的 Web 服务由 Nginx 提供,Nginx 需要配置反向代理才能使得 Web 服务转发到本地的 Node 服务。

Nginx 配置目录在 /etc/nginx/conf.d,我们在该目录创建 wechat.conf

示例代码:/etc/nginx/conf.d/wechat.conf
server {
        listen 80;
        server_name www.example.com; # 改为第一步申请的域名

        location / {
            proxy_pass http://127.0.0.1:5050;
        }
    }

按 Ctrl + S 保存配置文件,让 Nginx 重新加载配置使其生效:

nginx -s reload

在浏览器通过 http 的方式访问你解析的域名来测试 HTTP 是否成功启动

使用Server端回复微信消息

任务时间:1min ~ 5min

提交服务端配置

我们将第二步微信公众平台中保留的表单提交,同时将 基本配置 – 服务器配置 启用

关注、发送与消息回复

首先通过二维码关注微信订阅号

在聊天界面向微信公众号发送一条消息

最终我们会回到一条 你好,Hello World! 的回复

大功搞成

恭喜!您已经完成了搭建微信订阅号后台服务的实验内容!您可以留用或者购买 Linux 版本的 CVM 继续学习。

静态文件用nginx直接serve

#css|js|ico|gif|jpg|jpeg|png|txt|html|htm|xml|swf|wav这些都是静态文件,但应分辨,js、css可能经常会变,过期时间应小一些,图片、html基本不变,过期时间可以设长一些
location ~* ^.+\.(ico|gif|jpg|jpeg|png|html|htm)$ {
root /var/www/poseidon/root/static;
access_log off;
expires 30d;
}
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
root /var/www/poseidon/root/static;
access_log off;
expires 24h;
}
#注:location不包括?后面带的参数,所以以上正则可以匹配http://192.168.1.16/image/sxxx.jpg?a=xxx

Nginx的worker_cpu_affinity详解

配置文件中的worker_cpu_affinity可以用来绑定每个nginx进程所使用的CPU
官方的解释是:
#----------------------------引用文字-开始----------------------------
Syntax: worker_cpu_affinity cpumask [cpumask...]
Default: none
Linux only.
With this option you can bind the worker process to a CPU, it calls sched_setaffinity().
For example,
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
Bind each worker process to one CPU only.
worker_processes 2;
worker_cpu_affinity 0101 1010;
Bind the first worker to CPU0/CPU2, bind the second worker to CPU1/CPU3. This is suitable for HTT.
#----------------------------引用文字-结束----------------------------

最关键的地方没说清楚,怎样来表示每个CPU?

经过漫天的搜索和多次尝试发现
详解

如果8核就是:

worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

如此类推~~

resin + nginx

download the upstream jvm route from http://code.google.com/p/nginx-upstream-jvm-route/

[root@web1 nginx-1.2.0]# tar -zxf nginx-upstream-jvm-route-0.1.tar.gz

[root@web1 nginx-1.2.0]# patch -p0 ./nginx_upstream_jvm_route/jvm_route.patch

[root@web1 nginx-1.2.0]# ./configure –sbin-path=/usr/sbin/ –conf-path=/etc/nginx/nginx.conf –with-http_stub_status_module –with-http_ssl_module –add-module=./nginx_upstream_jvm_route

 

edit /etc/nginx/nginx.conf

add

upstream resin_proxy {

server 127.0.0.1:85 srun_id=app-by1 max_fails=2 fail_timeout=10s weight=200; //负载均衡
server web3:85 srun_id=app-by2 max_fails=2 fail_timeout=10s weight=200;      //负载均衡
jvm_route $cookie_JSESSIONID|sessionid;
}

server {
listen 80;
server_name default yourhosts;
location / {
proxy_pass http://resin_proxy;
include proxy.conf;
index index.jsp index.html index.htm;
}
}

create proxy.conf

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

 

 

varnish,squid,apache,nginx缓存文件比较

一,测试环境

1,硬件是奔腾双核,机子三年前买的。系统是archlinux

2,测试varnish和squid的时候,web服务用的apache

3,测试apache的时候,启动了5个进程,不过随着压力的增加,进程会增加的。

4,测试nginx的时候,启动了十个nginx进程,20个php-cgi进程

 

5,varnish,squid,nginx用的是反向代理的形势,也就是说访问图片的时候,要先透过缓存工具

二,测试

1,varnish

[root@BlackGhost bin]# /usr/local/bin/webbench -c 100 -t 20 http://127.0.0.1:8080/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://127.0.0.1:8080/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
100 clients, running 20 sec.

Speed=476508 pages/min, 47258114 bytes/sec.
Requests: 158836 susceed, 0 failed.

访问了这么次,没有缓存只有一次,效率真的很高。

2,squid

[root@BlackGhost bin]# /usr/local/bin/webbench -c 100 -t 20 http://localhost:9000/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://localhost:9000/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
100 clients, running 20 sec.

Speed=133794 pages/min, 7475018 bytes/sec.
Requests: 44598 susceed, 0 failed.

从测试效果来说,squid挺让我失望的,在测试前,我心里是这样估计的,缓存最好的是varnish,其次是squid,然后nginx,最后是apache,现在呢,squid是最差的。后来我看了一下log文件,发现正常情况下,缓存和没有缓存的比率不是1:2,如果在高压力下,缓存和没有缓存的比率更小。

3,apache

[root@BlackGhost conf]# /usr/local/bin/webbench -c 100 -t 20 http://localhost/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://localhost/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
100 clients, running 20 sec.

Speed=160890 pages/min, 15856005 bytes/sec.
Requests: 53630 susceed, 0 failed.

4,nginx

[root@BlackGhost conf]# /usr/local/bin/webbench -c 100 -t 20 http://localhost:10000/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://localhost:10000/00/01/RwGowEtWvcQAAAAAAAAWHH0Rklg81.gif
100 clients, running 20 sec.

Speed=304053 pages/min, 30121517 bytes/sec.
Requests: 101351 susceed, 0 failed.

从上面的测试结果我们可以发现,varnish > nginx > apache > squid,我想这个结果,根大家预期的结果有点出入,因为squid做老牌文件缓存工具怎么会这么差呢,squid的命中率低,我在网上查了一下,很多人都是这样的,这个可能根个人配置有关系,也许真正的高手,才能让squid发挥最大功力。

原文地址:http://blog.51yip.com/server/1032.html

nginx+resin 使用中文域名解决方案。

xxx中文域名.中国

这样的域名在resin下会出错:

[15:34:31.628] {hmux-127.0.0.1:6801-5} java.lang.StringIndexOutOfBoundsException: String index out of range: 9[15:34:31.628] {hmux-127.0.0.1:6801-5}  at java.lang.String.charAt(String.java:687)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.DomainName.decode(DomainName.java:205)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.DomainName.fromAscii(DomainName.java:86)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.HostContainer.buildInvocation(HostContainer.java:305)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.cluster.Server.buildInvocation(Server.java:915)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.dispatch.DispatchServer.buildInvocation(DispatchServer.java:209)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.hmux.HmuxRequest.handleRequest(HmuxRequest.java:427)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.port.TcpConnection.run(TcpConnection.java:603)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:721)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:643)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at java.lang.Thread.run(Thread.java:619)[15:34:31.628] {hmux-127.0.0.1:6801-5} java.lang.RuntimeException: java.lang.StringIndexOutOfBoundsException: String index out of range: 9[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.DomainName.fromAscii(DomainName.java:109)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.HostContainer.buildInvocation(HostContainer.java:305)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.cluster.Server.buildInvocation(Server.java:915)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.dispatch.DispatchServer.buildInvocation(DispatchServer.java:209)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.hmux.HmuxRequest.handleRequest(HmuxRequest.java:427)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.port.TcpConnection.run(TcpConnection.java:603)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:721)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:643)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at java.lang.Thread.run(Thread.java:619)[15:34:31.628] {hmux-127.0.0.1:6801-5} Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: 9[15:34:31.628] {hmux-127.0.0.1:6801-5}  at java.lang.String.charAt(String.java:687)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.DomainName.decode(DomainName.java:205)[15:34:31.628] {hmux-127.0.0.1:6801-5}  at com.caucho.server.host.DomainName.fromAscii(DomainName.java:86)[15:34:31.628] {hmux-127.0.0.1:6801-5}  … 8 more

 

 

原因是中文域名做了“转码”,不知道是什么鬼东西。反正就出错了。要解决。

分析一下中文域名转码后是怎样的?

例如 中文域名.中国   转码后   xn--wlqpfy8in9c9zd3hc50a.xn--io0a7i

原来这样:当resin接收 到host时,用正常的域名去解释这个地址,由于这个地址不符合正规的域名格式,所以出错。

解决思路,能不能在nginx转发时,改变host呢?查一查nginx说明文档,有一条这样写:

proxy_set_header Host $host;

应该就是这条了。将后面的$host改为 一个英文域名

proxy_set_header Host www.youdomain.com;

 

问题解决了。哈。。。大家加油。

 

 

Nginx源码分析-内存池

Nginx的内存池实现得很精巧,代码也很简洁。总的来说,所有的内存池基本都一个宗旨:申请大块内存,避免“细水长流”。

一、创建一个内存池

nginx内存池主要有下面两个结构来维护,他们分别维护了内存池的头部和数据部。此处数据部就是供用户分配小块内存的地方。

//该结构用来维护内存池的数据块,供用户分配之用。
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;	//可以挂一个chain结构
    ngx_pool_large_t     *large;	//分配大块内存用,即超过max的内存请求
    ngx_pool_cleanup_t   *cleanup;	//挂载一些内存池释放的时候,同时释放的资源。
    ngx_log_t            *log;
};

有了上面的两个结构,就可以创建一个内存池了,nginx用来创建一个内存池的接口是:ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)(位于src/core/ngx_palloc.c中);调用这个函数就可以创建一个大小为size的内存池了。这里,我用内存池的结构图来展示,就不做具体的代码分析了。

ngx_create_pool接口函数就是分配上图这样的一大块内存,然后初始化好各个头部字段(上图中的彩色部分)。红色表示的四个字段就是来自于上述的第一个结构,维护数据部分,由图可知:last是用户从内存池分配新内存的开始位置,end是这块内存池的结束位置,所有分配的内存都不能超过end。蓝色表示的max字段的值等于整个数据部分的长度,用户请求的内存大于max时,就认为用户请求的是一个大内存,此时需要在紫色表示的large字段下面单独分配;用户请求的内存不大于max的话,就是小内存申请,直接在数据部分分配,此时将会移动last指针。

二、分配小块内存(size <= max)

上面创建好了一个可用的内存池了,也提到了小块内存的分配问题。nginx提供给用户使用的内存分配接口有:
void *ngx_palloc(ngx_pool_t *pool, size_t size);
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);

ngx_palloc和ngx_pnalloc都是从内存池里分配size大小内存,至于分得的是小块内存还是大块内存,将取决于size的大小;他们的不同之处在于,palloc取得的内存是对齐的,pnalloc则否。ngx_pcalloc是直接调用palloc分配好内存,然后进行一次0初始化操作。ngx_pmemalign将在分配size大小的内存并按alignment对齐,然后挂到large字段下,当做大块内存处理。下面用图形展示一下分配小块内存的模型:

上图这个内存池模型是由上3个小内存池构成的,由于第一个内存池上剩余的内存不够分配了,于是就创建了第二个新的内存池,第三个内存池是由于前面两个内存池的剩余部分都不够分配,所以创建了第三个内存池来满足用户的需求。由图可见:所有的小内存池是由一个单向链表维护在一起的。这里还有两个字段需要关注,failed和current字段。failed表示的是当前这个内存池的剩余可用内存不能满足用户分配请求的次数,即是说:一个分配请求到来后,在这个内存池上分配不到想要的内存,那么就failed就会增加1;这个分配请求将会递交给下一个内存池去处理,如果下一个内存池也不能满足,那么它的failed也会加1,然后将请求继续往下传递,直到满足请求为止(如果没有现成的内存池来满足,会再创建一个新的内存池)。current字段会随着failed的增加而发生改变,如果current指向的内存池的failed达到了4的话,current就指向下一个内存池了。猜测:4这个值应该是作者的经验值,或者是一个统计值。

三、大块内存的分配(size > max)

大块内存的分配请求不会直接在内存池上分配内存来满足,而是直接向操作系统申请这么一块内存(就像直接使用malloc分配内存一样),然后将这块内存挂到内存池头部的large字段下。内存池的作用在于解决小块内存池的频繁申请问题,对于这种大块内存,是可以忍受直接申请的。同样,用图形展示大块内存申请模型:

注意每块大内存都对应有一个头部结构(next&alloc),这个头部结构是用来将所有大内存串成一个链表用的。这个头部结构不是直接向操作系统申请的,而是当做小块内存(头部结构没几个字节)直接在内存池里申请的。这样的大块内存在使用完后,可能需要第一时间释放,节省内存空间,因此nginx提供了接口函数:ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);此函数专门用来释放某个内存池上的某个大块内存,p就是大内存的地址。ngx_pfree只会释放大内存,不会释放其对应的头部结构,毕竟头部结构是当做小内存在内存池里申请的;遗留下来的头部结构会作下一次申请大内存之用。

四、cleanup资源


可以看到所有挂载在内存池上的资源将形成一个循环链表,一路走来,发现链表这种看似简单的数据结构却被频繁使用。由图可知,每个需要清理的资源都对应有一个头部结构,这个结构中有一个关键的字段handler,handler是一个函数指针,在挂载一个资源到内存池上的时候,同时也会注册一个清理资源的函数到这个handler上。即是说,内存池在清理cleanup的时候,就是调用这个handler来清理对应的资源。比如:我们可以将一个开打的文件描述符作为资源挂载到内存池上,同时提供一个关闭文件描述的函数注册到handler上,那么内存池在释放的时候,就会调用我们提供的关闭文件函数来处理文件描述符资源了。

五、内存的释放

nginx只提供给了用户申请内存的接口,却没有释放内存的接口,那么nginx是如何完成内存释放的呢?总不能一直申请,用不释放啊。针对这个问题,nginx利用了web server应用的特殊场景来完成;一个web server总是不停的接受connection和request,所以nginx就将内存池分了不同的等级,有进程级的内存池、connection级的内存池、request级的内存池。也就是说,创建好一个worker进程的时候,同时为这个worker进程创建一个内存池,待有新的连接到来后,就在worker进程的内存池上为该连接创建起一个内存池;连接上到来一个request后,又在连接的内存池上为request创建起一个内存池。这样,在request被处理完后,就会释放request的整个内存池,连接断开后,就会释放连接的内存池。因而,就保证了内存有分配也有释放。

总结:通过内存的分配和释放可以看出,nginx只是将小块内存的申请聚集到一起申请,然后一起释放。避免了频繁申请小内存,降低内存碎片的产生等问题