欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NGINX开发杀手锏-线程池

程序员文章站 2022-05-24 14:26:46
...

       nginx以高性能著称,在其内部运转的过程中,没有任何阻塞操作(极端情况还是存在),跟外部的通讯(比如fastcgi)以完全异步的方式进行。在线程池引入之前,我们已经觉得这足够完美。但是线程池的出现,让nginx在性能方面上了一个新的高度。本文将通过一个例子展现这个杀手锏。

 

1、需求:

 

我们想让nginx直接跟mysql通讯,你可以选择drizzle,这是异步的方式。本文我们为展现线程池带来的好处,用阻塞的方式与mysql进行通讯,所以选择libmysqlclient这个长久且稳定的库来操作mysql。

 

2、建立环境:

nginx:192.168.1.100

mysql:192.168.1.101

wrk1:192.168.1.102

wrk2:192.168.1.103


a、编译测试模块

> ./configure --with-threads --add-module=/xxx/nginx-http-mysql-module && make

b、配置

server {

    listen       80 ;

    #以下是mysql连接信息,请自行调整

    mysql_host      192.168.100.101;

    mysql_user      ***;

    mysql_pass      ***;

    mysql_db        ***;

    mysql_query     "select * from car";

    location /mwb {

        mysql_with_block;

    }

    location /mwt {

        mysql_with_thread;

    }

}

模块下载地址:nginx-http-mysql-module.tar.gz

3、测试

我选择wrk这个测试工具来进行压测。为了让测试更加接近真实,我选择两台客户端机器,第一台不断的制造压测,第二台用普通的方式进行测试。之所以这样是因为如果nginx服务器因为libmysqlclient阻塞了,第二台的qps的就很少。如果ngx服务器不会因为libmysqlclient阻塞,那第二台的qps会表现不错。

a、访问阻塞压测:

wrk1: > wrk -t12 -c400 -d100s http://192.168.1.100/mwb      

wrk2: > wrk -t12 -c400 -d30s http://192.168.1.100/mwb

nginx服务器

top - 23:18:23 up  3:24,  4 users,  load average: 0.19, 0.17, 0.11

Tasks: 100 total,   2 running,  95 sleeping,   3 stopped,   0 zombie

Cpu(s):  1.1%us, 45.9%sy,  0.0%ni, 41.8%id,  0.0%wa,  2.6%hi,  8.6%si,  0.0%st

Mem:   1922432k total,   677352k used,  1245080k free,    87704k buffers

Swap:  4128760k total,        0k used,  4128760k free,   386840k cached

 

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                       

21931 nobody    20   0  433m 3876 1444 R 55.9  0.2   0:50.05 nginx   


wrk1机器

Running 2m test @ http://192.168.100.134/mwb

  12 threads and 400 connections

  Thread Stats   Avg      Stdev     Max   +/- Stdev

    Latency   376.91ms  288.22ms   1.98s    65.05%

    Req/Sec    41.80     68.62   707.00     92.33%

  44629 requests in 1.67m, 8.81MB read

  Socket errors: connect 0, read 25, write 17, timeout 1629

  Non-2xx or 3xx responses: 11546

Requests/sec:    445.90

Transfer/sec:     90.11KB


wrk2机器

Running 30s test @ http://192.168.100.134/mwb

  12 threads and 400 connections

  Thread Stats   Avg      Stdev     Max   +/- Stdev

    Latency     0.00us    0.00us   0.00us    -nan%

    Req/Sec     0.00      0.00     0.00      -nan%

  0 requests in 30.02s, 0.00B read

Requests/sec:      0.00

Transfer/sec:       0.00B


b、访问线程池压测:

wrk1: > wrk -t12 -c400 -d100s http://192.168.1.100/mwt      

wrk2: > wrk -t12 -c400 -d30s http://192.168.1.100/mwt

nginx服务器

top - 23:24:56 up  3:30,  5 users,  load average: 3.00, 0.75, 0.31

Tasks:  99 total,   2 running,  95 sleeping,   2 stopped,   0 zombie

Cpu(s):  0.7%us, 93.4%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.7%hi,  5.3%si,  0.0%st

Mem:   1922432k total,   687728k used,  1234704k free,    88016k buffers

Swap:  4128760k total,        0k used,  4128760k free,   391292k cached

 

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                       

22010 nobody    20   0  882m 5564 1452 R 96.5  0.3   0:28.20 nginx  


wrk1机器

[root@localhost ~]# wrk -t12 -c400 -d100s http://192.168.100.134/mwt

Running 2m test @ http://192.168.100.134/mwt

  12 threads and 400 connections

  Thread Stats   Avg      Stdev     Max   +/- Stdev

    Latency   455.77ms  388.01ms   2.00s    80.91%

    Req/Sec    61.15     53.08   310.00     69.47%

  51479 requests in 1.67m, 9.17MB read

  Socket errors: connect 0, read 15, write 0, timeout 1249

  Non-2xx or 3xx responses: 8037

Requests/sec:    514.30

Transfer/sec:     93.80KB


wrk2机器

[root@localhost ~]# wrk -t12 -c400 -d30s http://192.168.100.134/mwt

Running 30s test @ http://192.168.100.134/mwt

  12 threads and 400 connections

  Thread Stats   Avg      Stdev     Max   +/- Stdev

    Latency   734.96ms  177.00ms   2.00s    87.92%

    Req/Sec    47.40     50.75   310.00     83.23%

  10943 requests in 30.09s, 1.79MB read

  Socket errors: connect 0, read 8, write 0, timeout 513

  Non-2xx or 3xx responses: 862

Requests/sec:    363.63

Transfer/sec:     60.91KB


测试总结:

开启线程池后,nginx的cpu得到更充分利用,第二台机器没有因为第一台的不断访问而受到处理阻碍,跟我们预期的一样,性能得到可观的提升。

4、解释

nginx引入线程池后本质上解决了什么呢?主线程不会被阻塞。它将阻塞的操作转移到了其它的线程,但又能得到回调通知的处理。所以在处理并发的能力上很接近异步的方式。可以说,这让nginx开发业务模块有了更多的选择,毕竟阻塞式的库比异步的容易实现,而且开源的也更丰富。相信不久以后,会有更多的nginx模块冒出来,拭目以待吧。需要说明的是,线程池是为了解决‘阻塞’,如果您的应用没有这个问题,引入线程池反而增加了不必要的开销。

5、线程池是如何实现的

 

如果想了解线程池的分析,在ngx内部如何实现,以及如何开发基于线程池的模块。阅读 nginx源码分析之线程池

推荐阅读:NGINX使用线程池提升性能9x倍

 

 

转自:http://nglua.com/articles/12.html