错误代码

了解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公司611.命名服务返回的服务器列表为空。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身份验证失败“身份验证失败”
埃托曼费1005ParallelChannel内部的子通道故障过多“%d/%d通道失败,fail_limit=%d”
EBACKUPREQUEST(电子回执请求)1007是的触发备份请求时设置。ErrorCode()未直接返回,可从/rpcz中的跨度查看“达到备份超时=%dms”
ERPC超时1008RPC超时。“达到超时=%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描述新的错误代码,以确保同一错误代码在进程内只定义一次。

上次修改时间:2024年5月6日更新index.md(66353dc)