Skip to content

Commit

Permalink
doc: 在线提交文章
Browse files Browse the repository at this point in the history
  • Loading branch information
01Petard authored Feb 19, 2025
1 parent 9ffed73 commit 330ceea
Showing 1 changed file with 157 additions and 0 deletions.
157 changes: 157 additions & 0 deletions docs/开发/一对多的数据交互方案设计.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---

# 总部与分公司数据交互方案

设想有这样一个场景:总部通过统一接口访问多个分公司的数据,并且请求中包含多个查询参数。这虽然是一个分布式系统场景,涉及总部和多个分公司之间的数据交互,但解决方案依然可以通过单体项目的思维来实现。本文将详细描述如何通过 Nginx 反向代理实现统一接口调用,并展示具体的前端、Nginx 和后端实现方式,实现在局域网环境,动态获取不同数据接口源的信息。

---

## 1. 场景描述

- **背景**:总部和四个分公司各自部署一个服务器,使用同一套源码实现相同接口功能。
- **目标**:总部希望通过一个统一接口(如 `http://localhost:8080/api/{子公司编号}/monitor/report/output`)查看不同分公司的数据,同时支持传递查询参数(如 `factoryCode`, `lineCode`, `startDate`, `endDate`, `pageIndex`, `pageSize`)。
- **技术选型**
- 前端负责调用接口并展示数据。
- Nginx 作为反向代理服务器进行请求转发。
- 后端实现具体业务逻辑,处理查询参数。

---

## 2. 实现方案

### 2.1 请求示例

前端发起的请求如下:
```shell
http://10.0.0.93:8080/api/5B20/monitor/report/output?factoryCode=5B20&lineCode=5B200101&startDate=20250218&endDate=20250218&pageIndex=1&pageSize=50
```

其中:
- `{子公司编号}` 是动态部分,例如 `5B20`
- 查询参数包括 `factoryCode`, `lineCode`, `startDate`, `endDate`, `pageIndex`, 和 `pageSize`

---

### 2.2 Nginx 配置

#### 主要任务
- 捕获 `{子公司编号}` 并动态匹配到对应的分公司服务器。
- 确保查询参数完整传递到目标服务器。

#### 示例配置
```nginx
http {
upstream server_5B20 {
server 10.0.0.94:8080; # 子公司5B20的服务器地址
}
upstream server_5B30 {
server 10.0.0.95:8080; # 子公司5B30的服务器地址
}
upstream server_5B40 {
server 10.0.0.96:8080; # 子公司5B40的服务器地址
}
upstream server_5B50 {
server 10.0.0.97:8080; # 子公司5B50的服务器地址
}
server {
listen 8080;
location ~ ^/api/(?<division_code>[^/]+)/monitor/report/output$ {
set $target_server "server_$division_code";
proxy_pass http://$target_server/monitor/report/output;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 确保查询参数完整传递
proxy_pass_request_headers on;
proxy_pass_request_body on;
}
}
}
```

#### 配置说明
- **捕获 `{子公司编号}`**:使用正则表达式 `(?<division_code>[^/]+)` 捕获 URL 中的 `{子公司编号}`
- **动态匹配目标服务器**:通过 `set $target_server "server_$division_code";` 动态设置目标服务器。
- **路径重写**:将原始路径 `/api/{子公司编号}/monitor/report/output` 转发为 `/api/monitor/report/output`
- **查询参数传递**`proxy_pass_request_headers on;``proxy_pass_request_body on;` 确保所有查询参数和请求头被正确转发。

---

### 2.3 后端接口设计

#### 接口定义
后端接口接收以下参数:
- `factoryCode`: 工厂编号
- `lineCode`: 生产线编号
- `startDate`: 开始日期
- `endDate`: 截止日期
- `pageSize`: 分页大小
- `pageIndex`: 分页索引

#### 示例代码(Spring Boot)
```java
@RestController
@RequestMapping("/monitor/report/")
public class MonitorController {

@ApiOperation("产量明细")
@GetMapping("output")
public ResponseEntity<ApiResponse<ListModel<OutputReportVo>>> output(
@RequestParam String factoryCode,
@RequestParam String lineCode,
@RequestParam Integer startDate,
@RequestParam Integer endDate,
@RequestParam int pageIndex,
@RequestParam int pageSize) {

// 参数校验
// ...

// 调用服务逻辑
// ...

return ResponseEntity.ok(ApiResponse.success(result));
}
}
```

#### 关键点
- **参数校验**:确保接收到的参数合法。
- **业务逻辑**:根据参数计算产量明细并返回结果。

---

### 2.4 整体流程

1. **前端调用**
- 请求示例:`http://10.0.0.93:8080/api/5B20/monitor/report/output?factoryCode=5B20&lineCode=5B200101&startDate=20250218&endDate=20250218&pageIndex=1&pageSize=50`
- 请求到达 Nginx。

2. **Nginx 转发**
- 捕获 `{子公司编号}`(如 `5B20`)。
- 将请求转发到对应子公司的服务器地址,例如 `http://10.0.0.94:8080/api/monitor/report/output?factoryCode=5B20&lineCode=5B200101&startDate=20250218&endDate=20250218&pageIndex=1&pageSize=50`

3. **后端处理**
- 子公司服务器接收到完整请求,解析参数并执行业务逻辑。
- 返回计算结果。

4. **响应返回**
- 数据经 Nginx 返回给前端。

---

## 3. 扩展性建议

- **负载均衡**:如果某个子公司服务器压力较大,可以在 Nginx 中为该子公司配置多个上游服务器。
- **日志记录**:在 Nginx 和后端服务中记录请求日志,便于后续排查问题。
- **安全性**:在 Nginx 中添加身份验证机制(如 Token 验证),确保只有授权用户可以访问敏感数据。

---

通过以上设计,可以高效地完成总部与分公司的数据交互需求,同时支持复杂的查询参数传递。

0 comments on commit 330ceea

Please sign in to comment.