V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  NeedI09in  ›  全部回复第 1 页 / 共 2 页
回复总数  23
1  2  
1 天前
回复了 gongxuanzhang 创建的主题 程序员 在一个群里被恶心坏了
@Wesson 哈哈哈,有道理。这个解释很有意思,哈哈哈。
1 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
@doggg 👌
1 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
@doggg 嗯嗯,关于进程泄漏的说法应该是设置比较长,然后卡在 timer 那里。
我还遇到过一种进程泄漏,是 worker 里起了 timer ,然后 timer 是一直递归的,发现 reload 后,worker 一直处于 shutting down 。我加了检测 worker.exiting 进程便不泄漏了,现在看来应该是卡在 ngx_process_events_and_timers 里。
1 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
@doggg 我可能没有表述清楚,我是指在 reload 前进来的请求耗时较长,且`worker_shutdown_timeout `设置较短,这样的话请求就返回报错了。但是这个不影响,还是看实际场景的😂,我是想到了这个例子哈哈。
2 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
问题 1:
从大佬文章介绍出发,先看如何关闭 listen port
发现下列代码
``` c

ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {

#if (NGX_QUIC)
if (ls[i].quic) {
continue;
}
#endif

c = ls[i].connection;

if (c) {
if (c->read->active) {
if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {

/*
* it seems that Linux-2.6.x OpenVZ sends events
* for closed shared listening sockets unless
* the events was explicitly deleted
*/

ngx_del_event(c->read, NGX_READ_EVENT, 0);

} else {
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
}
}

ngx_free_connection(c);

c->fd = (ngx_socket_t) -1;
}

```
cycle->listening.elts 明显存储着监听相关对象
接着全局查询 cycle->listening.elts

https://github.com/nginx/nginx/blob/6f7494081ae8a56664afb480eff583d639b60ab4/src/core/ngx_cycle.c#L505-L620 部分找到代码,这部分应该是处理 listening 数组的一些信号,调用 ngx_open_listening_sockets 开始监听 cycle 中的端口。

那他真的是零停机吗?

从流程上来看是的,ngx_init_cycle 阶段就已经开始监听端口了,在启动新 worker 后,会按照顺序删除用于接受 IO 通知的事件,关闭监听端口,关闭空闲连接,之后 ngx_process_events_and_timers 会保证处理完所有的未完成的请求。

但是这一切都是基于在指定 worker_shutdown_timeout 时间内能够执行完请求的前提下,能够正常处理完请求,所以如果在这段时间内处理不完,或者接口 duration 超过设置超时时间,那这个请求就会来不及处理,就结束了。
所以,worker_shutdown_timeout 设置要贴合实际场景。这个值如果设置非常大,就会有 worker 进程泄露的风险,设置的比较小,就会 reload 期间,存在接口返回报错。

我认为 nginx 已经处理得很好了,在 reload 期间,有些耗时较长的接口会存在一定问题,但是要根据具体场景,去规划这个超时值就可以避免,我认为他是零停机的。
3 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
@NeedI09in 补充一下,如果说的有误,麻烦大佬斧正,我对 nginx 底层源码了解甚少,只是看了这篇文章,尝试了解了一下源码。如果说的有什么不妥的地方,烦请大佬斧正,感谢。
不知道 ngx_close_idle_connections 是否是只 close 客户端的长连接,烦请大佬斧正。
3 天前
回复了 doggg 创建的主题 程序员 理解 Nginx 的优雅退出机制
问题 2:
从小聪明的角度,感觉函数调用名字是 ngx_close_idle_connections ,应该只是关闭 client 和 upstream 的空闲连接。
从源代码角度分析,收到 NGX_RECONFIGURE_SIGNAL 信号后会走到 ngx_reconfigure ,会通过 ngx_start_worker_processes 启动一个新的 worker ,然后 ngx_signal_worker_processes 会处理掉旧 worker 。旧 worker 的处理方式跟大佬文章里写的一样,旧 worker 的 connection 是否还有效,我是从 ngx_close_idle_connections 出发看他是怎么获取的 connection 。发现他是这么取的 connections
``` c
void
ngx_close_idle_connections(ngx_cycle_t *cycle)
{
ngx_uint_t i;
ngx_connection_t *c;

c = cycle->connections;

for (i = 0; i < cycle->connection_n; i++) {

/* THREAD: lock */

if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
}

```


侧面追踪发现 shutdown 超时也会出发关闭连接。大胆猜测 cycle->connections 就是连接池

``` c

static void
ngx_shutdown_timer_handler(ngx_event_t *ev)
{
ngx_uint_t i;
ngx_cycle_t *cycle;
ngx_connection_t *c;

cycle = ev->data;

c = cycle->connections;

for (i = 0; i < cycle->connection_n; i++) {

if (c[i].fd == (ngx_socket_t) -1
|| c[i].read == NULL
|| c[i].read->accept
|| c[i].read->channel
|| c[i].read->resolver)
{
continue;
}

ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
"*%uA shutdown timeout", c[i].number);

c[i].close = 1;
c[i].error = 1;

c[i].read->handler(c[i].read);
}
}
```

那就追踪 cycle ,从 ngx_master_process_cycle 函数追踪到这一行代码
``` c

cycle = ngx_init_cycle(cycle);
if (cycle == NULL) {
cycle = (ngx_cycle_t *) ngx_cycle;
continue;
}

```

