Files
apache--brpc/docs/cn/bthread_id.md
T
2026-07-13 13:29:29 +08:00

37 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
bthread_id是一个特殊的同步结构,它可以互斥RPC过程中的不同环节,也可以O(1)时间内找到RPC上下文(即Controller)。注意,这里我们谈论的是bthread_id_t,不是bthread_tbthread的tid),这个名字起的确实不太好,容易混淆。
具体来说,bthread_id解决的问题有:
- 在发送RPC过程中response回来了,处理response的代码和发送代码产生竞争。
- 设置timer后很快触发了,超时处理代码和发送代码产生竞争。
- 重试产生的多个response同时回来产生的竞争。
- 通过correlation_id在O(1)时间内找到对应的RPC上下文,而无需建立从correlation_id到RPC上下文的全局哈希表。
- 取消RPC。
上文提到的bug在其他rpc框架中广泛存在,下面我们来看下brpc是如何通过bthread_id解决这些问题的。
bthread_id包括两部分,一个是用户可见的64位id,另一个是对应的不可见的bthread::Id结构体。用户接口都是操作id的。从id映射到结构体的方式和brpc中的[其他结构](memory_management.md)类似:32位是内存池的位移,32位是version。前者O(1)时间定位,后者防止ABA问题。
bthread_id的接口不太简洁,有不少API:
- create
- lock
- unlock
- unlock_and_destroy
- join
- error
这么多接口是为了满足不同的使用流程。
- 发送request的流程:bthread_id_create -> bthread_id_lock -> ... register timer and send RPC ... -> bthread_id_unlock
- 接收response的流程:bthread_id_lock -> ..process response -> bthread_id_unlock_and_destroy
- 异常处理流程:timeout/socket fail -> bthread_id_error -> 执行on_error回调(这里会加锁),分两种情况
- 请求重试/backup request 重新register timer and send RPC -> bthread_id_unlock
- 无法重试,最终失败:bthread_id_unlock_and_destroy
- 同步等待RPC结束:bthread_id_join
为了减少等待,bthread_id做了一些优化的机制:
- error发生的时候,如果bthread_id已经被锁住,会把error信息放到一个pending queue中,bthread_id_error函数立即返回。当bthread_id_unlock的时候,如果pending queue里面有任务就取出来执行。
- RPC结束的时候,如果存在用户回调,先执行一个bthread_id_about_to_destroy,让正在等待的bthread_id_lock操作立即失败,再执行用户回调(这个可能耗时较长,不可控),最后再执行bthread_id_unlock_and_destroy