wiki生成

This commit is contained in:
三丙
2025-10-28 14:39:06 +08:00
parent 26cec08d61
commit fa9524d302
31 changed files with 13636 additions and 1 deletions

View File

@@ -0,0 +1,199 @@
# 微服务架构
<cite>
**本文档引用的文件**
- [JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java)
- [JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java)
- [app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml)
- [protocol-service.yml](file://jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml)
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java)
- [ProtocolController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/ProtocolController.java)
- [DownlinkController.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java)
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java)
- [DownlinkGrpcClient.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/grpc/DownlinkGrpcClient.java)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java)
- [ProtocolUplinkMsg.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolUplinkMsg.java)
- [app.Dockerfile](file://docker/app.Dockerfile)
- [protocol.Dockerfile](file://docker/protocol.Dockerfile)
- [docker-compose.monolith.yml](file://docker/docker-compose.monolith.yml)
</cite>
## 目录
1. [引言](#引言)
2. [微服务职责划分](#微服务职责划分)
3. [服务启动入口与配置](#服务启动入口与配置)
4. [服务间通信机制](#服务间通信机制)
5. [部署拓扑与中间件依赖](#部署拓扑与中间件依赖)
6. [Docker与容器化部署](#docker与容器化部署)
7. [部署拓扑图](#部署拓扑图)
## 引言
JChargePointProtocol是一个用于充电桩管理的微服务架构系统采用模块化设计将业务逻辑与协议处理分离。该系统由两个核心微服务组成jcpp-app主应用服务和jcpp-protocol-api协议处理核心通过清晰的职责划分实现高内聚、低耦合的系统架构。本文档详细阐述这两个微服务的架构设计、通信机制、配置管理及部署方案。
## 微服务职责划分
### jcpp-app主应用服务
jcpp-app微服务负责系统的业务逻辑处理和用户交互是整个系统的后端核心。其主要职责包括
- **业务逻辑处理**:实现充电桩、充电枪、充电站等实体的增删改查操作,处理用户管理、权限控制、计费策略等核心业务逻辑。
- **REST API暴露**通过Spring MVC提供标准的RESTful API接口供前端UI或其他客户端调用如充电桩管理、用户认证、数据查询等接口。
- **数据库交互**使用MyBatis作为持久层框架与PostgreSQL数据库进行交互管理充电桩、用户、会话等结构化数据。
- **用户管理**实现基于JWT的认证授权机制管理用户登录、权限验证和会话生命周期。
**微服务职责来源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L1-L112)
- [ProtocolController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/ProtocolController.java#L1-L41)
### jcpp-protocol-api协议处理核心
jcpp-protocol-api微服务专注于充电桩通信协议的处理是系统的通信前置。其主要职责包括
- **TCP长连接处理**使用Netty框架监听指定端口如38001-38011接收来自充电桩的TCP连接请求维护长连接会话。
- **协议编解码**针对不同厂商的充电桩协议如云快充V150/V160/V170、绿能V340实现消息的编码与解码处理二进制、JSON等格式的数据包。
- **消息路由**:根据协议类型和消息内容,将上行消息路由到相应的处理器进行业务逻辑处理,并将下行指令正确发送到指定的充电桩。
- **gRPC接口暴露**提供gRPC服务接口允许jcpp-app等服务通过高性能的远程过程调用方式向充电桩发送控制指令。
**微服务职责来源**
- [DownlinkController.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java#L1-L76)
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java#L1-L185)
## 服务启动入口与配置
### 启动入口
系统通过两个独立的Spring Boot应用作为微服务的启动入口
- **jcpp-app启动入口**`JCPPServerApplication`类是jcpp-app微服务的主启动类。它通过`@SpringBootApplication`注解启用Spring
Boot自动配置并通过`main`方法启动应用。启动时会自动加载`app-service.yml`配置文件,并在启动完成后输出启动耗时日志。
- **jcpp-protocol-api启动入口**`JCPPProtocolServiceApplication`类是jcpp-protocol-api微服务的主启动类。它同样基于Spring
Boot但通过`scanBasePackages`指定了特定的包扫描范围,确保只加载协议相关的组件。其`main`方法负责启动协议服务。
**启动入口来源**
- [JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java#L1-L55)
- [JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java#L1-L59)
### 配置文件
每个微服务都有独立的YAML配置文件实现配置隔离
- **app-service.yml**
jcpp-app微服务的配置文件定义了HTTP服务器端口8080、数据库连接PostgreSQL、缓存配置Caffeine/Redis、Kafka队列、安全设置JWT等。通过环境变量
`SPRING_DATASOURCE_URL`)支持不同环境的配置注入。
- **protocol-service.yml**
jcpp-protocol-api微服务的配置文件定义了HTTP服务器端口8081、gRPC服务端口9090、各协议监听器的TCP端口如云快充V150在38001端口、以及Kafka生产者配置。该文件明确将
`service.type`设置为`protocol`,表明其为纯协议处理服务。
**配置文件来源**
- [app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml#L1-L432)
- [protocol-service.yml](file://jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml#L1-L274)
## 服务间通信机制
### 异步消息传递Kafka
两个微服务通过Apache Kafka进行异步消息传递实现解耦和削峰填谷
- **消息类型**`ProtocolUplinkMsg`
是核心的上行消息类型封装了来自充电桩的原始数据。当jcpp-protocol-api接收到充电桩的上行消息时会将其序列化为Protobuf格式并通过Kafka生产者发送到名为
`protocol_uplink`的主题。
- **消息消费**jcpp-app微服务中包含`ProtocolUplinkConsumerService`消费者,它订阅`protocol_uplink`主题从Kafka拉取
`ProtocolUplinkMsg`消息。消费后,消息会被反序列化并分发到相应的业务处理器,如更新充电桩状态、记录充电数据等。
**异步通信来源**
- [ProtocolUplinkMsg.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolUplinkMsg.java#L1-L24)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java)
### 同步远程调用gRPC
对于需要即时响应的控制指令系统采用gRPC进行同步远程调用
- **gRPC服务端**jcpp-protocol-api通过`DownlinkGrpcService`类暴露gRPC服务。它继承自
`ProtocolInterfaceGrpc.ProtocolInterfaceImplBase`,实现了`onDownlink`方法用于接收来自jcpp-app的下行控制请求如启动充电、停止充电、设置电价等
- **gRPC客户端**jcpp-app通过`DownlinkGrpcClient`类作为gRPC客户端。它维护与jcpp-protocol-api的长连接并提供
`sendDownlinkRequest`方法。当业务需要向充电桩发送指令时jcpp-app会构造`RequestMsg`通过gRPC客户端发送给jcpp-protocol-api。
- **通信流程**jcpp-app -> (gRPC) -> jcpp-protocol-api -> (TCP) -> 充电桩。gRPC调用确保了指令的可靠、低延迟传输。
**同步通信来源**
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java#L1-L185)
- [DownlinkGrpcClient.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/grpc/DownlinkGrpcClient.java#L1-L298)
## 部署拓扑与中间件依赖
系统依赖于多种中间件来实现其功能:
- **PostgreSQL**作为主数据库由jcpp-app服务连接用于持久化存储充电桩、用户、站点等核心业务数据。
- **Redis**作为缓存层由jcpp-app服务连接用于缓存充电桩状态、会话信息等高频访问数据减轻数据库压力。
- **Kafka**作为消息中间件是两个微服务间通信的桥梁。jcpp-protocol-api将上行消息发布到Kafkajcpp-app从Kafka消费这些消息。
**中间件依赖来源**
- [app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml#L30-L100)
## Docker与容器化部署
系统通过Docker实现容器化部署确保环境一致性
- **Docker镜像构建**:提供了`app.Dockerfile``protocol.Dockerfile`
两个Dockerfile。它们都基于相同的Java基础镜像采用多阶段构建。首先在构建阶段编译打包应用然后在运行阶段提取JAR包的分层内容实现更小的镜像体积和更快的启动速度。
- **Docker Compose**:通过`docker-compose.monolith.yml`文件定义了本地开发环境的多服务部署。它创建了一个名为
`sanbing-network`的自定义网络,并定义了`jcpp-node-0`服务,该服务使用`app.Dockerfile`
构建将容器的8080端口映射到宿主机并暴露了多个TCP端口38001等用于充电桩连接。
**容器化部署来源**
- [app.Dockerfile](file://docker/app.Dockerfile#L1-L47)
- [protocol.Dockerfile](file://docker/protocol.Dockerfile#L1-L47)
- [docker-compose.monolith.yml](file://docker/docker-compose.monolith.yml#L1-L29)
## 部署拓扑图
以下Mermaid图展示了JChargePointProtocol系统的部署拓扑和各组件间的连接关系。
```mermaid
graph TD
subgraph "客户端"
WebUI[jcpp-web-ui]
end
subgraph "应用服务层"
App[jcpp-app]
Protocol[jcpp-protocol-api]
end
subgraph "中间件"
Kafka[(Kafka)]
Redis[(Redis)]
PostgreSQL[(PostgreSQL)]
end
subgraph "设备层"
Charger[充电桩]
end
WebUI --> |HTTP/REST| App
App --> |gRPC| Protocol
Protocol --> |TCP| Charger
Protocol --> |Publish| Kafka
Kafka --> |Subscribe| App
App --> |读写| PostgreSQL
App --> |读写| Redis
```
**图示来源**
- [app.Dockerfile](file://docker/app.Dockerfile#L1-L47)
- [protocol.Dockerfile](file://docker/protocol.Dockerfile#L1-L47)
- [docker-compose.monolith.yml](file://docker/docker-compose.monolith.yml#L1-L29)
- [app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml#L1-L432)
- [protocol-service.yml](file://jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml#L1-L274)

View File

@@ -0,0 +1,401 @@
# JChargePointProtocol 数据流分析文档
<cite>
**本文档引用的文件**
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java)
- [TcpChannelHandler.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpChannelHandler.java)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java)
- [DownlinkController.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java)
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java)
- [UserController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/UserController.java)
- [DownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/DownlinkCallService.java)
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java)
- [uplink.proto](file://jcpp-infrastructure-proto/src/main/proto/uplink.proto)
- [downlink.proto](file://jcpp-infrastructure-proto/src/main/proto/downlink.proto)
- [grpc.proto](file://jcpp-infrastructure-proto/src/main/proto/grpc.proto)
</cite>
## 目录
1. [概述](#概述)
2. [上行数据流分析](#上行数据流分析)
3. [下行指令流分析](#下行指令流分析)
4. [消息序列化与传输](#消息序列化与传输)
5. [关键组件架构](#关键组件架构)
6. [数据流时序图](#数据流时序图)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [总结](#总结)
## 概述
JChargePointProtocol是一个基于Java的企业级充电桩通信协议框架采用微服务架构设计支持多种通信协议和消息传输机制。该系统主要包含两个核心数据流上行数据流充电桩→服务器和下行指令流服务器→充电桩通过TCP连接、Kafka消息队列和gRPC等多种技术实现高效可靠的消息传递。
## 上行数据流分析
### 数据流路径
上行数据流从充电桩设备开始,经过多个处理阶段最终到达业务服务层:
```mermaid
sequenceDiagram
participant Pile as 充电桩设备
participant TCP as TcpListener
participant Handler as TcpChannelHandler
participant Processor as ProtocolMessageProcessor
participant Kafka as KafkaForwarder
participant Consumer as ProtocolUplinkConsumerService
participant Service as DefaultPileService
Pile->>TCP : TCP原始数据包
TCP->>Handler : 解码后的ProtocolUplinkMsg
Handler->>Processor : 异步处理消息
Processor->>Kafka : 发布到Kafka Topic
Kafka->>Consumer : 从Kafka消费消息
Consumer->>Service : 调用业务服务处理
Service->>Service : 更新数据库状态
```
**图表来源**
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java#L30-L70)
- [TcpChannelHandler.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpChannelHandler.java#L99-L128)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L145-L169)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java#L120-L200)
### 关键处理节点
#### 1. TCP监听器层
TCP监听器负责建立与充电桩的网络连接处理原始字节流并将其转换为结构化的消息对象。
**节来源**
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java#L30-L70)
#### 2. 消息处理器层
消息处理器负责解析不同格式的上行消息字节数组、JSON、字符串并异步处理这些消息以提高系统吞吐量。
**节来源**
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L25-L45)
#### 3. Kafka转发层
Kafka转发器将处理后的消息发布到指定的Kafka主题支持Protobuf和JSON两种序列化格式并添加分布式追踪信息。
**节来源**
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L145-L169)
#### 4. 消费者服务层
消费者服务从Kafka队列中消费消息根据消息类型路由到相应的业务处理方法支持多种充电相关事件的处理。
**节来源**
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java#L120-L200)
### 消息类型与处理
上行消息包含多种类型,每种类型对应不同的业务场景:
| 消息类型 | 描述 | 处理方法 |
|--------------------------|---------|----------------------------|
| LoginRequest | 充电桩登录请求 | pileLogin |
| HeartBeatRequest | 心跳检测 | heartBeat |
| GunRunStatusProto | 枪运行状态 | postGunRunStatus |
| ChargingProgressProto | 充电进度 | postChargingProgress |
| TransactionRecordRequest | 交易记录 | onTransactionRecordRequest |
| BmsChargingErrorProto | BMS充电错误 | onBmsChargingErrorProto |
## 下行指令流分析
### 数据流路径
下行指令流从管理平台开始通过REST API或gRPC接口传递到目标充电桩
```mermaid
sequenceDiagram
participant Admin as 管理员
participant Controller as UserController
participant CallService as DownlinkCallService
participant GrpcService as DownlinkGrpcService
participant Processor as ProtocolMessageProcessor
participant TCP as TcpChannelHandler
participant Pile as 充电桩设备
Admin->>Controller : REST API请求
Controller->>CallService : 调用下行指令服务
CallService->>GrpcService : gRPC调用
GrpcService->>Processor : 封装下行消息
Processor->>TCP : 通过TCP发送
TCP->>Pile : 下行指令数据包
```
**图表来源**
- [UserController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/UserController.java#L30-L50)
- [DownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/DownlinkCallService.java#L72-L109)
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java#L123-L151)
- [TcpChannelHandler.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpChannelHandler.java#L110-L130)
### 关键处理节点
#### 1. 控制器层
控制器接收来自管理平台的REST API请求验证权限后调用相应的服务处理指令。
**节来源**
- [UserController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/UserController.java#L30-L50)
#### 2. 服务调用层
服务调用层负责选择合适的通信方式REST或gRPC将指令发送到目标节点。
**节来源**
- [DownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/DownlinkCallService.java#L72-L109)
#### 3. gRPC服务层
gRPC服务层处理双向流式通信接收来自客户端的下行指令并转发给相应的协议会话。
**节来源**
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java#L123-L151)
#### 4. 协议处理器层
协议处理器将下行指令封装为特定格式的消息并通过TCP连接发送给充电桩。
**节来源**
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L45-L65)
### 指令类型与处理
下行指令包含多种类型,支持远程控制充电桩的各种功能:
| 指令类型 | 描述 | 参数 |
|----------------------------|--------|--------------------------|
| RemoteStartChargingRequest | 远程启动充电 | pileCode, gunNo, tradeNo |
| RemoteStopChargingRequest | 远程停止充电 | pileCode, gunNo |
| SetPricingRequest | 设置计费策略 | pricingModel |
| RestartPileRequest | 重启充电桩 | type |
| TimeSyncRequest | 时间同步 | time |
## 消息序列化与传输
### Protobuf序列化
系统采用Google Protocol Buffers作为主要的消息序列化格式提供高效的二进制序列化和跨语言兼容性。
**节来源**
- [uplink.proto](file://jcpp-infrastructure-proto/src/main/proto/uplink.proto#L1-L50)
- [downlink.proto](file://jcpp-infrastructure-proto/src/main/proto/downlink.proto#L1-L50)
### Kafka传输机制
Kafka作为消息中间件提供高吞吐量、低延迟的消息传递能力
```mermaid
flowchart TD
A[ProtocolMessageProcessor] --> B{序列化类型}
B --> |Protobuf| C[二进制序列化]
B --> |JSON| D[JSON序列化]
C --> E[Kafka Producer]
D --> E
E --> F[Kafka Broker]
F --> G[ProtocolUplinkConsumerService]
G --> H[业务服务处理]
```
**图表来源**
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L169-L200)
### gRPC通信协议
gRPC提供高性能的双向流式通信支持实时指令下发
**节来源**
- [grpc.proto](file://jcpp-infrastructure-proto/src/main/proto/grpc.proto#L15-L35)
## 关键组件架构
### 系统架构概览
```mermaid
graph TB
subgraph "客户端层"
A[管理平台]
B[充电桩设备]
end
subgraph "传输层"
C[TCP连接]
D[gRPC服务]
E[Kafka集群]
end
subgraph "协议处理层"
F[TcpListener]
G[ProtocolMessageProcessor]
H[KafkaForwarder]
end
subgraph "业务服务层"
I[ProtocolUplinkConsumerService]
J[DefaultPileService]
K[业务逻辑处理]
end
A --> D
B --> C
C --> F
D --> G
F --> G
G --> H
H --> I
I --> J
J --> K
```
**图表来源**
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java#L30-L70)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L31-L71)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java#L60-L100)
### 组件职责分离
每个组件都有明确的职责边界,确保系统的可维护性和扩展性:
| 组件层级 | 主要职责 | 关键特性 |
|------|-----------|---------|
| 传输层 | 网络通信和消息路由 | 高并发、低延迟 |
| 协议层 | 协议解析和消息处理 | 可扩展、标准化 |
| 业务层 | 业务逻辑和状态管理 | 事务性、一致性 |
## 数据流时序图
### 完整数据流时序
```mermaid
sequenceDiagram
participant Pile as 充电桩
participant TCP as TcpListener
participant Handler as TcpChannelHandler
participant Processor as ProtocolMessageProcessor
participant Kafka as KafkaForwarder
participant Consumer as ProtocolUplinkConsumerService
participant Service as DefaultPileService
participant DB as 数据库
Note over Pile,DB : 上行数据流
Pile->>TCP : 发送原始数据包
TCP->>Handler : 接收并解码
Handler->>Processor : 异步处理消息
Processor->>Kafka : 发布到Kafka
Kafka->>Consumer : 消费消息
Consumer->>Service : 路由到业务方法
Service->>DB : 更新状态信息
Note over Pile,DB : 下行指令流
Admin->>Service : 发起指令请求
Service->>Processor : 创建下行消息
Processor->>TCP : 通过TCP发送
TCP->>Pile : 下发指令
```
**图表来源**
- [TcpChannelHandler.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpChannelHandler.java#L99-L128)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L145-L169)
- [ProtocolUplinkConsumerService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java#L120-L200)
### 消息头信息
消息在传输过程中携带重要的追踪和路由信息:
| 字段名称 | 类型 | 描述 | 示例值 |
|----------------------|--------|---------|-----------------|
| MSG_MD_TRACER_ID | String | 分布式追踪ID | "trace-12345" |
| MSG_MD_TRACER_ORIGIN | String | 追踪来源 | "jcpp-protocol" |
| MSG_MD_TRACER_TS | Long | 追踪时间戳 | 1640995200000 |
| MessageKey | String | 消息唯一标识 | "msg-uuid-123" |
## 性能考虑
### 异步处理机制
系统采用异步处理模式,避免阻塞主线程,提高整体吞吐量:
- **线程池管理**:使用分片线程池处理不同会话的消息
- **批量处理**:支持消息批处理以减少系统开销
- **背压控制**通过Kafka的缓冲机制防止系统过载
### 缓存策略
- **会话缓存**使用Caffeine本地缓存和Redis分布式缓存
- **配置缓存**:缓存充电桩配置信息减少数据库查询
- **状态缓存**:缓存充电桩状态信息支持快速查询
### 监控指标
系统提供丰富的监控指标用于性能分析:
- **消息统计**:吞吐量、延迟、错误率
- **连接监控**:活跃连接数、连接池状态
- **队列监控**Kafka队列积压、消费者滞后
## 故障排除指南
### 常见问题诊断
#### 1. 连接问题
- **症状**:充电桩无法连接到服务器
- **排查步骤**
- 检查TCP监听器状态
- 验证防火墙配置
- 确认端口可用性
#### 2. 消息丢失
- **症状**:部分消息未能到达目标
- **排查步骤**
- 检查Kafka分区分配
- 验证消费者组配置
- 监控消息序列化错误
#### 3. 性能问题
- **症状**:消息处理延迟过高
- **排查步骤**
- 分析线程池使用情况
- 检查数据库连接池
- 监控GC性能
### 日志分析
系统提供详细的日志记录,支持问题定位:
- **TRACE级别**:详细的流程跟踪
- **DEBUG级别**:调试信息和状态变更
- **INFO级别**:正常操作记录
- **WARN级别**:潜在问题警告
- **ERROR级别**:错误和异常信息
## 总结
JChargePointProtocol通过精心设计的多层架构实现了高效可靠的充电桩通信系统。上行数据流通过TCP连接接收充电桩状态信息经由Kafka消息队列异步处理后更新业务状态下行指令流通过REST
API或gRPC接口实现远程控制功能。整个系统采用Protobuf序列化、异步处理和分布式缓存等技术确保了高并发场景下的稳定性和性能。
系统的主要优势包括:
- **高可靠性**:多重备份和故障恢复机制
- **高性能**:异步处理和优化的序列化格式
- **可扩展性**:模块化设计支持功能扩展
- **可观测性**:完善的监控和日志体系
通过合理的设计和技术选型,该系统能够满足大规模充电桩网络的通信需求,为智能充电基础设施提供坚实的技术支撑。

View File

@@ -0,0 +1,234 @@
# 架构模式
<cite>
**本文档引用的文件**
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java)
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java)
- [Forwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/Forwarder.java)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java)
- [MemoryForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/MemoryForwarder.java)
- [AppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/AppQueueFactory.java)
- [KafkaAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/KafkaAppQueueFactory.java)
- [InMemoryAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/InMemoryAppQueueFactory.java)
- [ProtocolContext.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolContext.java)
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
- [LvnengV340LoginULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340LoginULCmd.java)
- [YunKuaiChongV150LoginULCmd.java](file://jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150LoginULCmd.java)
</cite>
## 目录
1. [引言](#引言)
2. [模板方法模式](#模板方法模式)
3. [策略模式](#策略模式)
4. [工厂模式](#工厂模式)
5. [六边形架构](#六边形架构)
6. [设计模式综合类图](#设计模式综合类图)
7. [结论](#结论)
## 引言
JChargePointProtocol
是一个用于处理充电桩通信协议的系统其架构设计体现了多种经典的设计模式。本文档深入分析了该系统中应用的四种核心设计模式模板方法模式、策略模式、工厂模式和六边形架构。这些模式共同构建了一个可扩展、可测试且松耦合的系统能够灵活支持多种充电桩通信协议如绿能V3.40、云快充V1.50等)。通过分析这些模式的具体实现,我们可以理解系统如何实现协议初始化的标准化、消息转发的灵活性、对象创建的解耦以及核心业务逻辑与外部适配器的清晰分离。
## 模板方法模式
模板方法模式在 JChargePointProtocol 中通过 `ProtocolBootstrap`
抽象基类实现。该模式定义了一个算法的骨架(固定流程),而将一些步骤的实现延迟到子类中,从而允许子类在不改变算法结构的情况下重新定义算法的某些特定步骤。
在本系统中,`ProtocolBootstrap` 类定义了协议服务启动和销毁的固定流程。其核心方法 `init()``destroy()` 使用了 Spring 框架的
`@PostConstruct``@PreDestroy` 注解,确保在 Spring 容器初始化和销毁 Bean 时自动执行。`init()`
方法的流程是固定的:首先记录初始化日志,然后从配置提供者加载协议配置,接着根据配置创建相应的 `Forwarder`(消息转发器)和
`Listener`(监听器),最后调用子类实现的 `_init()` 方法。同样,`destroy()` 方法也遵循固定流程:先销毁 `Listener`,再销毁
`Forwarder`,最后调用子类的 `_destroy()` 方法。
具体的协议实现类,如 `LvnengV340ProtocolBootstrap`,继承了 `ProtocolBootstrap` 并实现了其抽象方法。`getProtocolName()`
方法返回具体的协议名称(如 "LVNENG_V340"`messageProcessor()` 方法返回该协议专用的消息处理器(
`LvnengProtocolMessageProcessor`)。值得注意的是,`_init()``_destroy()` 方法在 `LvnengV340ProtocolBootstrap`
中为空实现这表明对于绿能V3.40协议,除了基类提供的标准初始化流程外,不需要额外的初始化或销毁逻辑。这种设计使得所有协议都遵循统一的生命周期管理,保证了系统的一致性和健壮性,同时为特定协议提供了扩展点。
**本节来源**
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L1-L126)
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L41)
## 策略模式
策略模式在 JChargePointProtocol 中通过 `Forwarder` 接口及其具体实现类 `KafkaForwarder``MemoryForwarder`
来体现。该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户端。
在本系统中,消息转发策略是核心功能之一。`Forwarder` 是一个抽象类,它定义了所有转发器必须实现的公共接口,如 `sendMessage()`
用于发送消息,`destroy()` 用于资源清理,以及 `health()` 用于健康检查。`Forwarder` 的构造函数接收通用的配置和依赖项,如
`StatsFactory` 用于统计、`PartitionProvider` 用于分区等。
具体的转发策略由其子类实现。`KafkaForwarder` 实现了通过 Kafka 消息队列进行消息转发的策略。它使用 KafkaProducer 将消息发送到指定的
Kafka 主题,并支持 JSON 或 Protobuf 编码。`MemoryForwarder` 则实现了内存队列的转发策略,它依赖于 `AppQueueFactory`
创建的内存生产者,将消息直接放入内存队列中。这两种策略的切换完全由配置文件决定。在 `ProtocolBootstrap``init()`
方法中,系统根据配置中的 `ForwarderType`kafka 或 memory来实例化相应的 `Forwarder`
子类。这种设计极大地提高了系统的灵活性,开发者可以在不修改核心代码的情况下,通过更改配置来切换消息传输机制,例如在开发和测试环境中使用内存队列以简化部署,在生产环境中使用
Kafka 以保证可靠性和可扩展性。
**本节来源**
- [Forwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/Forwarder.java#L1-L113)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java#L1-L200)
- [MemoryForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/MemoryForwarder.java#L1-L85)
## 工厂模式
工厂模式在 JChargePointProtocol 中通过 `AppQueueFactory` 接口及其具体实现类 `KafkaAppQueueFactory`
`InMemoryAppQueueFactory` 来实现。该模式提供了一种创建对象的接口,但由子类决定实例化哪一个类,从而将对象的创建与使用分离。
`AppQueueFactory` 是一个简单的工厂接口,它定义了两个方法:`createProtocolUplinkMsgConsumer()` 用于创建上行消息消费者,
`createProtocolUplinkMsgProducer(String topic)` 用于创建指定主题的上行消息生产者。这个接口是客户端(如 `ProtocolBootstrap`
)获取队列组件的统一入口。
具体的对象创建逻辑由实现了 `AppQueueFactory` 的工厂类完成。`KafkaAppQueueFactory` 负责创建基于 Kafka 的消费者和生产者。它的
`createProtocolUplinkMsgConsumer()` 方法会构建一个 `KafkaConsumerTemplate`,并配置 Kafka 的消费者设置、主题、客户端ID、反序列化器等。类似地
`createProtocolUplinkMsgProducer()` 方法会构建一个 `KafkaProducerTemplate``InMemoryAppQueueFactory`
则负责创建基于内存的消费者和生产者,它使用一个共享的 `InMemoryStorage` 实例来存储消息。
这两个工厂类的加载由 Spring 的条件注解 `@ConditionalOnExpression` 控制。当配置项 `queue.type` 为 "kafka" 时Spring 容器会创建
`KafkaAppQueueFactory` 的 Bean`queue.type` 为 "memory" 时,则创建 `InMemoryAppQueueFactory` 的 Bean。`ProtocolContext`
类通过依赖注入获得正确的 `AppQueueFactory` 实例。这种工厂模式的使用,使得 `ProtocolBootstrap` 等核心组件完全不知道具体创建的是
Kafka 还是内存队列,实现了与具体实现的彻底解耦,简化了代码并提高了可维护性。
**本节来源**
- [AppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/AppQueueFactory.java#L1-L20)
- [KafkaAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/KafkaAppQueueFactory.java#L1-L84)
- [InMemoryAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/InMemoryAppQueueFactory.java#L1-L50)
- [ProtocolContext.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolContext.java#L1-L65)
## 六边形架构
JChargePointProtocol
系统清晰地体现了六边形架构(也称为端口和适配器架构)的设计思想。该架构的核心是将系统的核心业务逻辑(领域)与外部系统(如数据库、消息队列、用户界面)分离开来,通过定义明确的“端口”(接口)进行通信,外部系统通过“适配器”来实现这些端口。
在本系统中,核心领域是协议处理逻辑,它独立于任何特定的传输或存储技术。`ProtocolMessageProcessor` 是核心领域的一个关键组件,它定义了处理上行(
`uplinkHandle`)和下行(`doDownlinkHandle`)消息的抽象方法。具体的协议实现(如 `LvnengProtocolMessageProcessor`
)继承此类并实现具体的业务逻辑。
外部适配器则负责与核心领域交互。例如,`TcpListener` 是一个适配器,它监听 TCP 端口,接收来自充电桩的原始字节流。当收到消息后,它通过
`ProtocolMessageProcessor` 的端口将消息传递给核心领域进行处理。另一个适配器是 `Forwarder`它作为核心领域与消息队列Kafka
或内存)之间的桥梁。当核心领域需要将处理结果转发给后端应用时,它调用 `Forwarder``sendMessage()` 方法,而具体的
`KafkaForwarder``MemoryForwarder` 适配器则负责与实际的消息队列系统进行通信。
REST 控制器(如 `DownlinkController`)也是一个适配器,它接收来自管理后台的 HTTP
请求,将其转换为内部消息,并通过核心领域的端口进行处理。这种架构的优势在于,核心业务逻辑不依赖于任何外部框架或技术。如果需要更换消息队列系统,只需编写一个新的
`Forwarder` 适配器并修改配置,而核心的协议处理代码无需改动。这极大地提升了系统的可测试性(可以轻松地为适配器编写模拟对象)和可维护性。
**本节来源**
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L77)
- [LvnengV340LoginULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340LoginULCmd.java#L1-L120)
- [YunKuaiChongV150LoginULCmd.java](file://jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150LoginULCmd.java#L1-L84)
## 设计模式综合类图
```mermaid
classDiagram
class ProtocolBootstrap {
+protocolContext : ProtocolContext
+protocolCfg : ProtocolCfg
+listener : Listener
+forwarder : Forwarder
+init() : void
+destroy() : void
+health() : Health
+getProtocolName() : String
+_init() : void
+_destroy() : void
+messageProcessor() : ProtocolMessageProcessor
}
class LvnengV340ProtocolBootstrap {
+PROTOCOL_NAME : String
+getProtocolName() : String
+_init() : void
+_destroy() : void
+messageProcessor() : ProtocolMessageProcessor
}
class Forwarder {
+protocolName : String
+forwarderMessagesStats : MessagesStats
+partitionProvider : PartitionProvider
+serviceInfoProvider : ServiceInfoProvider
+isMonolith : boolean
+producer : QueueProducer
+health() : Health
+destroy() : void
+sendMessage(msg : UplinkQueueMessage) : void
+sendMessage(msg : UplinkQueueMessage, consumer : BiConsumer) : void
}
class KafkaForwarder {
+kafkaCfg : KafkaCfg
+jcppPartition : boolean
+kafkaProducer : KafkaProducer
+KafkaForwarder(...)
+health() : Health
+destroy() : void
+sendMessage(...) : void
}
class MemoryForwarder {
+memoryCfg : MemoryCfg
+MemoryForwarder(...)
+health() : Health
+destroy() : void
+sendMessage(...) : void
}
class AppQueueFactory {
+createProtocolUplinkMsgConsumer() : QueueConsumer
+createProtocolUplinkMsgProducer(topic : String) : QueueProducer
}
class KafkaAppQueueFactory {
+kafkaSettings : KafkaSettings
+appSettings : QueueAppSettings
+consumerStatsService : KafkaConsumerStatsService
+serviceInfoProvider : ServiceInfoProvider
+appAdmin : QueueAdmin
+KafkaAppQueueFactory(...)
+createProtocolUplinkMsgConsumer() : QueueConsumer
+createProtocolUplinkMsgProducer(topic : String) : QueueProducer
}
class InMemoryAppQueueFactory {
+storage : InMemoryStorage
+appSettings : QueueAppSettings
+InMemoryAppQueueFactory(...)
+createProtocolUplinkMsgConsumer() : QueueConsumer
+createProtocolUplinkMsgProducer(topic : String) : QueueProducer
}
class ProtocolMessageProcessor {
+forwarder : Forwarder
+protocolContext : ProtocolContext
+uplinkHandleAsync(...) : void
+uplinkHandle(...) : void
+downlinkHandle(...) : void
+doDownlinkHandle(...) : void
}
ProtocolBootstrap <|-- LvnengV340ProtocolBootstrap : "extends"
ProtocolBootstrap o-- Forwarder : "uses"
ProtocolBootstrap o-- Listener : "uses"
Forwarder <|-- KafkaForwarder : "extends"
Forwarder <|-- MemoryForwarder : "extends"
AppQueueFactory <|-- KafkaAppQueueFactory : "implements"
AppQueueFactory <|-- InMemoryAppQueueFactory : "implements"
ProtocolMessageProcessor o-- Forwarder : "uses"
ProtocolMessageProcessor o-- ProtocolContext : "uses"
```
**图示来源**
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java)
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java)
- [Forwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/Forwarder.java)
- [KafkaForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/KafkaForwarder.java)
- [MemoryForwarder.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/forwarder/MemoryForwarder.java)
- [AppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/AppQueueFactory.java)
- [KafkaAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/KafkaAppQueueFactory.java)
- [InMemoryAppQueueFactory.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/InMemoryAppQueueFactory.java)
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
## 结论
JChargePointProtocol
通过巧妙地组合使用模板方法模式、策略模式、工厂模式和六边形架构,构建了一个高度模块化、可扩展且易于维护的系统。模板方法模式确保了所有协议服务生命周期的一致性;策略模式提供了消息转发机制的灵活切换;工厂模式实现了对象创建的解耦;而六边形架构则清晰地划分了核心业务逻辑与外部依赖。这些设计模式的协同作用,使得系统能够轻松地支持新的充电桩协议,同时保持核心代码的稳定性和可测试性。这种架构设计为处理复杂、多变的物联网通信场景提供了一个优秀的实践范例。

View File

@@ -0,0 +1,198 @@
# 架构设计
<cite>
**本文档引用的文件**
- [jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java)
- [jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/BaseController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/BaseController.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/ProtocolController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/ProtocolController.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java)
- [jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaProducerTemplate.java](file://jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaProducerTemplate.java)
- [jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/JCPPRedisCacheConfiguration.java](file://jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/JCPPRedisCacheConfiguration.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/GrpcDownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/GrpcDownlinkCallService.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/RestDownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/RestDownlinkCallService.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java)
</cite>
## 目录
1. [简介](#简介)
2. [微服务架构划分](#微服务架构划分)
3. [六边形架构实现](#六边形架构实现)
4. [数据流分析](#数据流分析)
5. [系统上下文图](#系统上下文图)
6. [组件交互图](#组件交互图)
7. [架构决策与权衡](#架构决策与权衡)
8. [结论](#结论)
## 简介
JChargePointProtocol
是一个高性能、分布式、支持海量并发量的充电桩服务端系统,旨在为充电应用提供基础能力。该系统采用微服务架构设计,支持多种充电桩协议(如云快充、绿能等),并通过清晰的职责划分和现代化的技术栈实现高可扩展性和可维护性。本文档详细描述了系统的架构设计,包括微服务划分、六边形架构的实现、数据流处理以及关键的架构决策。
**本节不涉及具体源文件分析,因此无来源信息**
## 微服务架构划分
JChargePointProtocol 系统主要划分为两个核心微服务域:`jcpp-app``jcpp-protocol-*`,每个服务域都有明确的职责边界。
`jcpp-app` 服务作为业务逻辑与API网关的核心负责处理所有与业务相关的操作。它暴露RESTful
API接口供前端应用和其他外部系统调用处理用户认证、权限控制、业务规则验证等横切关注点。该服务还负责与数据库进行交互执行数据的持久化和查询操作并通过缓存机制提升系统性能。从架构角度看
`jcpp-app` 是系统的业务中枢,协调各个业务实体(如充电桩、枪口、站点等)的状态和行为。
`jcpp-protocol-*` 服务域则专注于协议处理的核心功能,包括 `jcpp-protocol-api``jcpp-protocol-yunkuaichong`
`jcpp-protocol-lvneng`
等模块。这些服务负责处理与充电桩设备的底层通信解析和生成特定协议格式的报文。它们通过TCP长连接与设备保持通信处理上行数据的解码和下行指令的编码。这种分离使得协议相关的复杂性被封装在独立的服务中便于针对不同协议进行独立开发、测试和部署。
这种架构划分实现了关注点分离的原则:`jcpp-app` 专注于业务领域逻辑,而 `jcpp-protocol-*`
专注于通信协议细节。两者通过定义良好的接口如Kafka消息队列和gRPC调用进行通信降低了系统耦合度提高了可维护性和可扩展性。
**本节不涉及具体源文件分析,因此无来源信息**
## 六边形架构实现
JChargePointProtocol 系统在代码层面体现了六边形架构(端口与适配器)的设计思想,将核心业务逻辑与外部系统依赖进行解耦。
在该架构中,**控制器Controller作为输入适配器**,负责将外部请求适配到内部业务逻辑。例如,`PileController` 类(位于
`jcpp-app`
模块作为充电桩管理的输入适配器接收HTTP请求将其转换为内部服务方法调用。它处理请求参数的验证、异常的统一处理并将内部服务的响应转换为HTTP响应格式。这种设计使得核心业务逻辑不受HTTP协议和框架的约束可以轻松替换或扩展不同的输入方式如gRPC、消息队列等
**仓库Repository作为输出适配器**,负责将内部业务逻辑与数据存储系统进行解耦。例如,`PileRepository`
接口定义了访问充电桩数据的契约,而具体的实现类(如 `PileRepositoryImpl`
则负责与MyBatis框架和PostgreSQL数据库进行交互。此外系统还通过多级缓存Caffeine本地缓存和Redis分布式缓存作为另一种输出适配器
`AttributeRedisCache``PileCaffeineCache` 等类实现了对缓存系统的访问。这种分层设计使得核心业务逻辑无需关心数据存储的具体实现,可以在不影响业务逻辑的情况下更换数据库或缓存方案。
六边形架构的核心在于将业务逻辑置于中心,所有外部依赖都通过适配器与之交互。这种设计极大地提高了代码的可测试性,因为核心业务逻辑可以在不依赖数据库、网络等外部资源的情况下进行单元测试。同时,它也增强了系统的灵活性,使得系统能够更容易地适应变化,例如支持新的通信协议或更换消息中间件。
**Section sources**
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/BaseController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/BaseController.java#L1-L117)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L1-L112)
- [jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java#L1-L17)
## 数据流分析
JChargePointProtocol 系统的数据流设计清晰地分离了上行uplink和下行downlink两个方向确保了数据处理的高效性和可靠性。
### 上行数据流Uplink
上行数据流始于充电桩设备通过TCP连接发送原始报文。`jcpp-protocol-*` 服务中的 `TcpListener` 组件接收这些字节流,并通过
`TcpMsgDecoder` 进行解码,将其转换为结构化的 `ProtocolUplinkMsg` 对象。随后,`ProtocolMessageProcessor`
`uplinkHandleAsync` 方法被调用该方法在独立的线程池中异步处理上行消息以避免阻塞IO线程。处理后的业务数据通过Kafka消息队列发布
`jcpp-app` 服务中的 `ProtocolUplinkConsumerService` 作为消费者订阅这些消息进行业务逻辑处理如状态更新、计费计算等最终将结果持久化到PostgreSQL数据库中。
### 下行数据流Downlink
下行数据流始于 `jcpp-app` 服务中的业务操作例如用户通过API请求启动充电。`RpcController` 接收该请求,调用
`PileProtocolService` 服务。该服务通过内部调用决定使用gRPC还是REST方式与 `jcpp-protocol-*` 服务通信。如果使用gRPC
`GrpcDownlinkCallService` 被调用,通过 `DownlinkGrpcClient` 发送 `DownlinkRequestMessage`如果使用REST
`RestDownlinkCallService` 通过 `RestTemplate` 发送HTTP请求到 `DownlinkController``jcpp-protocol-*` 服务接收到下行指令后,
`ProtocolMessageProcessor``doDownlinkHandle` 方法将其编码为特定协议的字节流并通过TCP通道发送到目标充电桩设备。
这种基于消息队列和RPC调用的异步通信模式不仅解耦了业务处理和协议处理还提供了良好的可伸缩性和容错能力。Kafka作为消息中间件保证了上行消息的可靠传递和顺序性。
**Section sources**
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L78)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L1-L197)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/GrpcDownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/GrpcDownlinkCallService.java#L1-L51)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/RestDownlinkCallService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/RestDownlinkCallService.java#L1-L64)
## 系统上下文图
```mermaid
graph TD
subgraph "外部系统"
User[用户]
ChargingPile[充电桩设备]
end
subgraph "JChargePointProtocol系统"
subgraph "jcpp-app"
APIGateway[API网关]
BusinessLogic[业务逻辑]
Database[(PostgreSQL)]
Cache[(Redis)]
end
subgraph "jcpp-protocol-*"
ProtocolAPI[协议API]
Kafka[(Kafka消息队列)]
TCP[TCP通信]
end
end
User --> |HTTP/HTTPS| APIGateway
APIGateway --> BusinessLogic
BusinessLogic --> Database
BusinessLogic --> Cache
BusinessLogic --> |gRPC/REST| ProtocolAPI
ProtocolAPI --> Kafka
ChargingPile --> |TCP| TCP
TCP --> ProtocolAPI
ProtocolAPI --> |发布消息| Kafka
Kafka --> |订阅消息| BusinessLogic
```
**Diagram sources**
- [jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java#L1-L55)
- [jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java#L1-L59)
## 组件交互图
```mermaid
sequenceDiagram
participant User as "用户"
participant AppController as "jcpp-app<br/>Controller"
participant AppService as "jcpp-app<br/>Service"
participant ProtocolAPI as "jcpp-protocol-*<br/>DownlinkController"
participant ProtocolProcessor as "jcpp-protocol-*<br/>ProtocolMessageProcessor"
participant Device as "充电桩设备"
User->>AppController : 发送启动充电请求
AppController->>AppService : 调用业务服务
AppService->>ProtocolAPI : gRPC/REST调用
ProtocolAPI->>ProtocolProcessor : 处理下行指令
ProtocolProcessor->>Device : 通过TCP发送协议报文
Device-->>ProtocolProcessor : 发送上行响应
ProtocolProcessor->>Kafka : 发布上行消息
Kafka-->>AppService : 消费上行消息
AppService-->>AppController : 返回处理结果
AppController-->>User : 返回响应
```
**Diagram sources**
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L1-L197)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkController.java#L1-L76)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L78)
## 架构决策与权衡
JChargePointProtocol 系统在架构设计上做出了一系列关键决策,这些决策背后体现了对性能、可靠性、可维护性和可扩展性的权衡。
### 选择Kafka而非RabbitMQ
系统选择Kafka作为消息中间件主要基于其在高吞吐量和持久化方面的优势。充电桩系统需要处理海量的上行数据如实时状态、充电记录等Kafka的分布式架构和分区机制能够轻松应对每秒数万条消息的吞吐量需求。其基于日志的存储模型提供了强大的消息持久化能力确保即使在消费者处理失败的情况下消息也不会丢失。相比之下RabbitMQ虽然在消息路由和灵活性上更胜一筹但在处理大规模、高频率的流式数据时其性能和扩展性可能成为瓶颈。Kafka的“发布-订阅”模型也更符合本系统中“一个上行消息可能被多个下游服务消费”的场景。
### 多级缓存策略
系统采用了多级缓存策略Caffeine +
Redis来平衡性能和一致性。Caffeine作为本地缓存提供了极低的访问延迟纳秒级用于缓存高频访问且不常变更的数据如充电桩配置。Redis作为分布式缓存解决了多实例部署下的数据共享问题。当本地缓存未命中时系统会查询Redis。这种设计显著减少了对数据库的直接访问提升了系统整体性能。然而这也引入了缓存一致性挑战。系统通过事件驱动的方式
`AttributeCacheEvictEvent`)来处理缓存失效,当数据在数据库中被更新时,会发布缓存清除事件,通知所有节点清除本地缓存,从而在一定程度上保证了数据的一致性。这种权衡是在极致性能和强一致性之间找到的平衡点。
### gRPC与REST的并存
系统同时支持gRPC和REST两种服务间通信方式通过配置项 `service.downlink.rpc.type`
进行动态切换。这为系统部署提供了灵活性在对性能要求极高的内部网络中可以选择高效的二进制协议gRPC而在需要与外部系统集成或调试时可以选择更通用的RESTful
API。这种设计虽然增加了实现的复杂性需要维护两套客户端但极大地提升了系统的适应性和可集成性。
**本节不涉及具体源文件分析,因此无来源信息**
## 结论
JChargePointProtocol 系统通过清晰的微服务划分、六边形架构的实践、高效的数据流设计以及深思熟虑的架构决策,构建了一个高性能、高可扩展且易于维护的充电桩服务端平台。
`jcpp-app``jcpp-protocol-*`
服务域的职责分离确保了业务逻辑与协议细节的解耦。六边形架构的实现使得核心业务逻辑独立于外部框架和依赖。基于Kafka的消息队列和多级缓存策略有效解决了海量数据处理和性能瓶颈问题。整体架构设计充分考虑了实际业务场景的需求在性能、可靠性、可维护性之间取得了良好的平衡为支持更多充电桩协议和更大规模的部署奠定了坚实的基础。
**本节不涉及具体源文件分析,因此无来源信息**