显然,如果这里的 ngx_init_cycle 返回是 NULL ,那么长连接就会无效,问题就回到了 ngx_init_cycle 里发生了什么。大胆猜测这个 init_cycle 正常情况返回自己,异常情况返回 Null 。点进去还真是。
所以结论就是非空闲长连接不会释放,cycle 还是老 cycle ,看起来很合理

不知道我推论对不对,烦请大佬解惑。大佬的文章收益匪浅,看完有种会捕鱼了的快乐,非常感谢。
不过想请教大佬 ngx_temp_pool 是做什么用的,为何 ngx_temp_pool 是 Null 会需要清理长连接呢?
也就是这段代码 https://github.com/nginx/nginx/blob/master/src/core/ngx_cycle.c#L778C1-L801C6

最后感谢大佬的输出,受益匪浅。
怎么方便怎么来吧
4 天前
回复了 gongxuanzhang 创建的主题 程序员 在一个群里被恶心坏了
@NeedI09in 补充一下,开发始终是一个百密不如一疏的行业,有人提出疏忽其实是好事,但是阴阳怪气和鄙夷(这点都不知道)这种态度是不对的,“你知道”并不意味着你可以阴阳怪气和鄙夷。
4 天前
回复了 gongxuanzhang 创建的主题 程序员 在一个群里被恶心坏了
首先,mysql 里读是加锁的,读锁和写锁是互斥的,rr 和 rc 之所以读写快是因为用了一致性非锁定读,本质是 mvcc ,通过 undo_log 实现。
rc 和 rr 都加了 mvcc ,但是 rc 有幻读,为了解决这个问题加的 rr 。
幻读解决办法是 rr 隔离级别加的间隙锁 + 一致性非锁定读( mvcc )解决的。
硬要说 rr 隔离级别下也有幻读。因为他不用一致性非锁定读,而用排他锁 for update ,或者共享锁 for share mode 。来读当前数据,确实有道理,但是他只是想显得自己很懂而已,没必要计较,因为你知道有这种特殊情况接纳就行了,当你和他争论,你就陷入了自证陷阱。语气不好就反击,没必要惯着。讨论问题是基于态度端正,而不是谁说话难听,反问句多就有道理。
如果我说的有不对还望各位海涵。
5 天前
回复了 zanelee 创建的主题 程序员 Consul 注册中心问题
你在 consul 侧看了注册上的服务的健康状态是 passing 吗?
可以,我去给你点个🌟
14 天前
回复了 dorm 创建的主题 职场话题 谈职场晋升
@dorm 总结一下楼主的心理,你们懂个鸡毛,学技术只有那点出息,能做管理靠的不是技术,要学会拍马屁、做舔狗。而不是执着技术(因为自己不会,经典诋毁)。
然而管理也做的一坨屎,被属下反驳就要发篇帖子安慰自己技术自卑的心理,又没法反驳下属,只好寻求其他也做管理的认同(技术人员就是不懂人情世故,这也太愚蠢了之类的话),这种自卑感让自己深受折磨,不认可下属的同时,是没有站位思考的能力和派兵遣将的能力,这种管理做起来,还不如不做。
最后说“还有人一直在原地踏步”是体现自己的优越感,表示自己这种“能与上级沟通”是一种软性能力的体现。其实看得出来,你能说出这种话,就说明本身就是狭隘的,处在达克效应无知且无畏的阶段。
做管理又不能好好处理下属的情绪和价值观的冲突,本身不能兼容,那你当什么领导。既不能以能力服众,又不能以德服众,还不知道能不能以钱服众,那手下人跟着你干嘛?跟着你看你会吐槽人,会 pua ?喝西北风?学到知识?
HTTP/1.1 提供了几种限制对象缓存,或限制提供已缓存对象的方式,以维持对象的新鲜度。no-store 首部和 no-cache 首部可以防止缓存提供未经证实的已缓存对象:
Pragma: no-cache
Cache-Control: no-store
Cache-Control: no-cache
标识为 no-store 的响应会禁止缓存对响应进行复制。缓存通常会像非缓存代理服务器一样,向客户端转发一条 no-store 响应,然后删除对象。
标识为 no-cache 的响应实际上是可以存储在本地缓存区中的。只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。这个首部使用 donot-serve-from-cache-without-revalidation 这个名字会更恰当一些。
@NeedI09in 还有 211 之后的部分都在讲这里。
25 天前
回复了 hello826 创建的主题 程序员 nginx 302 转发如何携带原请求的 head
1.通过返回的 Location 字段携带信息,例如 Location: /test?data=1
2.放在客户端 cookie 里
http 协议规范里好像没有与转发请求头相关的,所以用 cookie 比较适合你的方案。
57 天前
回复了 1140601003 创建的主题 程序员 国内有没有 api 网关推荐的呢?
apisix
60 天前
回复了 labilixin 创建的主题 MySQL mysql 数据库与表的字符集设置问题
不同字符集在联表查询时会进行隐式转换。包括 int 和 str
28.88w
1  2  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1062 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 25ms · UTC 22:07 · PVG 06:07 · LAX 15:07 · JFK 18:07
Developed with CodeLauncher
♥ Do have faith in what you're doing.