- Add Nacos registry for service registration and deregistration. - Implement Redis registry for session management with heartbeat and session claiming. - Improve completion service with session handling and request validation. - Enhance WebSocket handling for completion requests with JSON-RPC support. - Add tests for new registry implementations and completion manager functionalities. - Refactor existing code for better readability and maintainability.
5.3 KiB
5.3 KiB
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, DB1) - 会话归属冲突返回
409,并带routeTo+X-LSP-Route-To
3. 推荐架构
- 前端 -> Java Gateway/BFF -> Go LSP Gateway
- Go LSP Gateway 多副本部署(Nacos 注册)
- Redis 作为会话目录(
language + sessionId -> owner instance)
4. Nacos 接入方式
你有两种落地方式:
- 由部署系统注册(推荐)
指 K8s/运维平台在发布时自动调用 Nacos OpenAPI 注册实例,Go 程序本身不依赖 Nacos SDK。 - 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(或 headerX-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(服务发现)
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 配置:
cloud:
nacos:
discovery:
enabled: true
register-enabled: true
server-addr: 10.0.0.10:8848
username: nacos
password: nacos
对应 Go 环境变量:
ENABLE_NACOS_REGISTER=trueNACOS_SERVER_ADDR=10.0.0.10:8848NACOS_USERNAME=nacosNACOS_PASSWORD=nacosNACOS_SERVICE_NAME=lsp-gatewayNACOS_GROUP=DEFAULT_GROUPNACOS_IP=<当前实例可达IP>NACOS_PORT=8080(或你的服务端口)
6.3 Gateway 路由示例(HTTP + WS)
spring:
cloud:
gateway:
routes:
- id: lsp-http
uri: lb://lsp-gateway
predicates:
- Path=/lsp/api/**
filters:
- RewritePath=/lsp/api/(?<segment>.*), /api/$\{segment}
- id: lsp-ws
uri: lb:ws://lsp-gateway
predicates:
- Path=/lsp/ws/**
filters:
- RewritePath=/lsp/ws/(?<segment>.*), /ws/$\{segment}
6.4 BFF 转发逻辑(WebClient 伪代码)
Mono<ResponseEntity<String>> 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=trueREDIS_ADDR=10.0.0.10:6379REDIS_DB=1REDIS_PASSWORD=(空)INSTANCE_ID:每个实例唯一(建议 Pod 名)INSTANCE_URL:实例可回源地址(供 routeTo 使用)ENABLE_NACOS_REGISTER=trueNACOS_SERVER_ADDR=10.0.0.10:8848NACOS_USERNAME=nacosNACOS_PASSWORD=nacosNACOS_IP:实例可达内网 IP(不要填 127.0.0.1)NACOS_PORT:实例监听端口MAX_SESSIONS:按机器资源评估(如 200~500)SESSION_TTL:建议 10~30 分钟
8. 常见误区
-
“用了 Nacos 就不需要 Redis 会话目录”
错。Nacos 只告诉你“有哪些实例”,不维护“某会话属于哪台实例”。 -
“随机 LB 也能跑”
能跑但体验会抖,LSP 上下文会丢。 -
“不传 sessionId 也没关系”
错。会话粘性依赖稳定 sessionId。
9. 联调 checklist
- Nacos 中能看到
lsp-gateway实例。 - Java 转发 HTTP 可通。
- 同一
sessionId连续请求响应稳定。 - 人为让请求打到非 owner 实例时,Java 能按
routeTo自动重试成功。 - WS 通道可建立,断线重连后会话仍可恢复。