# Go LSP Gateway 接入 Java 微服务(Nacos)指南 ## 1. 结论先说 可以。 你完全可以把当前 Go LSP Gateway 注册到 Nacos,然后由 Java 微服务通过服务名发现并转发请求。 但要注意: - Nacos 解决的是「服务发现」问题。 - LSP 场景还需要「会话粘性」问题(同 `sessionId` 要持续命中同一实例)。 - 粘性在你现在的实现里由 Redis 会话目录 + `routeTo` 重试机制承担,Nacos 本身不替代这部分。 ## 2. 当前 Go 服务能力(已具备) 对外接口: - HTTP: `POST /api/v1/completions/{language}` - WS: `GET /ws/completions`、`GET /ws/completions/{language}` - 健康检查:`/health`、`/health/live`、`/health/ready` 多副本会话能力: - Redis 会话外置(默认 `10.0.0.10:6379`, DB `1`) - 会话归属冲突返回 `409`,并带 `routeTo` + `X-LSP-Route-To` ## 3. 推荐架构 1. 前端 -> Java Gateway/BFF -> Go LSP Gateway 2. Go LSP Gateway 多副本部署(Nacos 注册) 3. Redis 作为会话目录(`language + sessionId -> owner instance`) ## 4. Nacos 接入方式 你有两种落地方式: 1. 由部署系统注册(推荐) 指 K8s/运维平台在发布时自动调用 Nacos OpenAPI 注册实例,Go 程序本身不依赖 Nacos SDK。 2. Go 进程内注册 在 Go 服务启动时使用 `nacos-sdk-go` 注册/心跳/下线。 你当前明确要求走 SDK,本项目已支持方式 2。 ## 5. Java 侧必须做的事 ## 5.1 统一转发入口 Java 提供统一接口给前端,例如: - `POST /editor/completions/{language}` 内部转发到: - `http://{lsp-service}/api/v1/completions/{language}` ## 5.2 强制透传稳定 sessionId 请求体必须带稳定 `sessionId`,建议格式: - `tenant:user:project:tab` 如果 `sessionId` 不稳定,会导致会话频繁重建、补全抖动。 ## 5.3 处理 409 routeTo(关键) 当 Go 返回 `409` 时: - 读取响应体 `routeTo`(或 header `X-LSP-Route-To`) - Java 侧自动重试一次到 `routeTo` 这样可以跨实例正确命中会话拥有者。 ## 5.4 透传请求头 - `X-Request-Id`(链路追踪) - `X-API-Key`(若 Go 配置了 `LSP_API_TOKEN`) ## 6. Spring Cloud Alibaba(Nacos)示例 ## 6.1 application.yml(服务发现) ```yaml spring: application: name: editor-bff cloud: nacos: discovery: server-addr: 10.0.0.20:8848 ``` Go 服务在 Nacos 中注册名假设为:`lsp-gateway` ## 6.2 Go 侧与 Spring 配置映射(SDK 注册) 你的 Java 配置: ```yaml cloud: nacos: discovery: enabled: true register-enabled: true server-addr: 10.0.0.10:8848 username: nacos password: nacos ``` 对应 Go 环境变量: - `ENABLE_NACOS_REGISTER=true` - `NACOS_SERVER_ADDR=10.0.0.10:8848` - `NACOS_USERNAME=nacos` - `NACOS_PASSWORD=nacos` - `NACOS_SERVICE_NAME=lsp-gateway` - `NACOS_GROUP=DEFAULT_GROUP` - `NACOS_IP=<当前实例可达IP>` - `NACOS_PORT=8080`(或你的服务端口) ## 6.3 Gateway 路由示例(HTTP + WS) ```yaml spring: cloud: gateway: routes: - id: lsp-http uri: lb://lsp-gateway predicates: - Path=/lsp/api/** filters: - RewritePath=/lsp/api/(?.*), /api/$\{segment} - id: lsp-ws uri: lb:ws://lsp-gateway predicates: - Path=/lsp/ws/** filters: - RewritePath=/lsp/ws/(?.*), /ws/$\{segment} ``` ## 6.4 BFF 转发逻辑(WebClient 伪代码) ```java Mono> proxyCompletion(String language, String body, HttpHeaders headers) { return call("lb://lsp-gateway/api/v1/completions/" + language, body, headers) .flatMap(resp -> { if (resp.getStatusCodeValue() != 409) return Mono.just(resp); String routeTo = extractRouteTo(resp); // from body.routeTo or X-LSP-Route-To if (routeTo == null || routeTo.isBlank()) return Mono.just(resp); String direct = routeTo + "/api/v1/completions/" + language; return call(direct, body, headers); // retry once }); } ``` ## 7. Go 服务部署参数建议(生产) - `ENABLE_REDIS_STICKY=true` - `REDIS_ADDR=10.0.0.10:6379` - `REDIS_DB=1` - `REDIS_PASSWORD=`(空) - `INSTANCE_ID`:每个实例唯一(建议 Pod 名) - `INSTANCE_URL`:实例可回源地址(供 routeTo 使用) - `ENABLE_NACOS_REGISTER=true` - `NACOS_SERVER_ADDR=10.0.0.10:8848` - `NACOS_USERNAME=nacos` - `NACOS_PASSWORD=nacos` - `NACOS_IP`:实例可达内网 IP(不要填 127.0.0.1) - `NACOS_PORT`:实例监听端口 - `MAX_SESSIONS`:按机器资源评估(如 200~500) - `SESSION_TTL`:建议 10~30 分钟 ## 8. 常见误区 1. “用了 Nacos 就不需要 Redis 会话目录” 错。Nacos 只告诉你“有哪些实例”,不维护“某会话属于哪台实例”。 2. “随机 LB 也能跑” 能跑但体验会抖,LSP 上下文会丢。 3. “不传 sessionId 也没关系” 错。会话粘性依赖稳定 sessionId。 ## 9. 联调 checklist 1. Nacos 中能看到 `lsp-gateway` 实例。 2. Java 转发 HTTP 可通。 3. 同一 `sessionId` 连续请求响应稳定。 4. 人为让请求打到非 owner 实例时,Java 能按 `routeTo` 自动重试成功。 5. WS 通道可建立,断线重连后会话仍可恢复。