1.对于sse请求的网关转发配置
annotations:
higress.io/load-balance: "mcp-sse"
增加sse会话粘性,它确保的是同一个SSE会话 的请求,而不是同一个IP的请求,始终落到最初创建该会话的后端实例 上,当第一次请求的时候,将 Pod-A 的地址(如IP和端口)进行Base64编码 ,然后将这个编码后的字符串作为会话ID 的一部分,通过SSE消息返回给客户端,客户端会在返回中会带上这个包含编码后端地址的会话ID。Higress收到请求后,会直接解码会话ID ,提取出里面绑定的后端地址(Pod-A),然后精准地将请求路由到那个特定的Pod,而不是重新进行负载均衡。
所以设置mcp-sse需要前端同时配合 **在fetchEventSource 请求sse时 在请求头设置x-mcp-session-id 携带返回的sessionid 经实战测试 ,**设置sessionid的时机,应该在onopen的时候,因为onmessage是当服务端主动推送数据时才会触发,如果只在onmessage的时候设置,有可能会造成部分会话丢失,因为没有及时在请求头中携带x-mcp-session-id 具体实现代码如下
javascript
fetchEventSource(import.meta.env.VITE_APP_BASEURL+'/sseConnect', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'text/event-stream',
'x-mcp-session-id': currentSessionId || '',
},
onopen(response){
console.log('~~~~~~~~~~~~~~~~~sseClient onopen~~~~~~~~~~~~~~~~',response)
// 检查响应状态
if (!response.ok) {
// 响应非 2xx,抛出错误,避免重连
throw new Error(`SSE 连接失败,状态码: ${response.status}`);
}
const sid = response.headers.get('mcp-session-id');
if (sid) currentSessionId = sid;
console.log('SSE 连接成功');
},
onmessage(event){
console.log('Aievent::::::::::::::::;',event)
let data;
if(event.data){
data =JSON.parse(event.data)
}
if(data && data.sessionid){
currentSessionId = data.sessionid
}
...
}
并且最佳实践是在服务端初次sse实例初始化的时候,连接成功的时候,就先推送一个消息
2. 如果sse 在客户端的onopen都没触发,有可能是网关配置没关闭缓冲配置,同时需要服务端在sse请求的时候,对响应头设置也需要关闭缓冲配置
ingress配置是 proxy_buffering:off
higress和 nginx的配置可能会有所差异,如果当前的网关已经是higress管理的话,使用nginx的方式配置可能不会生效,
nginx.ingress.kubernetes.io/proxy-buffering: "off"
服务端创建sse连接实例时 需要设置关闭缓冲兜底配置x-Accel-buffering防止上面配置因为nginx higress网关没对应没生效的问题
javascript
res.status(200).set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
'X-Accel-Buffering': 'no' // 重要,绕过网关的缓冲 当proxy_buffering没生效时,否则onopen一直不会触发
// 'Access-Control-Allow-Origin': '*' // 允许跨域
});
如果不关闭网关会一直在缓冲,没有返回到客户端数据
3.text-embedding 的 higress网关特殊配置
之前我们在higress网关配置设置的时候对于普通的chat model是配置的/v1 + 模型对应的前缀匹配 具体可见笔者之前的文章
对于embedding的模型 由于他请求的路径不是/chat/competations而是/v1/embeddings ,所以需要和之前的/v1到chat的配置单独区分, 根据最长匹配优先,可以在路径匹配 设置/v1/embeddings 这样所有embeddings的请求都会优先打到 /v1/embeddings的网关规则配置,


4.密码环境变量配置的报错 secret 管道修饰符处理错误
如果因为环境变量的问题报错 ,可以进入pod内,执行env | grep '环境变量名' ,在进行secret配置的时候,stringData是为了将数组自动处理base64并添加到data中, | quote 是为了处理成字符串防止yaml解析报错,如果是string则需要手动自己做base64处理 使用,| b64en处理,这次报错就是我已经使用了stringData但是又错误的使用了b64en 然后打印了环境变量发现了报错
5.mongodb数据库写入权限不足报错
排查过程:
在mongodb pod中 mongosh登录后
db.runCommand({ connectionStatus: 1 }) authenticatedUsers 中要包含用户才有权
use admin
db.getUser("admin") 返回的roles里面看 { role: "readWrite", db: "app" } 有没有指定库的写入操作权限
如果没有 db.grantRolesToUser("admin", { role: "readWrite", db: "app" }) 补授权 测试,
后来发现只要每次pod重启请求就会将用户权限刷新,经过科学上网**,发现是在mongoStore部署初始化配置的角色的时候就已经设置固定了,mongodbcommunity 配置,**
javascript
users:
- db: admin
name: admin
passwordSecretRef:
name: mdb-admin-user-password
roles:
- db: admin
name: clusterAdmin
- db: admin
name: userAdminAnyDatabase
- db: admin
name: readWriteAnyDatabase
scramCredentialsSecretName: admin-scram
需要给admin用户开启 readWriteAnyDatabase权限,才能有对数据库的读取和使用,
排查技巧:
1.在排查网关请求转发的过程中,可以打印网关日志 即higress-gateway 的logs进行排查 ,重点关注response_code_detail,
如果是route not found则是网关没生效,找不到对应的网关请求路径,根据path能看到实际请求的地址,
kubectl logs -n higress-system -l app=higress-gateway -f --tail=10 | grep -E 'chat/completions'
可以打印过滤指定的higress网关日志