使用Gremlin.Net(V3.3.2)连接Azure Cosmos DB遇WebSocket异常求助
Gremlin.Net 3.3.2连接Azure Cosmos DB报错的原因与解决办法
我使用Gremlin.Net(版本3.3.2)编写了连接Azure Cosmos DB的示例代码,在执行
task.Wait()时收到错误:WebSocketException: The server returned status code '200' when status code '101' was expected。相同代码在Amazon Neptune中可正常运行,请问故障原因是什么?
相关代码片段:
var gremlinServer = new GremlinServer(hostname, port, enableSsl: true, username: "/dbs/" + database + "/colls/" + collection, password: authKey); using (var gremlinClient = new GremlinClient(gremlinServer)) { // 执行查询的代码,最终调用task.Wait()时出错 }
故障核心原因
这个问题本质是Azure Cosmos DB的Gremlin端点与Gremlin.Net 3.3.2版本的WebSocket握手逻辑不兼容:
- Amazon Neptune完全遵循Apache TinkerPop的标准WebSocket规范,握手阶段会返回
101 Switching Protocols状态码,这正是Gremlin.Net客户端预期的响应。 - 但Azure Cosmos DB的Gremlin端点在握手时会先返回
200 OK,再完成协议切换。而Gremlin.Net 3.3.2版本的WebSocket连接器会严格检查握手响应状态码,一旦不是101就直接抛出异常,这就导致了你看到的错误。
可行的解决方案
1. 优先升级Gremlin.Net版本
最省心的办法是把Gremlin.Net从3.3.2升级到3.4.0及以上版本。从这个版本开始,官方已经针对Azure Cosmos DB的特殊握手逻辑做了适配,客户端会自动处理200状态码的情况,不用改任何业务代码就能正常连接。
2. 无法升级时的手动适配
如果因为项目依赖限制不能升级版本,可以自定义一个WebSocket连接器,绕过默认的状态码检查:
public class CosmosDbCompatibleWebSocketConnector : WebSocketConnector { protected override async Task<WebSocket> ConnectAsync(Uri uri, CancellationToken cancellationToken) { // 先发送HTTP请求触发Cosmos DB的握手前置响应,忽略状态码检查 using var httpClient = new HttpClient(); await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead, cancellationToken); // 再发起标准的WebSocket连接 return await WebSocket.ConnectAsync(uri, cancellationToken); } }
然后在初始化GremlinClient时指定这个自定义连接器:
var gremlinClient = new GremlinClient( gremlinServer, new GraphSON2Reader(), new GraphSON2Writer(), new CosmosDbCompatibleWebSocketConnector());
这样就能绕过3.3.2版本的状态码校验,成功建立连接。
内容的提问来源于stack exchange,提问作者Rick JN
相关产品推荐
相关产品推荐

