Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

worker线程全部卡住时主动拒绝请求 #452

Open
jamesge opened this issue Aug 16, 2018 · 7 comments
Open

worker线程全部卡住时主动拒绝请求 #452

jamesge opened this issue Aug 16, 2018 · 7 comments
Labels
enhancement improvements on existing features official created by brpc authors

Comments

@jamesge
Copy link
Contributor

jamesge commented Aug 16, 2018

最简单的“卡住”方式就是usleep或sleep(但不是bthread_usleep,并不会卡住worker)。当所有的worker都陷入sleep时,EventDispatcher也不会工作,直到某个worker醒来,相应的请求会被延迟,但server端无法感知到这点,因为请求处理的“起点”就是EventDispatcher中的epoll,它同样被延迟了。可能的改进有:

  1. 让EventDispatcher运行在独立的pthread中,就像TimerThread那样,可能会略微降低新请求的调度。这个改进的问题在于brpc中的epoll和读取在不同的线程,epoll一次醒来后只要连接中有数据,读取线程就会持续读,这可能会导致epoll醒来的时间明显早于请求到达的时间,使延时计算不准确。
  2. 当发现worker不足时自动增加worker。百度内的分支做过类似的改动。但这和不支持动态创建tls的server会有冲突。新增的worker中的tls可能为空导致应用错误。
  3. 在bthread层面能汇报worker是否用满,brpc中发现用满也返回ELIMIT。比较倾向于这个方式,这个机制还能统一usercode_in_pthread模式中的一些代码。
@jamesge jamesge added the official created by brpc authors label Aug 16, 2018
@yitian134
Copy link

发表下个人的一些小见解。
worker是否用满感觉是个不好界定的事情。worker刚满可能说明利用效率较高,实际上QPS很高的时候应该就是这种情况。从用户角度可能希望避免的情况是 worker满了但堆积越来越严重。所以,建议大佬们把ELIMIT的条件放宽些,因为生产环境下,请求稍微等待久些 比 返回大量ELIMIT要好

@jamesge
Copy link
Contributor Author

jamesge commented Aug 21, 2018

  1. worker全部卡住可能使并发控制失效,这和让并发控制的上限高一点是两码事。这里关注的是正确性问题。你关注的“放宽些”可以在严格的并发参数上乘上对应的放大系数即可。
  2. worker满可能也意味着用户代码中存在大量待改进的(非bthread的)阻塞操作。
  3. 当服务的qps打满时,排队与等待是没有意义的。既会让后续的请求都陷入排队,可能也不如花上1ms重试到另一台机器上。ELIMIT是针对单机的,集群层面不应该拒绝流量。

@yitian134
Copy link

yitian134 commented Aug 21, 2018

了解了。其实我的疑问主要在第三点,上面说的“放宽些”也是指排队。
感觉有适量排队也正是高性能的一部分,不然worker就出现有空闲的情况。是否理解正确,望指教

@jamesge
Copy link
Contributor Author

jamesge commented Aug 21, 2018

是。这是因为并发的物理含义就是能缓存下任务的槽位,worker之外还有很多不可控的“槽位”,如socket中的缓冲,框架里常见的分发队列,甚至广义地说,任何和任务分发相关的容器都负担了若干并发。所以如果只是按worker数来计算并发就少算了,一般会加上额外的部分。
具体并发是通过“极限qps”乘以“低负载时的延时”来计算的,极限qps是可以精确测量的,但是延时的起点和末尾是不可能覆盖所有的部分的,比如收到epoll通知之前的开销,写入socket之后的延时。测量到的延时会低于真实延时,从这个角度看计算并发也要加上额外的部分。

@Redfriday
Copy link

最近看代码一直有这个疑问,之前一直觉得可能EventDispatcher是在单独的pthread里,看后面才发现是在某个worker的bthread 环境里,而bthread又不会主动yield和基于时间片调度,这样在worker忙的时候新请求会得不到调度。为什么“让EventDispatcher运行在独立的pthread中,就像TimerThread那样,可能会略微降低新请求的调度。”

@jamesge
Copy link
Contributor Author

jamesge commented Aug 22, 2018

@Redfriday 即使把EventDispatcher放独立的pthread,worker全满时新bthread不还是调度不了么?

@jamesge jamesge added the enhancement improvements on existing features label Sep 27, 2018
@cdjingit
Copy link
Contributor

@jamesge 关于”bthread层面汇报work是否用满”,具体统计哪些信息?比如 bthread在run_queue中的排队时间?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement improvements on existing features official created by brpc authors
Projects
None yet
Development

No branches or pull requests

4 participants