100gbs开发环境,新增socket代理,让本地可直连100环境。

dev
huwei 2026-07-08 16:45:49 +08:00
parent c999e1b348
commit 306637d44b
13 changed files with 222 additions and 257 deletions

View File

@ -1,181 +0,0 @@
# GBS Dubbo NodePort 映射与还原记录
记录时间2026-07-03
## 背景
本地项目连接 100 开发环境 Nacos 后Dubbo consumer 从 `jjb-dragon-facade` 获取到的 provider 地址是 k8s Pod IP例如
```text
10.244.178.143:20880
```
本地电脑无法直连 k8s Pod 网段,因此曾临时采用方案 A通过 NodePort 暴露 k8s 内 Dubbo provider并让 provider 注册 `192.168.20.100:32xxx` 到 Nacos。
## 临时映射操作
### 1. 创建 Dubbo NodePort Service
为实际注册 Dubbo provider 的底座服务创建 `*-dubbo` NodePort Service端口范围如下
```text
jjb-saas-system 32080
jjb-saas-auth 32081
jjb-saas-events 32082
jjb-saas-security 32083
jjb-saas-message 32084
jjb-saas-login 32085
jjb-saas-base 32086
jjb-saas-process-layout 32087
jjb-saas-user 32088
jjb-saas-official 32089
jjb-saas-facade 32090
jjb-saas-open-platform 32091
jjb-saas-application 32092
jjb-saas-attachment 32093
jjb-saas-formily-design 32094
jjb-saas-desk 32095
jjb-saas-config 32096
jjb-saas-document 32097
jjb-saas-component-design 32098
jjb-saas-view 32099
jjb-saas-gateway 32100
```
Service 结构示例:
```yaml
apiVersion: v1
kind: Service
metadata:
name: jjb-saas-message-dubbo
namespace: jjb-dragon
spec:
type: NodePort
selector:
app: jjb-saas-message-pod
ports:
- name: dubbo
protocol: TCP
port: 20880
targetPort: 20880
nodePort: 32084
```
### 2. 设置 Deployment 运行时环境变量
给对应 Deployment 设置:
```bash
kubectl set env deployment/<service>-deploy -n jjb-dragon \
DUBBO_IP_TO_REGISTRY=192.168.20.100 \
DUBBO_PORT_TO_REGISTRY=<nodePort>
```
示例:
```bash
kubectl set env deployment/jjb-saas-message-deploy -n jjb-dragon \
DUBBO_IP_TO_REGISTRY=192.168.20.100 \
DUBBO_PORT_TO_REGISTRY=32084
```
### 3. 开放防火墙端口
```bash
firewall-cmd --permanent --add-port=32080-32100/tcp
firewall-cmd --reload
```
### 4. 临时映射备份位置
```text
/root/codex-backups/dubbo-nodeport-20260703125329
```
## 还原操作
用户要求 100 环境不要映射 Dubbo 到外部端口,因此已执行还原。
### 1. 清理 Deployment 环境变量
```bash
kubectl set env deployment/<service>-deploy -n jjb-dragon \
DUBBO_IP_TO_REGISTRY- \
DUBBO_PORT_TO_REGISTRY-
```
### 2. 删除 Dubbo NodePort Service
```bash
kubectl delete svc <service>-dubbo -n jjb-dragon --ignore-not-found=true
```
已删除范围:
```text
jjb-saas-application-dubbo
jjb-saas-attachment-dubbo
jjb-saas-auth-dubbo
jjb-saas-base-dubbo
jjb-saas-component-design-dubbo
jjb-saas-config-dubbo
jjb-saas-desk-dubbo
jjb-saas-document-dubbo
jjb-saas-events-dubbo
jjb-saas-facade-dubbo
jjb-saas-formily-design-dubbo
jjb-saas-gateway-dubbo
jjb-saas-login-dubbo
jjb-saas-message-dubbo
jjb-saas-official-dubbo
jjb-saas-open-platform-dubbo
jjb-saas-process-layout-dubbo
jjb-saas-security-dubbo
jjb-saas-system-dubbo
jjb-saas-user-dubbo
jjb-saas-view-dubbo
```
### 3. 关闭防火墙端口
```bash
firewall-cmd --permanent --remove-port=32080-32100/tcp
firewall-cmd --reload
```
### 4. 还原前备份位置
```text
/root/codex-backups/dubbo-nodeport-restore-20260703180914
```
## 还原后验证
### k8s 验证
```bash
kubectl get svc -n jjb-dragon | grep -- '-dubbo'
kubectl get deploy -n jjb-dragon -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[0].env}{"\n"}{end}' | grep 'DUBBO_.*TO_REGISTRY'
```
结果:无 `*-dubbo` Service`DUBBO_IP_TO_REGISTRY` / `DUBBO_PORT_TO_REGISTRY` 环境变量。
### 本机端口验证
从本机测试:
```text
192.168.20.100:32080-32100 全部 CLOSED
```
### Nacos 验证
`jjb-dragon-facade` 中不再存在 `192.168.20.100:32xxx` provider。服务重启后重新回到 k8s 内部注册方式,即 Pod IP例如 `10.244.*:20880`
## 注意事项
1. 本次还原没有修改本地项目代码。
2. 本次还原没有重新打镜像。
3. 本次还原会使本地电脑不能再通过 `192.168.20.100:32xxx` 直连 k8s 内 Dubbo provider。
4. 如后续仍需要本地调用 k8s Dubbo 服务,建议优先采用独立 local-dev namespace 或 VPN/内网路由方案,避免影响正式线上环境。

