错误代码
了解bRPC客户端的错误代码。
brpc使用brpc::控制器设置和获取一个RPC的参数。控制器::错误代码()
和控制器::ErrorText()
分别返回RPC的错误代码和描述,只有在RPC完成后才能访问,否则结果是未定义的。错误文本()
由Controller的基类定义:谷歌::protobuf::RpcController
,同时错误代码()
由定义brpc::控制器
。控制器也有一个方法失败()
来判断RPC是否失败。三种方法之间的关系:
- 什么时候?
失败()
是真的,错误代码()
必须为非零且错误文本()
非空。 - 什么时候?
失败()
为假,错误代码()
为0并且错误文本()
未定义(目前在brpc中为空,但您最好不要依赖它)
将RPC标记为失败
brpc中的客户端和服务器都有控制器
,可以用设置设置失败()
修改ErrorCode和ErrorText。多次呼叫控制器::设置失败
保留最后一个错误代码并连接ErrorTexts而不是离开最后一个。该框架通过添加额外的前缀来详细说明ErrorTexts:客户端的重试次数和服务器端的服务器地址。
控制器::SetFailed()
at client通常由框架调用,如发送失败、响应不完整等。在某些情况下,客户端可能会设置错误。例如,如果发送请求之前的附加检查失败,您可能会将错误设置为RPC。
控制器::SetFailed()
在服务器端,通常由用户在服务回调中调用。一般来说,当发生错误时,用户会调用设置失败()
,释放所有资源,然后从回调返回。框架根据通信协议将错误代码和消息填充到响应中。当收到响应时,内部错误被设置到客户端控制器中,以便用户可以在RPC结束后获取它们。请注意默认情况下,服务器不会将错误打印到客户端,因为频繁的日志记录可能会由于磁盘IO过大而严重影响服务器的性能。客户端疯狂地产生错误可能会降低整个服务器的速度,并影响所有其他客户端,甚至可能成为对服务器的攻击方法。如果您真的想看到服务器上的错误消息,请打开gflag-日志错误文本(可在运行时修改),服务器将记录每个失败RPC的相应控制器的ErrorText。
brpc中的错误代码
brpc中的所有错误代码都定义于错误号原型,其中以系统_由linux系统定义,与中定义的完全相同/usr/include/errno。小时
.我们把它放在.proto中的原因是为了跨语言。其余错误代码由brpc定义。
berror(错误代码)获取错误代码的描述,以及berror()
获取当前的描述系统错误号。请注意错误文本()!=berror(错误代码())自从错误文本()
包含更具体的信息。brpc默认包含berror,因此您可以在项目中直接使用它。
下表显示了常见错误代码及其说明:
错误代码 | 价值 | 重试 | 描述 | 日志记录消息 |
---|
EAGAIN公司 | 11 | 是的 | 同时请求太多,几乎不会发生,因为这是一个软限制。 | 资源暂时不可用 |
ENODATA公司 | 61 | 是 | 1.命名服务返回的服务器列表为空。2.当命名服务在所有实例都已修改的情况下发生更改时,命名服务会先删除所有实例,然后再添加所有实例来更新LB,LB实例列表可能会在短时间内变空。 | 无法从xxx中选择服务器 |
ETIMEDOUT公司 | 110 | 是的 | 连接超时。 | 连接超时 |
EHOSTDOWN公司 | 112 | 是的 | 可能的原因:A.命名服务器返回的列表不为空,但LB无法选择可用的服务器,并且LB返回EHOSTDOWN错误。可能的具体原因:a.服务器正在退出(返回ELOGOFF)b.服务器由于以前的一些故障而被阻止,块的特定逻辑:1。对于单连接类型,唯一的连接套接字被SetFail阻塞,触发此块的代码中多次出现SetFailed。2.对于池/短连接类型,只有当错误号满足does_error_affect_main_socket(ECONREFUSED、ENETUNREACH、EHOSTUNREACH或EINVAL)时,它才会被阻止3。阻塞后,有一个CheckHealth线程进行健康检查,Just try to connect,检查间隔由SocketOptions的health_check_interval_s控制,如果连接成功,Socket将被解锁。B.使用SingleServer方法初始化Channel(不带LB),唯一的连接是LOGOFF或blocked(同上) | “无法从…中选择服务器”“尚未连接到…” |
环境服务 | 1001 | 不 | 找不到服务,很少发生,通常是ENOMETHOD | |
ENOMETHOD公司 | 1002 | 不 | 找不到方法。 | 其他表单,常见的是“找不到方法=…” |
埃雷奎斯特 | 1003 | 不 | 无法序列化请求,可以在客户端或服务器端设置 | 杂项表单:“请求中缺少必填字段:…”“无法分析请求消息,…”“错误请求” |
EAUTH公司 | 1004 | 不 | 身份验证失败 | “身份验证失败” |
埃托曼费 | 1005 | 不 | ParallelChannel内部的子通道故障过多 | “%d/%d通道失败,fail_limit=%d” |
EBACKUPREQUEST(电子回执请求) | 1007 | 是的 | 触发备份请求时设置。ErrorCode()未直接返回,可从/rpcz中的跨度查看 | “达到备份超时=%dms” |
ERPC超时 | 1008 | 不 | RPC超时。 | “达到超时=%dms” |
EFAILED插座 | 1009 | 是的 | RPC期间连接断开 | “套接字设置失败” |
EHTTP公司 | 1010 | 不 | 具有非2xx状态代码的HTTP响应被视为失败,并使用此代码进行设置。默认情况下不重试,可通过自定义RetryPolicy进行更改。 | 错误的http调用 |
人满为患 | 1011 | 是的 | 要在发送方缓冲的消息太多。通常是由大量并发异步请求引起的。可由修改-socket_max_unwitten_bytes(套接字_最大_未编写_字节) 默认为8MB。 | 服务器过度拥挤 |
EINTERNAL公司 | 2001 | 不 | 的默认错误控制器::设置失败 没有指定一个。 | 内部服务器错误 |
ERESPONSE公司 | 2002 | 不 | 无法序列化响应,可以在客户端或服务器端设置 | 其他表单:“响应中缺少必填字段:…”“解析响应消息失败”,“响应错误” |
ELOGOFF公司 | 2003 | 是的 | 服务器已停止 | “服务器将退出” |
ELIMIT公司 | 2004 | 是的 | 并发处理的请求数超过服务器选项最大货币 | “已达到服务器的并发请求限制=%d” |
用户定义的错误代码
在C/C++中,可以在宏、常量或枚举中定义错误代码:
#定义ESTOP-114//信用证++静止的 常数 整数 EMYERROR公司 = 30; //信用证++常数 整数 EMYERROR2公司 = -31; //仅限于C++
如果需要完成错误描述贝罗
,通过以下方式将其注册到c/cpp文件的全局作用域中BAIDU_REGISTER_ERRNO(错误代码,描述)
,例如:
BAIDU _寄存器_ RRNO(ESTOP公司, “线程正在停止”)
BAIDU _寄存器_ RRNO(EMYERROR公司, “我的错误”)
请注意斯特雷罗
和strerror或r
无法识别由定义的错误代码BAIDU _寄存器_ RRNO
。也没有%米
在中使用打印
。您必须使用%秒
与…配对贝罗
:
错误编号 = ESTOP公司;
打印(“描述错误号:%m\n个"); //[错误]描述错误号:未知错误-114打印(“描述错误号:%s\n个", strerror或r(错误编号, 无效的, 0)); //[错误]描述错误号:未知错误-114打印(“描述错误号:%s\n个", 贝罗()); //[正确]描述错误号:线程正在停止打印(“描述错误号:%s\n个", 贝罗(错误编号)); //[Correct]描述错误号:线程正在停止
当错误代码的注册重复时,如果在C++中定义链接错误,则会生成链接错误:
重新定义“class BaiduErrnoHelper<30>”
或程序在启动前中止:
无法定义已定义为“只读文件系统”的EMYERROR(30),中止
您必须确保不同的模块对同一错误代码有相同的理解。否则,对错误代码进行不同解释的两个模块之间的交互可能是未定义的。为了防止这种情况发生,你最好遵循以下几点:
- 一般来说,首选具有固定值和含义的系统错误代码。
- 在多个模块之间共享错误定义的代码,以防止修改后出现不一致。
- 使用
BAIDU _寄存器_ RRNO
描述新的错误代码,以确保同一错误代码在进程内只定义一次。