pika连接AMQPS报IncompatibleProtocolError错误解决方法
pika连接AMQPS服务报SSLEOF/协议不兼容错误解决方案
问题复现
尝试使用pika连接AMQPS服务,无服务端配置权限、无法获取服务端证书,初始实现代码如下:
import pika from urllib.parse import urlparse import ssl credentials = pika.PlainCredentials(username, password) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.verify_mode = ssl.CERT_NONE ssl_options=pika.SSLOptions(context) params = pika.ConnectionParameters( host=url.hostname, port=url.port, credentials=credentials, ssl_options=ssl_options ) connection = pika.BlockingConnection(params) channel = connection.channel() # start a channel
执行后抛出如下错误:
ERROR:pika.adapters.utils.connection_workflow:AMQPConnector - reporting failure: AMQPConnectorAMQPHandshakeError: IncompatibleProtocolError: The protocol returned by the server is not supported: ('StreamLostError: ("Stream connection lost: SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:2633)')",)',)
相同账号、地址下,设置sasl_enabled=True的qpid-proton库可正常连接,参考代码如下:
from proton import Message from proton.utils import BlockingConnection conn = BlockingConnection( url, password=password, user=username, sasl_enabled=True, )
解决步骤
第一步:修正SSL与SASL配置(适用于服务端支持AMQP 0-9-1的场景)
原代码的核心配置问题有三点:
- 硬编码强制使用TLSv1.2,若服务端仅支持TLS1.3或配置了自动协商TLS版本,握手阶段会被直接断开
- 未显式开启SSL开关,部分低版本pika无法仅通过
ssl_options自动识别SSL连接,会以明文发送AMQP协议头被服务端拒绝 - 未显式指定SASL协商机制列表,默认配置无法对齐qpid-proton开启
sasl_enabled后的自动协商行为,会被要求SASL认证的服务端断开 - 使用
PROTOCOL_TLS_CLIENT上下文时默认开启主机名校验,无服务端证书的场景下必须手动关闭
修正后的可运行代码如下:
import pika from urllib.parse import urlparse import ssl # 先解析AMQPS连接串 url = urlparse("替换为你的实际amqps连接地址") credentials = pika.PlainCredentials(username, password) # 使用自动协商版本的TLS客户端上下文,不要硬编码TLS版本 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) # 关闭证书与主机名校验(适配无服务端证书的场景) context.check_hostname = False context.verify_mode = ssl.CERT_NONE ssl_options = pika.SSLOptions(context) params = pika.ConnectionParameters( host=url.hostname, port=url.port, credentials=credentials, ssl_options=ssl_options, ssl=True, # 显式开启SSL连接,规避版本兼容问题 # 显式声明支持的SASL机制,自动协商匹配服务端要求的认证方式 auth_mechanisms=['PLAIN', 'AMQPLAIN', 'ANONYMOUS', 'EXTERNAL'] ) connection = pika.BlockingConnection(params) channel = connection.channel()
第二步:确认服务端AMQP协议版本(配置修正后仍报错的场景)
如果按上述配置修改后仍然抛出IncompatibleProtocolError,属于协议层不兼容问题:
pika从设计上仅支持AMQP 0-9-1协议,主要适配RabbitMQ这类实现0-9-1版本的消息中间件qpid-proton是AMQP 1.0协议的客户端实现,如果服务端仅支持AMQP 1.0(常见于ActiveMQ Artemis、Qpid Broker、云厂商托管事件服务等),pika没有任何配置可以实现兼容,直接使用qpid-proton作为客户端即可,没有必要强行适配pika。
内容的提问来源于stack exchange,提问作者stiller_leser
相关产品推荐
相关产品推荐

