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

Nginx的c30k问题解决方法

程序员文章站 2023-11-25 22:56:52
最近我们的下载服务遭遇了c30k,导致nginx的下载服务近乎停滞。原因嘛,很简单,服务器部署在国外,众所周知的原因,sl机房的线路不稳,加上不同地区出口速率抖动很厉害,为...

最近我们的下载服务遭遇了c30k,导致nginx的下载服务近乎停滞。原因嘛,很简单,服务器部署在国外,众所周知的原因,sl机房的线路不稳,加上不同地区出口速率抖动很厉害,为了加速下载,我们放开了限制,允许用户使用多线程的下载工具。这样一来,自然产生了c10k问题。下载文件都不小,每个用户至少使用4线程,同时下载若干个素材。。。很自然并发链接数30k以上。

更受限于手头money,无法扩容(实际上要有钱也不会跑国外)。因此,必须提高单机并发能力和吞吐量。

我们的下载服务是使用perl写的一个plack应用,典型的psgi,实现下载验证,实时防火墙,用户下载跟踪等等,无法直接使用静态文件分发(实际上perl的性能还是很高效的,部署于starman,对比php的实现,是后者(php-fpm)的10倍左右)。

starman是一个很不错的psgi server,它使用传统的prefork模式。即便高效,但prefork确实无法有效应对c10k,我无法把starman的worker增大到几百上千个。在以前的文章曾经提到evented io是能够应付c10k的一个方案。因此,我使用twiggy换下了starman。twiggy是基于ae(anyevent)的一个psgi server,单进程。在低并发下,单进程的twiggy的qps是弱于starman,不过到了高并发,twiggy的优势就显现出来了。在实际部署中,我启动了多个twiggy进程,分别监听独立的端口,nginx则使用upstream进行负载均衡。 10个twiggy的吞吐量已经远远超过了50个starman worker。 twiggy的开销也不大,因此可以很放心的增加twiggy的进程。

感谢psgi的接口规范,从starman切换到twiggy,应用程序无需做任何改动。(前提是程序内不能有阻塞io的操作)。

另一个问题是服务器的io-wait比较高,毕竟下载这个是io-bound的任务。

nginx支持linux native aio,因此我考虑是否使用aio能够大大降低io-wait? 性能应该有比较明显的提升?

网上有一些资料,吹嘘的nginx aio性能提升,神奇云云。我有点将信将疑,因为都没有任何的测试数据比较,均是人云亦云。另外,多数配置都是或多或少有问题的。

我使用的centos, nginx aio要使用,必须是centos 5.5以上。因为只有5.5的kernel才有aio的backport,nginx并没有使用libaio。

此外,nginx的aio本来是为freebsd开发,linux固然可以使用,不过受到了linux aio的很多限制。

1. 必须使用direct io. 这样一来,导致无法使用vm的disk cache.
2. 文件只有大小和directio_alignment定义block size整数倍的数据才可以使用aio,当文件整数据块之前和之后,那些不能取整的部分则是blocking方式读取的,这也是为什么需要output-buffer。directio_alignment大小取决于你使用的文件系统,默认是512,而对于xfs,注意,如果你没有修改xfs bsize, 需要调整为xfs默认的4k.

我使用的配置如下:

复制代码 代码如下:

location /archive {
internal;
aio on;
directio 4k;
directio_alignment 4k;
output_buffers 1 128k;
}

当启用aio后,可以看到vmstat中,cache的内存消耗迅速降低,这是因为使用aio必须使用directio,这就绕过了vm的diskcache。

实际性能如何,aio一定很快么? 这点即便是igor也不确定。

从我们自己的实际效果看,aio并没有明显的性能提升,相反,偶尔会轻微增加了io-wait,这是因为无法利用diskcache,而如果文件多数又和directio_alignment有偏差(尤其是断点续传的时候,多数文件读取位置在directio_alignment数据边界外),这部分的数据必须使用blocking io读取,又没有disk cache,增加io-wait也可以理解。

最终,结论是,与其使用不那么靠谱的nginx aio, 不如多开一些nginx的worker,重复利用vm disk cache, 当内存100%利用率的时候,nginx的静态文件分发效率是高于aio模式的。

btw,这个实际用例也重新印证了我的一个观点,不要轻信网上那些毫无测试数据的忽悠,多数都是copy & paste的传说, 各个说好,其实多数都没实际印证过。