feat: enhance API and session management with Nacos and Redis integration

- 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.
This commit is contained in:
2026-02-15 17:46:34 +08:00
parent 57afb90bc0
commit 3284ce07c7
22 changed files with 1863 additions and 87 deletions

View File

@@ -0,0 +1,186 @@
# 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 AlibabaNacos示例
## 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/(?<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 伪代码)
```java
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=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 通道可建立,断线重连后会话仍可恢复。