nginx老是work connection not enough怎么读,怎么解决

nginx老是work connection not enough,怎么解决
韩晓柒1660
尝试调整一下 Nginx.conf 配置如:error_log logs/error.#error_log logs/error.#error_log logs/error.worker_rlimit_nofile 65535;pid logs/nginx.events {worker_connections 65535;}
为您推荐:
其他类似问题
扫描下载二维码nginx+nodejs搭配出现的问题【已解决】 - CNode技术社区
这家伙很懒,什么个性签名都没有留下。
最近监控发现nginx+nodejs做的webservice接口有些失败率,查看nginx日志发现了问题,但不知道原因特来求解
两地机房A和B,每地都是4台机器,nginx里upstream配的
upstream nodejs{
server 192.168.10.100:8888;
server 192.168.10.101:8888
server 192.168.10.102:8888
server 192.168.10.103:8888
都是连本机的node,同机房的其他3台作为backup
查看了一天的日志,A、B两个机房的机器每天都是60多w条请求记录,但是现在A机房的机器没有错误,而B机房的机器,每台都差不多有500条左右no live upstreams while connecting to upstream的错误。
按照我的理解,这个错误应该是upstream里的4台node都连不上?但感觉这个不太可能啊。。。两地的配置都一样,为什么就B机房有这种情况
现在没有什么解决的头绪。。。不知道有谁也遇到过这种情况
找到原因了,是因为node的http server不支持url中有空格的(未编码),这种请求进来,对于nginx来说,就是后端的node不可用,而上面的upstream没有配max_fails,一次就被标记为失败了,这个时候后面跟着的同一nginx进程上的请求就会no live upstreams~
从错误日志也可以看出,每次no live upstreams while connecting to upstream错误都是紧跟在4条upstream prematurely closed connection while reading response header from upstream错误后的,而后者这个错误都是由于url里有未编码的空格引起的,解决办法就是调大max_fails,调低fail_timeout,不过这个方法不彻底。。。最好是别用http建server,用net,虽然这个问题是因为url不规范,但是没法限制用户要这么传,而且即使不规范也不能造成问题。。。
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的一个和worker_connections参数相关的Nginx系统问题及解决办法 - 窗厦的天空 - ITeye技术网站
1. 问题现象
nginx运行过程中,发现无法访问nginx(导致nagios监控告警) ,且error日志中一直报如下错误
16:31:07 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:07 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:07 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:07 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:07 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:08 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:08 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:08 [alert] 24 worker_connections is not enough while accepting new connection on
16:31:08 [alert] 24 worker_connections is not enough while accepting new connection on
2.初步原因分析
目前nginx 中worker_connections 值设置是1024,worker_processes 值设置是4,按反向代理模式下最大连接数的理论计算公式:
最大连接数 = worker_processes * worker_connections/4
算出目前每台nginx理论上只支持1024个。但观察NGINX 历史性能数据,发现活动连接数经常是大于1024,并且最高达到5000左右,因而有时会导致连接数不够,直到NGINX无法再处理新的连接请求。
3.解决办法
查看相关资料,生产环境中worker_connections 建议值最好超过9000,计划将一台nginx 设置为10240,再观察一段时间。
浏览: 18437 次
我测试的 使用redis sharding后rps性能减低为了 ...nginx源码分析(13)
& & & & 上一篇文章分析了nginx是如何管理监听事件,并把监听事件注册到epoll事件管理器中。接下来在这基础上分析当有客户端连接请求到来时,nginx是如何与客户端建立tcp连接,以及连接建立后又是如何管理超时事件。
一、连接事件管理
& & & & 在函数ngx_event_process_init中,会设置读事件的回调为ngx_event_accept。 这样设置后,在nginx服务器监听到来自客户端的连接请求后,该回调会被触发,用来与客户端建立tcp连接。连接建立后,就可以正常与客户端进行数据交互。
//ngx_event_core_module模块的init_process方法。在函数ngx_worker_process_init中被调用
static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
//对于每一个监听端口,从连接池中取出一个连接对象(也将从读时间,写事件池取出对象,
//使得连接,读、写保持一一对应关系),负责监听来自客户端的连接
ls = cycle-&listening.
for (i = 0; i & cycle-&listening. i++)
c = ngx_get_connection(ls[i].fd, cycle-&log);
c-&listening = &ls[i];
ls[i].connection =
//设置连接回调,当有客户端连接时,将触发回调
rev-&handler = ngx_event_
//如果work进程之间没有使用枷锁,则把读事件加入epoll中
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR)
return NGX_ERROR;
& & & & ngx_event_accept用来接收来自客户端的连接请求。tcp建立后,从连接池中获取一个新连接对象(同时获取到读、写事件), 并把读事件加入到epoll中。这个新连接对象与监听对象作用是不同的。 监听对象注意用来监听来自客户端的连接,是还没有与客户端建立连接前被调用。而这个新连接对象是在tcp连接后被调用,用来与客户端进行数据读写。
//客户端请求连接回调
void ngx_event_accept(ngx_event_t *ev)
//接收客户端连接
s = accept(lc-&fd, (struct sockaddr *) sa, &socklen);
//work进程之间赋值均衡,但一个work进程超过每一个进程的最大连接数的7/8时,
//则该work进程不在监听来自客户端的连接请求。但已经建立tcp连接的客户端不收影响,正常进行数据读写
ngx_accept_disabled = ngx_cycle-&connection_n / 8
- ngx_cycle-&free_connection_n;
//获取一个空闲连接对象(同时也获取到读,写事件)
c = ngx_get_connection(s, ev-&log);
//给新连接对象赋值
c-&pool = ngx_create_pool(ls-&pool_size, ev-&log);
c-&sockaddr = ngx_palloc(c-&pool, socklen);
ngx_memcpy(c-&sockaddr, sa, socklen);
//设置从内核读取数据,写入数据的的方法。这些方法实际上就是ngx_os_io结构的各个成员
c-&recv = ngx_
c-&send = ngx_
c-&recv_chain = ngx_recv_
c-&send_chain = ngx_send_
c-&listening =
//调用监听对象的方法
ls-&handler(c);
//ngx_http_init_connection
} while (ev-&available);
& & & & 在函数中会调用ngx_listening_s对象的handler方法。这个方法其实就是ngx_http_init_connection,在ngx_http_add_listening函数中设置。
ngx_http_init_listening
& &---&&ngx_http_add_listening
& & & & & &---&
//创建一个ngx_listening_t对象,并给对象的成员赋值。例如设置监听回调
ngx_listening_t * ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
//创建一个ngx_listening_t对象
ls = ngx_create_listening(cf, &addr-&opt.u.sockaddr, addr-&opt.socklen);
//监听回调
ls-&handler = ngx_http_init_
}& & & & ngx_http_init_connection是用来为新建立的客户端连接注册读事件回调ngx_http_init_request、写事件回调ngx_http_empty_handler、同时将注册读事件的超时事件到红黑树实现的定时器中。最终将读事件放入到epoll中。这些操作执行之后,就可以接收来自客户端的数据了。
//在收到客户端连接时,ngx_event_accept函数中会调用ngx_listening_t的handler,也就是本函数
//功能:注册客户端的读写事件回调
void ngx_http_init_connection(ngx_connection_t *c)
//读事件回调
rev-&handler = ngx_http_init_
//该写回调没有做任何事件,因为这个阶段还不需要向客户端写入任何数据
c-&write-&handler = ngx_http_empty_
//将读事件插入到红黑树中,用于管理超时事件,post_accept_timeout超时事件
//为nginx.conf中的client_header_timeout选项
ngx_add_timer(rev, c-&listening-&post_accept_timeout);
//将读事件注册到epoll中
ngx_handle_read_event(rev, 0);
}& & & & nginx服务器处理完客户端的连接请求后,又回到了work进程的事件循环中。监听新建立的对象,等待客户端发来的数据,与客户端进行数据交互。
//work进程的事件循环
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
for ( ;; )
ngx_process_events_and_timers(cycle);
二、超时事件管理
& & & & nginx服务器在监听到来自客户端的连接请求后,会与客户端建立一个tcp连接,并为这个新连接注册读写事件,并将读事件的超时事件加入到红黑树实现的定时器中。
从上面的ngx_http_init_connection函数中就可以看出这些操作,并把读事件添加到了红黑树实现的定时器中。
//在收到客户端连接时,ngx_event_accept函数中会调用ngx_listening_t的handler,也就是本函数
//功能:注册客户端的读写事件回调
void ngx_http_init_connection(ngx_connection_t *c)
//读事件回调
rev-&handler = ngx_http_init_
//该写回调没有做任何事件,因为这个阶段还不需要向客户端写入任何数据
c-&write-&handler = ngx_http_empty_
//将读事件插入到红黑树中,用于管理超时事件,post_accept_timeout超时事件
//为nginx.conf中的client_header_timeout选项
ngx_add_timer(rev, c-&listening-&post_accept_timeout);
//将读事件注册到epoll中
ngx_handle_read_event(rev, 0);
& & & & ngx_event_add_timer负责将事件注册到红黑树实现的定时器中。红黑树中的所有超时事件节点都是通过ngx_event_s对象的timer成员给串接起来。而定时器中每一个超时事件节点的key就是超时时间,记录该事件的超时时间。
//将定时事件添加到红黑树中,timer为超时时间
static ngx_inline void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
ngx_msec_int_
key = ngx_current_msec +
//已经将事件插入到红黑树种,则先删除之前的事件
if (ev-&timer_set)
ngx_del_timer(ev);
//设置定时器的唯一id,也就是时间
ev-&timer.key =
//插入到红黑树种
ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev-&timer);
//表示事件已经存在红黑树中了
ev-&timer_set = 1;
& & & & 将读事件加入到红黑树定时器后,接下来work进程进入事件循环,阻塞在epoll_wait调用。那epoll_wait什么时候返回呢? 在接收到客户端的数据后,或者每个事件的定时时间到后,可以从epoll_wait返回。接下来看下如何设置epoll_wait的超时时间,使得定时时间到后,能及时从epoll_wait返回。
//work进程事件循环
void ngx_process_events_and_timers(ngx_cycle_t *cycle)
//在红黑树中查找所有事件的最小超时事件,返回值timer就是所有事件的最小超时时间
timer = ngx_event_find_timer();
//调用epoll_wait等待事件
(void) ngx_process_events(cycle, timer, flags);
//epoll_wait返回后,处理所有超时事件
ngx_event_expire_timers();
& & & & 红黑树是一颗二叉排序树,因此最小超时时间实际上就是左子树的最小值。因此可以看到ngx_event_find_timer函数的实现,就是在左子树种查找最小值。如不清楚红黑树的实现,则可以查看july大神的博客
//返回红黑树中最小事件的超时事件;
//返回值:&0 表示还剩多长事件超时
&=0 表示事件已经超时
ngx_msec_t ngx_event_find_timer(void)
ngx_msec_int_
ngx_rbtree_node_t
*node, *root, *
//红黑树为空,则返回-1表示事件已经超时
if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel)
return NGX_TIMER_INFINITE;
root = ngx_event_timer_rbtree.
sentinel = ngx_event_timer_rbtree.
//查找左字数
node = ngx_rbtree_min(root, sentinel);
//计算剩余超时时间
timer = (ngx_msec_int_t) node-&key - (ngx_msec_int_t) ngx_current_
return (ngx_msec_t) (timer & 0 ? timer : 0);
& & & & 而epoll_wait调用返回后,如果有事件超时了,那如何处理这些超时事件呢?ngx_event_expire_timers内部会遍历红黑树,查找所有已经超时的事件,并调用这些超时事件的处理回调。与此同时也会从红黑树中删除这个超时事件,如果还需要管理这个超时事件,则需要重新加入到红黑树中。
//调用红黑树中所有已经超时的事件回调,并把已经超时的事件从红黑树中删除
void ngx_event_expire_timers(void)
ngx_event_t
ngx_rbtree_node_t
*node, *root, *
sentinel = ngx_event_timer_rbtree.
//遍历红黑树,查找超时事件
for ( ;; )
root = ngx_event_timer_rbtree.
//红黑树为空则返回
if (root == sentinel)
//取出红黑树中时间最小的节点
node = ngx_rbtree_min(root, sentinel);
/* node-&key &= ngx_current_time */
//发生超时
if ((ngx_msec_int_t) node-&key - (ngx_msec_int_t) ngx_current_msec &= 0)
ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
//从红黑树中删除这个已经超时的定时器事件
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev-&timer);
//表示事件已经不存在定时器中了
ev-&timer_set = 0;
//标示事件已经超时
ev-&timedout = 1;
//调用事件回调
ev-&handler(ev);
//直接处理下一个超时事件,前一个超时事件已经从红黑树中删除了
//没有事件超时则直接退出,因此最小时间都没有超时,那红黑树中其它时间也肯定没有超时
& & & & 到此,超时事件的管理也分析完成了。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:23451次
排名:千里之外
原创:44篇
文章:14篇
阅读:5236
文章:26篇
阅读:15937
(7)(7)(1)(1)(1)(25)(1)(1)

我要回帖

更多关于 nginx connection 的文章

 

随机推荐