View File

@ -2,6 +2,33 @@
> 适用场景:本地 IDE 已通过 **VPN** 接入 `192.168.20.0/24`,需要调用 100 上 GBS Dubbo 服务进行开发联调。 > 适用场景:本地 IDE 已通过 **VPN** 接入 `192.168.20.0/24`,需要调用 100 上 GBS Dubbo 服务进行开发联调。
> 脚本目录:`docs/gbs/scripts/dubbo-dev-proxy/` > 脚本目录:`docs/gbs/scripts/dubbo-dev-proxy/`
> **本文档为唯一实施指南**,可独立指导任意新会话从零搭建整套方案。
---
## 0. 新会话快速实施清单
按顺序执行,已完成的步骤可跳过。
| 步骤 | 动作 | 验收标准 |
|------|------|----------|
| 0 | 确认 VPN 连通 `192.168.20.100` | `Test-NetConnection 192.168.20.100 -Port 30140` 成功 |
| 1 | 检查 100 是否已装代理(见 **4.0** | `dubbo-proxy-status.sh` 显示 `running` |
| 2 | 未安装则执行 **4.2**`deploy_plan_c.py` | `32080`、`32084` 端口 LISTEN |
| 3 | 确认本项目代码改动已就位(见 **5.7** | `bootstrap.yml` / `application-local.yml` / Dubbo Client 已配置 |
| 4 | IDEA 设置 `local` profile + VM Options**5.4** | 启动无 Nacos 报错 |
| 5 | 启动本地服务,检查 Dubbo 日志 | 连接 `192.168.20.100:32080`**无** `10.244.*` 超时 |
| 6 | 功能验证 | 用户同步、短信等依赖 GBS 的接口正常 |
**关键端口速记safety-eval 常用)**
| Facade / 服务 | GBS 服务名 | 代理端口 |
|---------------|-----------|----------|
| **UserFacade** | jjb-saas-**system** | **32080** |
| **MessageFacade** | jjb-saas-**message** | **32084** |
| user 服务(非 UserFacade | jjb-saas-user | 32088 |
> 易错点:`UserFacade` 在 **system32080**,不是 user32088
--- ---
@ -19,11 +46,11 @@
**192.168.20.100 主机** 上运行 `socat` TCP 代理: **192.168.20.100 主机** 上运行 `socat` TCP 代理:
```text ```text
本地 IDE --VPN--> 192.168.20.100:32088 --socat--> 10.244.x.x:20880 (user Pod) 本地 IDE --VPN--> 192.168.20.100:32080 --socat--> 10.244.x.x:20880 (system Pod)
固定端口 当前 Pod IP动态刷新 固定端口 当前 Pod IP动态刷新
``` ```
### 1.3 与已废弃「NodePort + 改注册」方案的区别 ### 1.3 与已废弃「NodePort + 改注册」方案 A 的区别
| 对比项 | 已废弃方案 A | **方案 C本文** | | 对比项 | 已废弃方案 A | **方案 C本文** |
|--------|-------------|-------------------| |--------|-------------|-------------------|
@ -33,7 +60,7 @@
| 影响集群内服务互调 | 是 | **否** | | 影响集群内服务互调 | 是 | **否** |
| 本地可通过固定端口访问 Dubbo | 是 | **是** | | 本地可通过固定端口访问 Dubbo | 是 | **是** |
**结论:方案 C 只在 100 主机做端口转发K8s 内部仍保持 Pod IP 注册与 ClusterIP 通讯。** **结论:方案 C 只在 100 主机做端口转发K8s 内部仍保持 Pod IP 注册与 ClusterIP 通讯。禁止重新执行方案 A。**
--- ---
@ -51,16 +78,18 @@ flowchart LR
end end
subgraph k8s [jjb-dragon 集群内 - 不变] subgraph k8s [jjb-dragon 集群内 - 不变]
Pod1[user Pod 10.244.x.x:20880] PodSystem[system Pod 10.244.x.x:20880]
Pod2[system Pod 10.244.x.x:20880] PodMessage[message Pod 10.244.x.x:20880]
Nacos[prod-nacos:8848] Nacos[prod-nacos:8848]
end end
IDE -->|192.168.20.100:32088| FW IDE -->|192.168.20.100:32080 UserFacade| FW
IDE -->|192.168.20.100:32084 MessageFacade| FW
FW --> Socat FW --> Socat
Socat --> Pod1 Socat --> PodSystem
Pod2 --> Nacos Socat --> PodMessage
Pod1 --> Nacos PodSystem --> Nacos
PodMessage --> Nacos
``` ```
--- ---
@ -71,15 +100,15 @@ flowchart LR
| 本地固定端口 | GBS 服务 | Pod 标签 | Dubbo 端口 | | 本地固定端口 | GBS 服务 | Pod 标签 | Dubbo 端口 |
|-------------|----------|----------|------------| |-------------|----------|----------|------------|
| 32080 | jjb-saas-system | jjb-saas-system-pod | 20880 | | **32080** | **jjb-saas-system** | jjb-saas-system-pod | 20880 |
| 32081 | jjb-saas-auth | jjb-saas-auth-pod | 20880 | | 32081 | jjb-saas-auth | jjb-saas-auth-pod | 20880 |
| 32082 | jjb-saas-events | jjb-saas-events-pod | 20880 | | 32082 | jjb-saas-events | jjb-saas-events-pod | 20880 |
| 32083 | jjb-saas-security | jjb-saas-security-pod | 20880 | | 32083 | jjb-saas-security | jjb-saas-security-pod | 20880 |
| 32084 | jjb-saas-message | jjb-saas-message-pod | 20880 | | **32084** | **jjb-saas-message** | jjb-saas-message-pod | 20880 |
| 32085 | jjb-saas-login | jjb-saas-login-pod | 20880 | | 32085 | jjb-saas-login | jjb-saas-login-pod | 20880 |
| 32086 | jjb-saas-base | jjb-saas-base-pod | 20880 | | 32086 | jjb-saas-base | jjb-saas-base-pod | 20880 |
| 32087 | jjb-saas-process-layout | jjb-saas-process-layout-pod | 20880 | | 32087 | jjb-saas-process-layout | jjb-saas-process-layout-pod | 20880 |
| **32088** | **jjb-saas-user** | jjb-saas-user-pod | 20880 | | 32088 | jjb-saas-user | jjb-saas-user-pod | 20880 |
| 32089 | jjb-saas-official | jjb-saas-official-pod | 20880 | | 32089 | jjb-saas-official | jjb-saas-official-pod | 20880 |
| 32090 | jjb-saas-facade | jjb-saas-facade-pod | 20880 | | 32090 | jjb-saas-facade | jjb-saas-facade-pod | 20880 |
| 32091 | jjb-saas-open-platform | jjb-saas-open-platform-pod | 20880 | | 32091 | jjb-saas-open-platform | jjb-saas-open-platform-pod | 20880 |
@ -93,12 +122,36 @@ flowchart LR
| 32099 | jjb-saas-view | jjb-saas-view-pod | 20880 | | 32099 | jjb-saas-view | jjb-saas-view-pod | 20880 |
| 32100 | jjb-saas-gateway | jjb-saas-gateway-pod | 20880 | | 32100 | jjb-saas-gateway | jjb-saas-gateway-pod | 20880 |
> **safety-eval** 常用:`32080`system/UserFacade、`32084`message/MessageFacade按实际依赖选用。
--- ---
## 4. 100 服务器需要做什么 ## 4. 100 服务器需要做什么
### 4.0 判断是否已安装(先执行,可跳过安装)
在 100 上执行:
```bash
# 目录与 systemd 是否存在
ls /opt/dubbo-dev-proxy/dubbo-proxy-status.sh
systemctl is-active dubbo-dev-proxy.timer
# 代理是否在跑
/opt/dubbo-dev-proxy/dubbo-proxy-status.sh
# 关键端口是否在监听
ss -lntp | grep -E ':32080|:32084'
```
**已安装且 running** → 跳到 **4.3** 日常运维,或直接进入本文 **第 5 节** 配置本地。
**未安装或 stopped** → 执行 **4.2** 安装。
从开发机远程一键检查(需 Python + paramiko
```bash
python docs/gbs/scripts/dubbo-dev-proxy/debug_plan_c.py
```
### 4.1 前置条件 ### 4.1 前置条件
| 项 | 要求 | | 项 | 要求 |
@ -111,15 +164,24 @@ flowchart LR
### 4.2 一次性安装 ### 4.2 一次性安装
将仓库中脚本目录上传到 100或在 100 上 git pull 后执行): **方式 A在 100 上手动安装**
```bash ```bash
# 在 100 上执行 ssh root@192.168.20.100
cd /path/to/safety-eval-service/docs/gbs/scripts/dubbo-dev-proxy cd /path/to/safety-eval-service/docs/gbs/scripts/dubbo-dev-proxy
chmod +x *.sh chmod +x *.sh
sudo ./dubbo-proxy-install.sh sudo ./dubbo-proxy-install.sh
``` ```
**方式 B从开发机 SSH 自动部署(推荐新会话使用)**
```bash
# 需 pip install paramiko
python docs/gbs/scripts/dubbo-dev-proxy/deploy_plan_c.py
```
脚本会上传 `*.sh``dubbo-proxy.map` 到 100 的 `/opt/dubbo-dev-proxy-src/`,再执行 `dubbo-proxy-install.sh`
安装脚本会: 安装脚本会:
1. 安装 `socat` 1. 安装 `socat`
@ -153,10 +215,11 @@ systemctl start dubbo-dev-proxy.timer
# 2. 端口监听 # 2. 端口监听
ss -lntp | grep -E '3208[0-9]|32100' ss -lntp | grep -E '3208[0-9]|32100'
# 3. 本机探测 user 代理(示例) # 3. 本机探测 safety-eval 常用代理
nc -zv 127.0.0.1 32088 nc -zv 127.0.0.1 32080 # system / UserFacade
nc -zv 127.0.0.1 32084 # message / MessageFacade
# 4. 确认 K8s 未被改动 # 4. 确认 K8s 未被改动(方案 A 残留检查)
kubectl get svc -n jjb-dragon | grep dubbo # 应无 *-dubbo kubectl get svc -n jjb-dragon | grep dubbo # 应无 *-dubbo
kubectl get deploy -n jjb-dragon -o yaml | grep DUBBO_IP_TO_REGISTRY # 应无输出 kubectl get deploy -n jjb-dragon -o yaml | grep DUBBO_IP_TO_REGISTRY # 应无输出
``` ```
@ -166,6 +229,7 @@ kubectl get deploy -n jjb-dragon -o yaml | grep DUBBO_IP_TO_REGISTRY # 应无
| 类别 | 路径/端口 | 说明 | | 类别 | 路径/端口 | 说明 |
|------|-----------|------| |------|-----------|------|
| 安装目录 | `/opt/dubbo-dev-proxy/` | 脚本与 map 配置 | | 安装目录 | `/opt/dubbo-dev-proxy/` | 脚本与 map 配置 |
| 上传暂存 | `/opt/dubbo-dev-proxy-src/` | `deploy_plan_c.py` 上传位置 |
| PID 目录 | `/var/run/dubbo-dev-proxy/` | socat 进程 PID | | PID 目录 | `/var/run/dubbo-dev-proxy/` | socat 进程 PID |
| 日志 | `/var/log/dubbo-dev-proxy/` | 按端口分日志 | | 日志 | `/var/log/dubbo-dev-proxy/` | 按端口分日志 |
| systemd | `dubbo-dev-proxy.service` | 刷新代理 | | systemd | `dubbo-dev-proxy.service` | 刷新代理 |
@ -190,16 +254,16 @@ kubectl get deploy -n jjb-dragon -o yaml | grep DUBBO_IP_TO_REGISTRY # 应无
在本地 PowerShell / Git Bash 执行: 在本地 PowerShell / Git Bash 执行:
```bash ```powershell
# VPN + 网关 # VPN + 网关
curl -s -o /dev/null -w "gateway:%{http_code}\n" http://192.168.20.100:30140/ curl -s -o /dev/null -w "gateway:%{http_code}\n" http://192.168.20.100:30140/
# Nacos # Nacos
curl -s -o /dev/null -w "nacos:%{http_code}\n" http://192.168.20.100:30290/nacos/ curl -s -o /dev/null -w "nacos:%{http_code}\n" http://192.168.20.100:30290/nacos/
# Dubbo 代理(100 上方案 C 启用后 # Dubbo 代理(safety-eval 常用端口
# Windows 可用 Test-NetConnection Test-NetConnection 192.168.20.100 -Port 32080 # UserFacade
Test-NetConnection 192.168.20.100 -Port 32088 Test-NetConnection 192.168.20.100 -Port 32084 # MessageFacade
``` ```
### 5.3 本地配置原则 ### 5.3 本地配置原则
@ -208,16 +272,24 @@ Test-NetConnection 192.168.20.100 -Port 32088
2. **HTTP**:走网关 `http://192.168.20.100:30140` 2. **HTTP**:走网关 `http://192.168.20.100:30140`
3. **MySQL/Redis**:直连 `192.168.20.100:33080` / `6379` 3. **MySQL/Redis**:直连 `192.168.20.100:33080` / `6379`
4. **Dubbo****不要**依赖 Nacos 自动发现的 `10.244.*` 地址;对需要的接口使用 **显式 URL** `dubbo://192.168.20.100:32xxx` 4. **Dubbo****不要**依赖 Nacos 自动发现的 `10.244.*` 地址;对需要的接口使用 **显式 URL** `dubbo://192.168.20.100:32xxx`
5. **本地服务注册**不要以线上同名注册到 `jjb-dragon`(避免污染负载) 5. **本地服务注册**关闭 Nacos discovery避免以线上同名注册到 `jjb-dragon`
### 5.4 safety-eval 本地 Profile 示例 ### 5.4 safety-eval 本地 Profile 配置
复制 `application-local.example.yml` 为本地使用(**不要提交含密码的私人配置** **模板文件**(完整版,含数据源密码
```text ```text
docs/gbs/scripts/dubbo-dev-proxy/application-local.example.yml docs/gbs/scripts/dubbo-dev-proxy/application-local.example.yml
``` ```
**本项目已提交的配置**(精简版,依赖 nacos 公共配置):
```text
safety-eval-start/src/main/resources/application-local.yml
```
`bootstrap.yml` 已在 `local` profile 中 import `application-local.yml`**无需额外改动 bootstrap**。
IDE VM Options 示例: IDE VM Options 示例:
```text ```text
@ -231,23 +303,23 @@ IDE VM Options 示例:
-DGBS_MESSAGE_FACADE_URL=dubbo://192.168.20.100:32084 -DGBS_MESSAGE_FACADE_URL=dubbo://192.168.20.100:32084
``` ```
IDEA 环境变量(可选): IDEA 环境变量(可选,与 VM Options 二选一
```text ```text
GBS_USER_FACADE_URL=dubbo://192.168.20.100:32080 GBS_USER_FACADE_URL=dubbo://192.168.20.100:32080
GBS_MESSAGE_FACADE_URL=dubbo://192.168.20.100:32084 GBS_MESSAGE_FACADE_URL=dubbo://192.168.20.100:32084
``` ```
### 5.5 Dubbo 依赖与端口对照(按需配置) ### 5.5 Dubbo 依赖与端口对照
| 业务依赖 | 建议显式 URL | | 业务依赖 | GBS 服务 | 显式 URL |
|----------|-------------| |----------|----------|----------|
| 用户 FacadeUserFacadesystem 服务) | `dubbo://192.168.20.100:32080` | | 用户 Facade**UserFacade** | jjb-saas-system | `dubbo://192.168.20.100:32080` |
| 消息 FacadeMessageFacade | `dubbo://192.168.20.100:32084` | | 消息 Facade**MessageFacade** | jjb-saas-message | `dubbo://192.168.20.100:32084` |
| 认证/安全 | `dubbo://192.168.20.100:32081` / `32083` | | 认证 / 安全 | jjb-saas-auth / security | `32081` / `32083` |
| 附件 | `dubbo://192.168.20.100:32093` | | 附件 | jjb-saas-attachment | `dubbo://192.168.20.100:32093` |
若项目通过 `@DubboReference` 自动发现,需在本地 profile 中为对应 reference 配置 `url` 属性,或关闭该 bean 的注册中心发现(按 GBS client 模块约定) 更多端口见 `dubbo-reference-local.example.properties`
### 5.6 本地清单(汇总) ### 5.6 本地清单(汇总)
@ -256,54 +328,64 @@ GBS_MESSAGE_FACADE_URL=dubbo://192.168.20.100:32084
| Profile | `spring.profiles.active` | `local` | | Profile | `spring.profiles.active` | `local` |
| Nacos 配置中心 | `spring.cloud.nacos.config.server-addr` | `192.168.20.100:30290` | | Nacos 配置中心 | `spring.cloud.nacos.config.server-addr` | `192.168.20.100:30290` |
| Nacos 命名空间 | `jjb-dragon` | 与线上一致(只读拉配置) | | Nacos 命名空间 | `jjb-dragon` | 与线上一致(只读拉配置) |
| Nacos 服务注册 | `spring.cloud.nacos.discovery.enabled` | `false` |
| 网关 | `gateway.url` | `http://192.168.20.100:30140` | | 网关 | `gateway.url` | `http://192.168.20.100:30140` |
| MySQL | host/port | `192.168.20.100:33080` | | MySQL | host/port | `192.168.20.100:33080` |
| Redis | host/port | `192.168.20.100:6379` | | Redis | host/port | `192.168.20.100:6379` |
| Dubbo UserFacade | `GBS_USER_FACADE_URL` | `dubbo://192.168.20.100:32080` | | Dubbo UserFacade | `GBS_USER_FACADE_URL` | `dubbo://192.168.20.100:32080` |
| Dubbo MessageFacade | `GBS_MESSAGE_FACADE_URL` | `dubbo://192.168.20.100:32084` | | Dubbo MessageFacade | `GBS_MESSAGE_FACADE_URL` | `dubbo://192.168.20.100:32084` |
| 本地服务端口 | `server.port` | `8095`(与项目默认一致) | | 本地服务端口 | `server.port` | `8095` |
| **禁止** | 注册到线上同名 Nacos 服务 | 使用独立服务名或关闭注册 |
### 5.7 本项目已改文件清单(新会话核对用)
| 文件 | 改动说明 |
|------|----------|
| `safety-eval-start/src/main/resources/bootstrap.yml` | `local` profile import `application-local.yml` |
| `safety-eval-start/src/main/resources/application-local.yml` | 关闭 discovery配置 Dubbo 显式 URL |
| `safety-eval-infrastructure/.../GbsUserFacadeClient.java` | `@DubboReference(url = "${safety-eval.gbs-user-sync.user-facade-url:}")` |
| `safety-eval-infrastructure/.../SmsRemote.java` | `@DubboReference(url = "${safety-eval.dubbo.message-facade-url:}")` |
新增 Dubbo 依赖时,按同样模式在 `application-local.yml` 增加 URL 属性,并在对应 `@DubboReference` 绑定 `${...}` 占位符。
--- ---
## 6. 完整操作流程(首次) ## 6. 完整操作流程(首次)
### Step 1100 安装代理 ### Step 1100 安装或确认代理
```bash ```bash
ssh root@192.168.20.100 # 先检查4.0),未安装则:
cd /path/to/safety-eval-service/docs/gbs/scripts/dubbo-dev-proxy python docs/gbs/scripts/dubbo-dev-proxy/deploy_plan_c.py
chmod +x *.sh # 或 SSH 到 100 手动执行 dubbo-proxy-install.sh
./dubbo-proxy-install.sh
./dubbo-proxy-status.sh
``` ```
### Step 2本地验证 VPN + 代理端口 ### Step 2本地验证 VPN + 代理端口
```powershell ```powershell
Test-NetConnection 192.168.20.100 -Port 32088 Test-NetConnection 192.168.20.100 -Port 32080
Test-NetConnection 192.168.20.100 -Port 32084
Test-NetConnection 192.168.20.100 -Port 30140 Test-NetConnection 192.168.20.100 -Port 30140
Test-NetConnection 192.168.20.100 -Port 30290 Test-NetConnection 192.168.20.100 -Port 30290
``` ```
### Step 3本地配置 IDE ### Step 3本地配置 IDE
1. 复制 `application-local.example.yml``application-local.yml`(放在 `safety-eval-start/src/main/resources/` 或 IDE 外部配置 1. 确认 `application-local.yml` 存在(或从 example 复制
2. 设置 VM Options见 5.4 2. 设置 VM Options见 5.4
3. Active profiles 填 `local` 3. Active profiles 填 `local`
### Step 4启动本地服务并验证 ### Step 4启动本地服务并验证
```bash 启动后检查日志:
# 本地启动后检查日志
# - Nacos 配置拉取成功 - Nacos 配置拉取成功
# - Dubbo 连接 192.168.20.100:32088 成功 - Dubbo 连接 `192.168.20.100:32080` / `32084` 成功
# - 无 10.244.x.x 连接超时 - **无** `10.244.x.x` 连接超时
```
### Step 5功能验证 ### Step 5功能验证
- 调用依赖 GBS 用户的接口(如同步用户) - 调用依赖 GBS 用户的接口(用户同步)
- 调用依赖短信的接口MessageFacade
- 通过网关 `30140` 访问前端页面(可选) - 通过网关 `30140` 访问前端页面(可选)
--- ---
@ -312,11 +394,12 @@ Test-NetConnection 192.168.20.100 -Port 30290
| 现象 | 排查 | | 现象 | 排查 |
|------|------| |------|------|
| 本地 `32088` 连不上 | VPN 是否通100 上 `dubbo-proxy-status.sh` 是否 running防火墙是否开放 | | 本地 `32080` / `32084` 连不上 | VPN 是否通100 上 `dubbo-proxy-status.sh` 是否 running防火墙是否开放 |
| Dubbo 仍连 `10.244.*` | 本地未覆盖 URL仍走 Nacos 自动发现;检查 profile / 环境变量 | | Dubbo 仍连 `10.244.*` | 未走 `local` profile未配置显式 URL检查 `GbsUserFacadeClient` / `SmsRemote` |
| 代理 running 但调用失败 | Pod 已漂移,执行 `dubbo-proxy-refresh.sh` | | 代理 running 但调用失败 | Pod 已漂移,执行 `dubbo-proxy-refresh.sh` `debug_plan_c.py` |
| 100 上某服务显示 skipped | 对应 Pod 非 Running`kubectl get pods -n jjb-dragon` 检查 | | 100 上某服务显示 skipped | 对应 Pod 非 Running`kubectl get pods -n jjb-dragon` 检查 |
| 集群内服务异常 | **立即停止代理排查**,确认未改 Deployment env方案 C 不应影响) | | 集群内服务异常 | 确认未改 Deployment env`kubectl get svc -n jjb-dragon \| grep dubbo` 应为空 |
| UserFacade 调不通但 32088 通 | **端口配错**UserFacade 用 `32080`system不是 `32088`user |
--- ---
@ -324,7 +407,7 @@ Test-NetConnection 192.168.20.100 -Port 30290
1. **限制访问源**:若 VPN 网段固定,可将 `32080-32100` 仅对 VPN 网段开放(`firewall-cmd --add-rich-rule` 1. **限制访问源**:若 VPN 网段固定,可将 `32080-32100` 仅对 VPN 网段开放(`firewall-cmd --add-rich-rule`
2. **下班停止**:不需要联调时 `dubbo-proxy-stop.sh`,减少暴露面 2. **下班停止**:不需要联调时 `dubbo-proxy-stop.sh`,减少暴露面
3. **不要与方案 A 混用**:禁止同时设置 `DUBBO_IP_TO_REGISTRY` 3. **禁止方案 A**:不得创建 `*-dubbo` NodePort Service 或设置 `DUBBO_IP_TO_REGISTRY`
4. **Pod 大规模重启后**:手动执行一次 `dubbo-proxy-refresh.sh` 4. **Pod 大规模重启后**:手动执行一次 `dubbo-proxy-refresh.sh`
5. **定期核对**`kubectl get svc -n jjb-dragon | grep dubbo` 应始终为空 5. **定期核对**`kubectl get svc -n jjb-dragon | grep dubbo` 应始终为空
@ -332,7 +415,6 @@ Test-NetConnection 192.168.20.100 -Port 30290
## 9. 相关文档 ## 9. 相关文档
- `docs/gbs/GBS-Dubbo-NodePort映射与还原记录.md` — 已废弃方案与还原记录
- `docs/gbs/GBS底座服务手册v2.md` — 端口与 Nacos 外部访问说明 - `docs/gbs/GBS底座服务手册v2.md` — 端口与 Nacos 外部访问说明
- `docs/本地JAR打包发布到100服务器完整流程.md` — K8s 部署流程(与本地开发并行) - `docs/本地JAR打包发布到100服务器完整流程.md` — K8s 部署流程(与本地开发并行)
@ -347,4 +429,7 @@ Test-NetConnection 192.168.20.100 -Port 30290
| `dubbo-proxy-refresh.sh` | 刷新 socat 到当前 Pod IP | | `dubbo-proxy-refresh.sh` | 刷新 socat 到当前 Pod IP |
| `dubbo-proxy-status.sh` | 查看运行状态 | | `dubbo-proxy-status.sh` | 查看运行状态 |
| `dubbo-proxy-stop.sh` | 停止全部代理 | | `dubbo-proxy-stop.sh` | 停止全部代理 |
| `application-local.example.yml` | 本地 IDE 配置模板 | | `deploy_plan_c.py` | 从开发机 SSH 上传并安装(新会话推荐) |
| `debug_plan_c.py` | 远程诊断代理与 Pod 状态 |
| `application-local.example.yml` | 本地 IDE 完整配置模板 |
| `dubbo-reference-local.example.properties` | Dubbo 显式 URL 速查 |

View File

@ -33,10 +33,10 @@ public class GbsUserSyncInterceptor implements WebMvcConfigurer {
private final AntPathMatcher pathMatcher = new AntPathMatcher(); private final AntPathMatcher pathMatcher = new AntPathMatcher();
private final String[] anonymousUrl = { private final String[] anonymousUrl = {
"/**/images/**",
"/**/account/syncUserToGBS/**", "/**/account/syncUserToGBS/**",
"/**/org-info/save/**", "/**/org-info/save/**",
"/**/account/save/**", "/**/account/save/**",
"/**/account/sendMessage/**",
"/**/file/**", "/**/file/**",
"/**/tree/**" "/**/tree/**"
}; };

View File

@ -5,7 +5,10 @@ import org.qinan.safetyeval.domain.exception.BizException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Primary;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
@ -18,6 +21,9 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
@Primary
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice(basePackages = "org.qinan.safetyeval.adapter.web") @RestControllerAdvice(basePackages = "org.qinan.safetyeval.adapter.web")
public class GlobalExceptionHandler { public class GlobalExceptionHandler {

View File

@ -8,7 +8,6 @@ import org.qinan.safetyeval.client.api.AccountApi;
import org.qinan.safetyeval.client.co.AccountCO; import org.qinan.safetyeval.client.co.AccountCO;
import org.qinan.safetyeval.client.dto.*; import org.qinan.safetyeval.client.dto.*;
import org.qinan.safetyeval.infrastructure.dataobject.base.Req; import org.qinan.safetyeval.infrastructure.dataobject.base.Req;
import org.qinan.safetyeval.infrastructure.remote.SmsRemote;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -28,10 +27,6 @@ public class AccountController {
@Resource @Resource
private AccountApi accountApi; private AccountApi accountApi;
@Resource
private SmsRemote smsRemote;
@ApiOperation("新增用户") @ApiOperation("新增用户")
@PostMapping("/save") @PostMapping("/save")
public SingleResponse<AccountCO> add(@Validated @RequestBody AccountAddCmd cmd) { public SingleResponse<AccountCO> add(@Validated @RequestBody AccountAddCmd cmd) {
@ -62,12 +57,6 @@ public class AccountController {
return accountApi.page(query); return accountApi.page(query);
} }
@ApiOperation("发送短信")
@PostMapping("/sendMessage")
public com.alibaba.cola.dto.SingleResponse<Boolean> sendMessage(@Validated @RequestBody SendMessageCmd cmd) {
return smsRemote.sign(cmd.getMobile());
}
@ApiOperation("用户同步gbs") @ApiOperation("用户同步gbs")
@GetMapping("/syncUserToGBS") @GetMapping("/syncUserToGBS")
public SingleResponse<AccountCO> syncUserToGBS(@ApiParam("账号") @RequestParam String account) { public SingleResponse<AccountCO> syncUserToGBS(@ApiParam("账号") @RequestParam String account) {

View File

@ -0,0 +1,41 @@
package org.qinan.safetyeval.adapter.web;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.qinan.safetyeval.client.dto.SendMessageCmd;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.infrastructure.remote.SmsRemote;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
*
* <p>
* /safetyEval/images
* </p>
*/
@Api(tags = "对外开放接口")
@RestController
@RequestMapping("/safetyEval/images")
public class ImagesOpenController {
@Resource
private SmsRemote smsRemote;
@ApiOperation("发送短信")
@PostMapping("/sendMessage")
public com.alibaba.cola.dto.SingleResponse<Boolean> sendMessage(@Validated @RequestBody SendMessageCmd cmd) {
return smsRemote.sign(cmd.getMobile());
}
@ApiOperation("发送短信")
@PostMapping("/test")
public SingleResponse test() {
return SingleResponse.success("hello word");
}
}

View File

@ -71,7 +71,11 @@ final class FileStorageHelper {
ossFileInfo.setUrl(fileStorage.getUrl()); ossFileInfo.setUrl(fileStorage.getUrl());
ossFileInfo.setBasePath(fileStorage.getBasePath()); ossFileInfo.setBasePath(fileStorage.getBasePath());
ossFileInfo.setFilename(fileStorage.getFilename()); ossFileInfo.setFilename(fileStorage.getFilename());
ossFileInfo.setPlatform(fileStorage.getPlatform()); String platform = fileStorage.getPlatform();
if (platform == null || platform.isEmpty() || "local".equalsIgnoreCase(platform)) {
platform = "aliyun-oss-1";
}
ossFileInfo.setPlatform(platform);
return ossFileInfo; return ossFileInfo;
} }

View File

@ -0,0 +1,17 @@
# 线上 prod 专用配置(打包进 jar不依赖项目内 nacos/ 目录)
# 解决 FileStorageRuntimeException: 没有找到对应的存储平台platform:local
# OSS 凭证优先取 Nacos config-common.common.aliyun.oss取不到时用下方默认值
dromara:
x-file-storage:
default-platform: aliyun-oss-1
thumbnail-suffix: ""
aliyun-oss:
- platform: aliyun-oss-1
enable-storage: true
access-key: ${common.aliyun.oss.accessKeyId:LTAI5tP6UnjpDRBjsUaxbLz9}
secret-key: ${common.aliyun.oss.accessKeySecret:9XCpOutOC1lTE7E4twbUOHGzaxoMRz}
end-point: oss-cn-hangzhou.aliyuncs.com
bucket-name: ${common.aliyun.oss.bucketName:cqqypx}
domain: https://${common.aliyun.oss.bucketName:cqqypx}.oss-cn-hangzhou.aliyuncs.com/
base-path: jjb/

View File

@ -38,3 +38,4 @@ spring:
- classpath:nacos-prod.yml - classpath:nacos-prod.yml
- classpath:sdk-prod.yml - classpath:sdk-prod.yml
- classpath:swagger.yml - classpath:swagger.yml
- classpath:application-prod.yml

View File

@ -131,6 +131,7 @@ safety-eval:
- /swagger-ui - /swagger-ui
- /swagger-resources - /swagger-resources
- /webjars - /webjars
- /images
- /public/org-personnel - /public/org-personnel
- /test - /test
- /tmp - /tmp

View File

@ -28,6 +28,7 @@
uri: http://jjb-saas-base uri: http://jjb-saas-base
path: /${application.gateway}/container/** path: /${application.gateway}/container/**
order: -2 order: -2
openapi: openapi:
appId: 2070081274042777600 appId: 2070081274042777600
appKey: dd367066994a4e93a49e847f26462f60 appKey: dd367066994a4e93a49e847f26462f60

View File

@ -1,4 +1,4 @@
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.1 Frontend_Env[production] Build_Date[2026/7/8 11:32:35] App_Identifier[safetyEval]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title>--</title><script>(function () { <!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.1 Frontend_Env[production] Build_Date[2026/7/8 16:24:36] App_Identifier[safetyEval]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title>--</title><script>(function () {
const APP_ENV = { const APP_ENV = {
antd: { antd: {
'ant-prefix': 'micro-temp', 'ant-prefix': 'micro-temp',
@ -89,4 +89,4 @@
}, },
} }
}</script><script defer="defer" src="/safetyEval/static/js/934.ada55f776be86394.js"></script><script defer="defer" src="/safetyEval/static/js/121.ae75e71830bf4ae0.js"></script><script defer="defer" src="/safetyEval/static/js/289.f12da2fe2f6ad2ae.js"></script><script defer="defer" src="/safetyEval/static/js/main.6ff8cc6ae670e8a0.js"></script><link href="/safetyEval/static/css/main.cb6068c6562f0d94.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.1 Frontend_Env[production] Build_Date[2026/7/8 11:32:35] App_Identifier[safetyEval] Frontend_Branch[dev] Backend_Branch[<branch-name>]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body></html> }</script><script defer="defer" src="/safetyEval/static/js/934.ada55f776be86394.js"></script><script defer="defer" src="/safetyEval/static/js/121.ae75e71830bf4ae0.js"></script><script defer="defer" src="/safetyEval/static/js/289.f12da2fe2f6ad2ae.js"></script><script defer="defer" src="/safetyEval/static/js/main.5ef5933af7c7f2d5.js"></script><link href="/safetyEval/static/css/main.cb6068c6562f0d94.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.1 Frontend_Env[production] Build_Date[2026/7/8 16:24:36] App_Identifier[safetyEval] Frontend_Branch[dev] Backend_Branch[<branch-name>]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body></html>

File diff suppressed because one or more lines are too long