C++中gRPC与REST服务器共存时TSI_OUT_OF_RESOURCES错误排查
核心根源
gRPC 1.41.1发布于2022年,未适配OpenSSL 3.x系列的API变更与默认安全策略,而OpenSSL 3.x相比1.1.1n做了大量API调整(如废弃部分旧接口、默认禁用弱加密算法),导致gRPC的SSL上下文创建逻辑失败。
排查步骤
1. 版本兼容性验证
gRPC从1.45.0版本开始才正式支持OpenSSL 3.x,1.41.1属于早期版本,对OpenSSL 3.x的新API(如SSL_CTX创建、算法协商逻辑)完全没有适配,这是最直接的原因。
2. 证书与加密套件检查
OpenSSL 3.x默认启用SECLEVEL=2的安全策略,禁用了SHA-1、TLSv1.0/1.1等旧算法:
- 用以下命令检查证书签名算法:
openssl x509 -in server.crt -text -noout | grep "Signature Algorithm" - 检查当前OpenSSL支持的加密套件:
openssl ciphers -v
如果证书使用了SHA-1等被禁用的算法,也会导致SSL上下文创建失败。
3. 编译依赖链路检查
确认gRPC 1.41.1编译时是否正确链接OpenSSL 3.x:
- 检查可执行文件的依赖:
ldd your_server_binary | grep ssl
如果链接的是OpenSSL 1.1.1的库,可能存在依赖冲突;如果是OpenSSL 3.x,说明版本适配问题确实存在。
解决方案
方案1:升级gRPC到兼容版本(推荐)
直接将gRPC升级到1.45.0或更高版本,这些版本已经完成了OpenSSL 3.x的适配。注意同步升级protobuf到3.22.x及以上版本(与gRPC版本匹配),避免跨版本依赖冲突。
方案2:调整OpenSSL 3.x安全策略(临时兼容)
修改OpenSSL全局配置文件(通常为/etc/ssl/openssl.cnf),降低安全级别以兼容旧版gRPC:
[default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.2 CipherString = DEFAULT:@SECLEVEL=1
修改后重启服务,gRPC即可创建SSL上下文。此方案适合无法立即升级gRPC的场景,但会降低整体安全级别。
方案3:回退到OpenSSL 1.1.1n(短期过渡)
如果暂时无法升级gRPC,可继续使用OpenSSL 1.1.1n(注意该版本2025年9月停止安全支持),保持依赖环境与之前的正常状态一致。
方案4:手动修改gRPC源码适配(不推荐)
针对gRPC 1.41.1的SSL模块源码(如src/core/lib/security/transport/ssl_transport_security.cc),修改OpenSSL API调用逻辑:
- 替换已废弃的
SSL_CTX_new为SSL_CTX_new_with_method - 适配OpenSSL 3.x的错误码处理逻辑
此方案维护成本极高,且容易引入新的稳定性问题,仅适合必须保留旧版gRPC的极端场景。
内容的提问来源于stack exchange,提问作者NoClueHowToCode

