[nginx]Nginx下限速限制下载速度实例
Nginx(著名的高性能http服务器和反向代理服务器)的模块开发,在此分享nginx的限速实现核心代码。
Nginx的http核心模块ngx_http_core_module中提供limit_rate这个指令可以用于控制速度,limit_rate_after用于设置http请求传输多少字节后开始限速。
另外两个模块ngx_http_limit_conn_module和ngx_http_limit_req_module分别用于连接数和连接频率的控制。
限制速度的配置指令简单易懂,限速支持固定的数值
- location /flv/ {
- limit_rate_after 500k;
- limit_rate 50k;
- }
查 看nginx源代码,可以发现ngx_http_write_filter_module.c源文件具体实现了速度的控制,nginx的特点是高度模块 化,从名字可以看出这个文件其实也是一个filter模块(nginx中的模块分handler,filter,upstream等三类),这个模块属于 filter类别。
- static ngx_int_t
- ngx_http_write_filter_init(ngx_conf_t *cf)
- {
- ngx_http_top_body_filter = ngx_http_write_filter;
- return NGX_OK;
- }
模块挂载了一个函数在filter的顶端(经过编译链接后此模块即被“压”到filter“链表”的尾部),用于控制数据的输出,这个函数里面就包含了速度的控制。
- if (r->limit_rate) {
- limit = r->limit_rate * (ngx_time() - r->start_sec + 1)
- - (c->sent - clcf->limit_rate_after);
- if (limit <= 0) {
- c->write->delayed = 1;
- ngx_add_timer(c->write,
- (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1));
- c->buffered |= NGX_HTTP_WRITE_BUFFERED;
- return NGX_AGAIN;
- }
- if (clcf->sendfile_max_chunk
- && (off_t) clcf->sendfile_max_chunk < limit)
- {
- limit = clcf->sendfile_max_chunk;
- }
- }
上面代码的逻辑是:如果配置文件设置了限速(limit_rate是速度值,size_t类型,0表示不限速)
- 当c->sent<clcf->limit_rate_after时,说明还没有到需要限速的阈值,计算limit值大于0(下一次应该传输位置偏移量),不必限速
- 当c->sent>clcf->limit_rate_after时,需要控制限速,分两种情况:
- r->limit_rate * (ngx_time() – r->start_sec + 1)>(c->sent – clcf->limit_rate_after) 理论传输量>实际传输量,不必控制(传得慢了)
- r->limit_rate * (ngx_time() – r->start_sec + 1)<(c->sent – clcf->limit_rate_after) 理论传输量<实际传输量,需要设置延时(传得快了)
chain = c->send_chain(c, r->out, limit);
通过上面的c->send_chain函数异步发送数据,nginx在处理完上面send_chain函数后做了延时的微调,倘若进行到下面的程序 之前异步IO使得c->sent增加了,则按照增加量添加延时时间delay,因为一般情况这段时间c->sent应该不会来得及改变的。所 以如果异步IO改变了数据传输量,也应该及时做速度限制的调整,看得出来nginx对这些细节上的处理非常仔细啊,保证一个准确度。
- if (r->limit_rate) {
- nsent = c->sent;
- if (clcf->limit_rate_after) {
- sent -= clcf->limit_rate_after;
- if (sent < 0) {
- sent = 0;
- }
- nsent -= clcf->limit_rate_after;
- if (nsent < 0) {
- nsent = 0;
- }
- }
- delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
- if (delay > 0) {
- limit = 0;
- c->write->delayed = 1;
- ngx_add_timer(c->write, delay);
- }
- }
接下来nginx还做了点延时的微调,不过这个是涉及到sendfile_max_chunk指令,而不是limit_rate指令的,所以不做分析。
- if (limit
- && c->write->ready
- && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
- {
- c->write->delayed = 1;
- ngx_add_timer(c->write, 1);
- }
总之,可以看出nginx是通过使用ngx_add_timer函数实现对write event的控制,进而实现速度上限的控制。
题外话:nginx对于速度的限制不止是通过limit_rate设置阈值,在upstream模块中通过获取上游服 务器返回的响应头headers[“X-Accel-Limit-Rate”]的值也可来动态调整limit_rate的具体数值,这个可以用来实现变化 的速度控制。
热门文章推荐
- [nginx]使用nginx搭建rtmp流媒体服务器环境
- [nginx]HTTP服务器Nginx.conf配置文件介绍与调试
- [Nginx]windows下设置Nginx随机子开机自动启动运行的方法
- [nginx]NGINX的rtmp流媒体插件
- [nginx]Nginx下限速限制下载速度实例
- [nginx]nginx-rtmp-module使用实现rtmp
- [nginx]做防盗链的教程:Apache和Nginx防盗链的几种配置方法
- [nginx]Windows环境的Nginx启动与重启操作