添加:ZHub 管理接口文档和客户端使用指南
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "完成 ZHub 服务安装后,来看看一遍就会的基础使用文档~"
|
||||
"description": "ZHub 基础功能使用指南,包含连接创建、发布订阅、RPC调用等核心功能"
|
||||
}
|
||||
}
|
||||
|
||||
112
docs/tutorial-basics/broadcast-delay.md
Normal file
112
docs/tutorial-basics/broadcast-delay.md
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: 广播与延时消息
|
||||
description: ZHub 广播消息和延时消息功能详解,包含基础使用、应用场景和注意事项
|
||||
---
|
||||
|
||||
# 广播与延时消息
|
||||
|
||||
## 广播消息
|
||||
|
||||
广播消息发送给所有连接的客户端。
|
||||
|
||||
### 基础使用
|
||||
|
||||
**字符串广播**:
|
||||
```java
|
||||
// 发送广播
|
||||
zhub.broadcast("topic-abc", "hello!");
|
||||
|
||||
// 订阅广播
|
||||
zhub.subscribe("topic-abc", message -> {
|
||||
System.out.println("收到公告: " + message);
|
||||
});
|
||||
```
|
||||
|
||||
**类型化广播**:
|
||||
```java
|
||||
// 定义通知类型
|
||||
public class SystemNotification {
|
||||
private String type;
|
||||
private String title;
|
||||
private String content;
|
||||
private long timestamp;
|
||||
// getter/setter...
|
||||
}
|
||||
|
||||
// 发送类型化广播
|
||||
SystemNotification notification = new SystemNotification(
|
||||
"maintenance", "hello!", "hello!", System.currentTimeMillis()
|
||||
);
|
||||
zhub.broadcast("topic-abc", notification);
|
||||
|
||||
// 订阅类型化广播
|
||||
zhub.subscribe("topic-abc", new TypeToken<SystemNotification>(){}, notification -> {
|
||||
System.out.println("通知: " + notification.getTitle());
|
||||
});
|
||||
```
|
||||
|
||||
### 应用场景
|
||||
|
||||
**示例场景**:
|
||||
```java
|
||||
zhub.broadcast("topic-abc", "hello!");
|
||||
zhub.broadcast("topic-def", "hello!");
|
||||
```
|
||||
|
||||
**配置更新**:
|
||||
```java
|
||||
zhub.broadcast("topic-xyz", "hello!");
|
||||
zhub.subscribe("topic-xyz", message -> updateConfig(message));
|
||||
```
|
||||
|
||||
**状态同步**:
|
||||
```java
|
||||
zhub.broadcast("topic-123", "hello!");
|
||||
zhub.subscribe("topic-123", message -> System.out.println("状态: " + message));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 延时消息
|
||||
|
||||
延时消息在指定时间后发送,支持毫秒级精度。
|
||||
|
||||
### 基础使用
|
||||
|
||||
```java
|
||||
// 延时5秒
|
||||
zhub.delay("reminder-task", "执行提醒任务", 5000);
|
||||
|
||||
// 延时1小时
|
||||
zhub.delay("cleanup-task", "执行清理任务", 60 * 60 * 1000);
|
||||
|
||||
// 延时1天
|
||||
zhub.delay("report-generate", "生成日报", 24 * 60 * 60 * 1000);
|
||||
```
|
||||
|
||||
### 应用场景
|
||||
|
||||
**任务提醒**:
|
||||
```java
|
||||
zhub.delay("task-reminder", "任务即将到期", 5 * 60 * 1000);
|
||||
zhub.subscribe("task-reminder", message -> sendReminder(message));
|
||||
```
|
||||
|
||||
**订单超时**:
|
||||
```java
|
||||
zhub.delay("order-timeout-check", orderId, 30 * 60 * 1000);
|
||||
zhub.subscribe("order-timeout-check", orderId -> checkOrderTimeout(orderId));
|
||||
```
|
||||
|
||||
**缓存过期**:
|
||||
```java
|
||||
zhub.delay("cache-expire", key, expireMs);
|
||||
zhub.subscribe("cache-expire", key -> cache.remove(key));
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 延时时间不限制延迟时间
|
||||
- 重启后延时消息丢失
|
||||
- 广播消息影响所有客户端性能
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 广播消息
|
||||
description: 发送、接收广播消息
|
||||
---
|
||||
|
||||
:::tip
|
||||
消息接收
|
||||
广播消息的消息接收,与主题消息、延时消息 api一致,且使用了相同 topic 命名空间
|
||||
|
||||
- 消息接收
|
||||
- 广播消息发送
|
||||
|
||||
:::
|
||||
|
||||
## 消息接收
|
||||
|
||||
> [广播消息接收](publish-subscribe.md#订阅主题消息)
|
||||
|
||||
## 广播消息发送
|
||||
|
||||
> 和发布订阅消息基本差不多
|
||||
|
||||
```java
|
||||
private ZHubClient zhub;
|
||||
|
||||
@RestMapping(name = "publish_test", auth = false, comment = "发送广播消息测试")
|
||||
public String publishTest(String value) {
|
||||
zhub.broadcast("topic-a", value);
|
||||
return "send ok!";
|
||||
}
|
||||
```
|
||||
@@ -1,60 +1,177 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
sidebar_position: 1
|
||||
title: 创建连接
|
||||
description: 初始化客户端连接对象
|
||||
---
|
||||
|
||||
:::tip
|
||||
目前已提供三种客户端连接使用
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
- Java 项目
|
||||
- [普通 Java 项目](#java通用)
|
||||
- [使用 Redkale 的 Java 项目](#redkale框架-项目里面使用)
|
||||
- [Golang 项目](#golang-项目中使用)
|
||||
## 支持的框架
|
||||
|
||||
:::
|
||||
普通Java、SpringBoot、Redkale、Golang
|
||||
|
||||
---
|
||||
|
||||
## Java通用
|
||||
|
||||
> 在Java 项目中引入 zhub-client.jar
|
||||
<Tabs>
|
||||
<TabItem value="java" label="普通Java项目" default>
|
||||
|
||||
```java
|
||||
private ZHubClient zhub;
|
||||
private ZHubClient zhub;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
// 参数说明:① ip:端⼝, ②消费者组名称, ③项⽬实例名(名称需全局唯⼀)④授权码
|
||||
zhub = new ZHubClient("127.0.0.1:6066", "test-hub", "DEV-LOCAL", "user@pwd123");
|
||||
@Before
|
||||
public void init() {
|
||||
// 参数:地址、组名、appid(唯一)、token
|
||||
zhub = new ZHubClient("127.0.0.1:1216", "test-hub", "DEV-LOCAL-001", "token-12345");
|
||||
}
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- `appid` 必须唯一,RPC 消息回复使用此标识
|
||||
- `groupid` 协同消费组,同组内只有一个消费者处理消息
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="spring" label="SpringBoot项目">
|
||||
|
||||
**1. 依赖**
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>dev.zhub</groupId>
|
||||
<artifactId>zhub-client-spring</artifactId>
|
||||
<version>0.1.0424.dev</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**2. 配置 application.yml**
|
||||
```yaml
|
||||
zhub:
|
||||
addr: 127.0.0.1:1216
|
||||
groupid: spring-boot-app
|
||||
appid: spring-boot-001 # 必须唯一
|
||||
auth: token-12345
|
||||
```
|
||||
|
||||
**3. 配置类**
|
||||
```java
|
||||
@Configuration
|
||||
public class ZHubConfig {
|
||||
@Value("${zhub.addr}") private String addr;
|
||||
@Value("${zhub.groupid}") private String groupId;
|
||||
@Value("${zhub.appid}") private String appId;
|
||||
@Value("${zhub.auth}") private String auth;
|
||||
|
||||
@Bean
|
||||
public ZHubClient zhubClient() {
|
||||
return new ZHubClient(addr, groupId, appId, auth);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Redkale框架 项目里面使用
|
||||
|
||||
> 在Java的redkale 项目中引入 zhub-rekale.jar
|
||||
> 在配置文件中配置zhub组件
|
||||
|
||||
**4. 使用**
|
||||
```java
|
||||
@Service
|
||||
public class UserService {
|
||||
@Autowired
|
||||
private ZHubClient zhub;
|
||||
|
||||
public void publishEvent(String userId, String event) {
|
||||
zhub.publish("user-event", "{\"userId\":\"" + userId + "\",\"event\":\"" + event + "\"}");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
zhub.subscribe("user-notification", message -> {
|
||||
System.out.println("通知: " + message);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
# source.properties 中配置
|
||||
############ ClusterSource @Resource(name="hub") ############
|
||||
redkale.cluster.zhub[hub].addr = 127.0.0.1:6066
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="redkale" label="Redkale项目">
|
||||
|
||||
**配置文件**:
|
||||
```properties
|
||||
# source.properties
|
||||
redkale.cluster.zhub[hub].addr = 127.0.0.1:1216
|
||||
redkale.cluster.zhub[hub].auth = user@pwd123
|
||||
redkale.cluster.zhub[hub].groupid = test-hub
|
||||
```
|
||||
|
||||
> 在 service 中注入组件
|
||||
>
|
||||
|
||||
**使用**:
|
||||
```java
|
||||
@Resource(name = "hub")
|
||||
protected ZHubClient zhub;
|
||||
@Resource(name = "hub")
|
||||
protected ZHubClient zhub;
|
||||
```
|
||||
|
||||
## Golang 项目中使用
|
||||
</TabItem>
|
||||
<TabItem value="golang" label="Golang项目">
|
||||
|
||||
> 待补充
|
||||
```go
|
||||
// Golang 连接示例
|
||||
// TODO: 待补充
|
||||
```
|
||||
|
||||
---
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
|
||||
## 使用示例
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="subscribe" label="基础订阅" default>
|
||||
|
||||
```java
|
||||
// 单个主题
|
||||
zhub.subscribe("user-login", message -> System.out.println("登录: " + message));
|
||||
|
||||
// 类型化消息(使用TypeToken)
|
||||
zhub.subscribe("user-profile", new TypeToken<UserProfile>(){}, profile ->
|
||||
System.out.println("用户: " + profile.getUsername()));
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="multi" label="多主题订阅">
|
||||
|
||||
```java
|
||||
// 逗号分隔
|
||||
zhub.subscribe("user-login,user-logout,user-register", message ->
|
||||
System.out.println("用户操作: " + message));
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="publish" label="发布消息">
|
||||
|
||||
```java
|
||||
// 字符串消息
|
||||
zhub.publish("user-login", "用户ID: 12345");
|
||||
|
||||
// 类型化消息
|
||||
UserProfile profile = new UserProfile("12345", "张三", "zhangsan@example.com");
|
||||
zhub.publish("user-profile", profile);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 异步处理
|
||||
```java
|
||||
// 避免阻塞消息处理
|
||||
zhub.subscribe("topic-abc", message -> {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
processMessage(message);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
```java
|
||||
zhub.subscribe("topic-abc", message -> {
|
||||
try {
|
||||
processMessage(message);
|
||||
} catch (Exception e) {
|
||||
logger.error("消息处理失败", e);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: 延时消息
|
||||
description: zhub 的延时消息使用
|
||||
---
|
||||
|
||||
:::tip
|
||||
|
||||
首先完成 **[连接创建](create-connection.md)** ,便可进行**延时消息**的发送和接收,
|
||||
|
||||
- [订阅主题消息](#订阅主题消息)
|
||||
- [发送延时消息](#发送延时消息)
|
||||
|
||||
:::
|
||||
|
||||
## 订阅主题消息
|
||||
|
||||
> 见 [主题的订阅](publish-subscribe.md#订阅主题消息)
|
||||
|
||||
## 发送延时消息
|
||||
|
||||
> 参数说明:①主题名称 ②消息内容 ③延时多久,单位ms
|
||||
> zhub.delay("topic-delay-a", "delay-value", 1000);
|
||||
>
|
||||
|
||||
示例代码:
|
||||
```java
|
||||
private ZHubClient zhub;
|
||||
|
||||
@RestMapping(name = "delay_test", auth = false, comment = "发送延时主题消息测试")
|
||||
public String delayTest(String value) {
|
||||
zhub.delay("topic-delay-a", "delay-value", 1000);
|
||||
return "send ok!";
|
||||
}
|
||||
```
|
||||
242
docs/tutorial-basics/golang-connection.md
Normal file
242
docs/tutorial-basics/golang-connection.md
Normal file
@@ -0,0 +1,242 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: Golang 连接
|
||||
description: 在 Go 项目中使用 ZHub 客户端
|
||||
---
|
||||
|
||||
# Golang 项目中使用
|
||||
|
||||
> 在 Go 项目中使用 ZHub 客户端
|
||||
|
||||
---
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
go get github.com/your-org/zhub-client-go
|
||||
```
|
||||
|
||||
:::info 说明
|
||||
Go 客户端的实际包名请以官方发布为准,此处仅为示例
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 基础连接
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"github.com/your-org/zhub-client-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建 ZHub 客户端
|
||||
client := zhub.NewClient("127.0.0.1:1216", "go-group", "go-app-001", "token-12345")
|
||||
|
||||
// 连接服务
|
||||
err := client.Connect()
|
||||
if err != nil {
|
||||
log.Fatal("连接失败:", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
log.Println("ZHub 连接成功")
|
||||
}
|
||||
```
|
||||
|
||||
**参数说明**:
|
||||
- `127.0.0.1:1216`: 服务端地址
|
||||
- `go-group`: 消费者组名称
|
||||
- `go-app-001`: 应用实例ID(必须唯一)
|
||||
- `token-12345`: 认证令牌(开启权限验证时)
|
||||
|
||||
---
|
||||
|
||||
## 基础使用
|
||||
|
||||
### 发布订阅
|
||||
|
||||
```go
|
||||
// 订阅消息
|
||||
client.Subscribe("user-login", func(message string) {
|
||||
log.Println("收到消息:", message)
|
||||
})
|
||||
|
||||
// 发布消息
|
||||
err := client.Publish("user-login", "用户登录")
|
||||
if err != nil {
|
||||
log.Println("发布失败:", err)
|
||||
}
|
||||
```
|
||||
|
||||
### 广播消息
|
||||
|
||||
```go
|
||||
// 广播消息给所有客户端
|
||||
err := client.Broadcast("topic-abc", "hello!")
|
||||
if err != nil {
|
||||
log.Println("广播失败:", err)
|
||||
}
|
||||
```
|
||||
|
||||
### RPC 调用
|
||||
|
||||
```go
|
||||
// 服务端:提供 RPC 服务
|
||||
client.RpcSubscribe("user-get-info", func(request string) string {
|
||||
return "用户信息: " + request
|
||||
})
|
||||
|
||||
// 客户端:调用 RPC 服务
|
||||
result, err := client.Rpc("user-get-info", "user123")
|
||||
if err != nil {
|
||||
log.Println("RPC 失败:", err)
|
||||
} else {
|
||||
log.Println("RPC 结果:", result)
|
||||
}
|
||||
```
|
||||
|
||||
### 延时消息
|
||||
|
||||
```go
|
||||
// 延时5秒发送消息
|
||||
err := client.Delay("task-reminder", "任务提醒", 5000)
|
||||
if err != nil {
|
||||
log.Println("延时消息失败:", err)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 完整示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
"github.com/your-org/zhub-client-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建客户端
|
||||
client := zhub.NewClient("127.0.0.1:1216", "go-demo", "go-demo-001", "token-12345")
|
||||
|
||||
// 连接服务
|
||||
err := client.Connect()
|
||||
if err != nil {
|
||||
log.Fatal("连接失败:", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
log.Println("ZHub 连接成功")
|
||||
|
||||
// 订阅消息
|
||||
client.Subscribe("user-login", func(message string) {
|
||||
log.Println("收到用户登录消息:", message)
|
||||
})
|
||||
|
||||
// 发布消息
|
||||
err = client.Publish("user-login", "用户ID: 12345")
|
||||
if err != nil {
|
||||
log.Println("发布失败:", err)
|
||||
}
|
||||
|
||||
// 广播消息
|
||||
err = client.Broadcast("topic-abc", "hello!")
|
||||
if err != nil {
|
||||
log.Println("广播失败:", err)
|
||||
}
|
||||
|
||||
// 延时消息
|
||||
err = client.Delay("task-reminder", "任务提醒", 5000)
|
||||
if err != nil {
|
||||
log.Println("延时消息失败:", err)
|
||||
}
|
||||
|
||||
// 提供 RPC 服务
|
||||
client.RpcSubscribe("user-get-info", func(userId string) string {
|
||||
return "用户信息: " + userId
|
||||
})
|
||||
|
||||
// 调用 RPC 服务
|
||||
result, err := client.Rpc("user-get-info", "user123")
|
||||
if err != nil {
|
||||
log.Println("RPC 失败:", err)
|
||||
} else {
|
||||
log.Println("RPC 结果:", result)
|
||||
}
|
||||
|
||||
// 保持程序运行
|
||||
time.Sleep(time.Minute)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
### 1. AppID 唯一性
|
||||
|
||||
:::warning 重要
|
||||
- **每个客户端必须使用不同的 appid**
|
||||
- RPC 通讯消息回复地址使用 appid 标识
|
||||
- 相同 appid 会导致 RPC 消息回复找不到目标客户端
|
||||
:::
|
||||
|
||||
**推荐命名规则**:
|
||||
- `go-service-001`
|
||||
- `go-worker-002`
|
||||
- `go-gateway-001`
|
||||
|
||||
### 2. 错误处理
|
||||
|
||||
```go
|
||||
// 建议的错误处理方式
|
||||
if err := client.Publish("topic-abc", "message"); err != nil {
|
||||
log.Printf("发布消息失败: %v", err)
|
||||
// 根据业务需要决定是否重试
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 连接管理
|
||||
|
||||
```go
|
||||
// 检查连接状态
|
||||
if !client.IsConnected() {
|
||||
log.Println("客户端未连接")
|
||||
return
|
||||
}
|
||||
|
||||
// 重连机制
|
||||
for {
|
||||
if !client.IsConnected() {
|
||||
err := client.Connect()
|
||||
if err != nil {
|
||||
log.Printf("重连失败: %v", err)
|
||||
time.Sleep(time.Second * 5)
|
||||
continue
|
||||
}
|
||||
log.Println("重连成功")
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 版本信息
|
||||
|
||||
- **客户端版本**: 待发布
|
||||
- **支持 Go 版本**: 1.19+
|
||||
- **包管理**: go mod
|
||||
|
||||
:::info 说明
|
||||
- Go 客户端提供基础的发布订阅、广播、RPC 功能
|
||||
- 连接参数与 Java 客户端保持一致
|
||||
- 详细 API 请参考客户端源码文档
|
||||
:::
|
||||
214
docs/tutorial-basics/pub-sub.md
Normal file
214
docs/tutorial-basics/pub-sub.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 发布订阅
|
||||
description: ZHub 消息发布订阅功能详解,包含基础使用、多主题订阅、类型化消息和最佳实践
|
||||
---
|
||||
|
||||
# 发布订阅
|
||||
|
||||
## 基础概念
|
||||
|
||||
- **发布者**:发送消息到指定主题
|
||||
- **订阅者**:订阅主题并处理消息
|
||||
- **主题**:消息分类标识,支持正则表达式匹配
|
||||
- **消费组(GroupID)**:协同消费机制,同组内只有一个消费者处理消息
|
||||
|
||||
## 重要说明
|
||||
|
||||
**发布订阅**:使用具体主题名称
|
||||
```java
|
||||
zhub.subscribe("user-login", message -> { ... });
|
||||
zhub.publish("user-login", "用户登录");
|
||||
```
|
||||
|
||||
**消费组机制**:同组内消息只被一个消费者处理
|
||||
```java
|
||||
// 消费者A和B属于同一组,消息只会被其中一个处理
|
||||
ZHubClient consumerA = new ZHubClient("127.0.0.1:1216", "order-group", "app-a", "token");
|
||||
ZHubClient consumerB = new ZHubClient("127.0.0.1:1216", "order-group", "app-b", "token");
|
||||
|
||||
// 消费者C属于不同组,会收到所有消息
|
||||
ZHubClient consumerC = new ZHubClient("127.0.0.1:1216", "notification-group", "app-c", "token");
|
||||
```
|
||||
|
||||
**权限配置**:支持正则表达式
|
||||
```yaml
|
||||
users:
|
||||
- id: 1
|
||||
username: "user-service"
|
||||
reads: ["user.*"] # 匹配所有 user.* 主题
|
||||
writes: ["user.*"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 协同消费
|
||||
|
||||
### 消费组机制
|
||||
|
||||
**工作原理**:同组内只有一个消费者处理消息,不同组独立消费
|
||||
|
||||
```java
|
||||
// 负载均衡:同组内竞争消费
|
||||
ZHubClient service1 = new ZHubClient("127.0.0.1:1216", "order-group", "app-1", "token");
|
||||
ZHubClient service2 = new ZHubClient("127.0.0.1:1216", "order-group", "app-2", "token");
|
||||
// 只有其中一个处理消息
|
||||
|
||||
// 消息广播:不同组都收到消息
|
||||
ZHubClient notify1 = new ZHubClient("127.0.0.1:1216", "notify-group-1", "notify-1", "token");
|
||||
ZHubClient notify2 = new ZHubClient("127.0.0.1:1216", "notify-group-2", "notify-2", "token");
|
||||
// 两个都会收到消息
|
||||
```
|
||||
|
||||
**应用场景**:
|
||||
- **负载均衡**:同组内多个服务竞争处理
|
||||
- **消息广播**:不同组都接收消息
|
||||
- **数据去重**:同组内确保只处理一次
|
||||
|
||||
---
|
||||
|
||||
## 基础使用
|
||||
|
||||
### 1. 基础发布订阅
|
||||
|
||||
**字符串消息**:
|
||||
```java
|
||||
// 订阅
|
||||
zhub.subscribe("user-login", message -> {
|
||||
System.out.println("用户登录: " + message);
|
||||
});
|
||||
|
||||
// 发布
|
||||
zhub.publish("user-login", "用户ID: 12345");
|
||||
```
|
||||
|
||||
**类型化消息**:
|
||||
```java
|
||||
// 定义消息类型
|
||||
public class UserLoginEvent {
|
||||
private String userId;
|
||||
private String username;
|
||||
private long loginTime;
|
||||
// getter/setter...
|
||||
}
|
||||
|
||||
// 订阅类型化消息(使用TypeToken)
|
||||
zhub.subscribe("user-login", new TypeToken<UserLoginEvent>(){}, event -> {
|
||||
System.out.println("用户: " + event.getUsername());
|
||||
});
|
||||
|
||||
// 发布类型化消息
|
||||
UserLoginEvent event = new UserLoginEvent("12345", "张三", System.currentTimeMillis());
|
||||
zhub.publish("user-login", event);
|
||||
```
|
||||
|
||||
**基础类型**:
|
||||
```java
|
||||
// 整数消息(使用IType)
|
||||
zhub.subscribe("user-count", IType.INT, count -> {
|
||||
System.out.println("用户数: " + count);
|
||||
});
|
||||
zhub.publish("user-count", 100);
|
||||
|
||||
// Map 消息(使用IType)
|
||||
zhub.subscribe("user-info", IType.MAP, info -> {
|
||||
System.out.println("用户信息: " + info);
|
||||
});
|
||||
Map<String, String> userInfo = Map.of("userId", "12345", "username", "张三");
|
||||
zhub.publish("user-info", userInfo);
|
||||
```
|
||||
|
||||
### 2. 多主题订阅
|
||||
|
||||
**分别订阅**:
|
||||
```java
|
||||
zhub.subscribe("user-profile", message -> {
|
||||
System.out.println("用户资料: " + message);
|
||||
});
|
||||
zhub.subscribe("user-login", message -> {
|
||||
System.out.println("用户登录: " + message);
|
||||
});
|
||||
```
|
||||
|
||||
**逗号分隔订阅**:
|
||||
```java
|
||||
// 同时订阅多个主题
|
||||
zhub.subscribe("user-profile,user-login,user-logout", message -> {
|
||||
System.out.println("用户消息: " + message);
|
||||
});
|
||||
|
||||
// 类型化消息(使用TypeToken)
|
||||
zhub.subscribe("order-create,order-payment", new TypeToken<OrderEvent>(){}, event -> {
|
||||
System.out.println("订单事件: " + event.getOrderId());
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 广播消息
|
||||
|
||||
```java
|
||||
// 广播给所有客户端
|
||||
zhub.broadcast("topic-abc", "hello!");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 高级功能
|
||||
|
||||
### 1. 延时消息
|
||||
```java
|
||||
// 延时5分钟后发送消息
|
||||
zhub.delay("reminder-email", "发送提醒邮件", 5 * 60 * 1000);
|
||||
```
|
||||
|
||||
### 2. 消息过滤
|
||||
```java
|
||||
zhub.subscribe("user-notification", message -> {
|
||||
if (message.contains("VIP")) {
|
||||
System.out.println("VIP用户消息: " + message);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 批量处理
|
||||
```java
|
||||
private final List<String> messageBatch = new ArrayList<>();
|
||||
|
||||
zhub.subscribe("data-sync", message -> {
|
||||
synchronized (messageBatch) {
|
||||
messageBatch.add(message);
|
||||
if (messageBatch.size() >= 100) {
|
||||
processBatch(new ArrayList<>(messageBatch));
|
||||
messageBatch.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
**Topic 命名**:`user-profile-update`、`order-payment-success`
|
||||
|
||||
**异常处理**:
|
||||
```java
|
||||
zhub.subscribe("critical-task", message -> {
|
||||
try {
|
||||
processTask(message);
|
||||
} catch (Exception e) {
|
||||
logger.error("处理失败", e);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 消息特性
|
||||
|
||||
- **顺序保证**:单个主题内消息严格按发送顺序处理
|
||||
- **非持久化**:默认不持久化,重启后消息丢失
|
||||
- **高性能**:内存处理,支持高并发消息传递
|
||||
- **容量限制**:服务端通道容量500条,满时消息会被丢弃
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 避免创建大量对象
|
||||
- 注意消息积压:服务端通道容量500条,满时消息会被丢弃
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 发布&订阅
|
||||
description: zhub 创建客户端连接、订阅主题、发送主题消息
|
||||
---
|
||||
|
||||
:::tip
|
||||
|
||||
发布-订阅(Publish-Subscribe):消息中间件可以用于实现发布-订阅模式。发布者将消息发布到一个或多个主题(Topic),而订阅者订阅感兴趣的主题。当有新的消息发布到主题时,所有订阅了该主题的订阅者都会接收到消息。这样可以实现一对多的消息传递,降低发送方和接收方之间的耦合性。
|
||||
|
||||
首先完成 **[连接创建](create-connection.md)** ,便可进行消息的发送和接收,
|
||||
- [订阅主题消息](#订阅主题消息)
|
||||
- [发送主题消息](#发送主题消息)
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## 订阅主题消息
|
||||
|
||||
```java
|
||||
// 事件订阅
|
||||
zhub.subscribe("topic-a", x -> {
|
||||
System.out.println("接收到主题 topic-a 事件,消息内容:" + x);
|
||||
});
|
||||
```
|
||||
|
||||
## 发送主题消息
|
||||
|
||||
测试发送主题消息
|
||||
|
||||
```java
|
||||
private ZHubClient zhub;
|
||||
|
||||
@RestMapping(name = "publish_test", auth = false, comment = "发送主题消息测试")
|
||||
public String publishTest(String value) {
|
||||
zhub.publish("topic-a", value);
|
||||
return "send ok!";
|
||||
}
|
||||
```
|
||||
|
||||
这个时候,将会在订阅端收到主题订阅消息,并在控制台输出: `接收到主题 topic-a 事件,消息内容:xx` 的消息内容
|
||||
@@ -1,36 +1,167 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: 远程调用 RPC
|
||||
description: RPC 远程调用,Remote Procedure Call,RPC
|
||||
title: RPC 远程调用
|
||||
description: ZHub RPC 远程调用功能详解,包含基础类型、类型化调用和多客户端示例
|
||||
---
|
||||
|
||||
# RPC远程调用
|
||||
# RPC 远程调用
|
||||
|
||||
:::tip
|
||||
|
||||
RPC 是一种通过网络将远程过程调用(Remote Procedure Call,RPC)封装成消息,并传送到远程服务器上的过程。
|
||||
|
||||
:::
|
||||

|
||||

|
||||
|
||||
## 使用场景
|
||||
> 在分布式环境下,通过 RPC 可以在两个应用之间进行消息传递,实现远程调用。
|
||||
|
||||
## rpc的订阅-调用基础示例
|
||||
### 被调用端
|
||||
- **微服务间通信**:用户服务调用订单服务
|
||||
- **数据查询服务**:统一的数据查询接口
|
||||
- **业务逻辑封装**:封装复杂业务逻辑供其他模块调用
|
||||
- **第三方服务集成**:调用外部 API
|
||||
|
||||
## 基础示例
|
||||
|
||||
**重要**:RPC 通讯要求每个客户端使用唯一的 appid,消息回复使用此标识。
|
||||
|
||||
### 基础类型 RPC
|
||||
|
||||
**服务端**:
|
||||
```java
|
||||
// 订阅 rpc-b 事件, 参数类型为 String
|
||||
zhub.rpcSubscribe("rpc-b", IType.STRING, r -> {
|
||||
String str = r.getValue();
|
||||
System.out.println("接收到 b 事件:" + str);
|
||||
return r.render("接收到 b 事件:" + str);
|
||||
});
|
||||
```
|
||||
### 调用端
|
||||
```java
|
||||
// 调用 rpc-b 事件, 参数类型为 String,返回类型为 String
|
||||
RpcResult<String> rpcResult = zhub.rpc("rpc-b", "hello rpc", IType.STRING);
|
||||
String result = rpcResult.getResult();
|
||||
System.out.println("rpc result:" + result);
|
||||
// 订阅 RPC 服务
|
||||
zhub.rpcSubscribe("rpc-b", IType.STRING, r -> {
|
||||
String str = r.getValue();
|
||||
System.out.println("接收到: " + str);
|
||||
return r.render("处理结果: " + str);
|
||||
});
|
||||
```
|
||||
|
||||
**客户端**:
|
||||
```java
|
||||
// 调用 RPC 服务
|
||||
RpcResult<String> result = zhub.rpc("rpc-b", "hello rpc", IType.STRING);
|
||||
System.out.println("结果: " + result.getResult());
|
||||
```
|
||||
|
||||
### 类型化 RPC
|
||||
|
||||
**定义类型**:
|
||||
```java
|
||||
// 请求类型
|
||||
public class UserQueryRequest {
|
||||
private String userId;
|
||||
private String queryType;
|
||||
// getter/setter...
|
||||
}
|
||||
|
||||
// 响应类型
|
||||
public class UserInfoResponse {
|
||||
private String userId;
|
||||
private String username;
|
||||
private String email;
|
||||
private long lastLoginTime;
|
||||
// getter/setter...
|
||||
}
|
||||
```
|
||||
|
||||
**服务端**:
|
||||
```java
|
||||
zhub.rpcSubscribe("user-get-info", new TypeToken<UserQueryRequest>(){}, request -> {
|
||||
String userId = request.getUserId();
|
||||
String queryType = request.getQueryType();
|
||||
return request.render(new UserInfoResponse(userId, "张三", "zhangsan@example.com", System.currentTimeMillis()));
|
||||
});
|
||||
```
|
||||
|
||||
**客户端**:
|
||||
```java
|
||||
UserQueryRequest request = new UserQueryRequest("12345", "basic");
|
||||
RpcResult<UserInfoResponse> result = zhub.rpc("user-get-info", request, new TypeToken<UserInfoResponse>(){});
|
||||
|
||||
if (result.isSuccess()) {
|
||||
UserInfoResponse userInfo = result.getResult();
|
||||
System.out.println("用户: " + userInfo.getUsername());
|
||||
} else {
|
||||
System.out.println("调用失败: " + result.getError());
|
||||
}
|
||||
```
|
||||
|
||||
### 多客户端示例
|
||||
|
||||
**服务端**:
|
||||
```java
|
||||
ZHubClient serviceProvider = new ZHubClient("127.0.0.1:1216", "service-group", "service-provider-001", "token-12345");
|
||||
|
||||
// 单个 RPC 服务
|
||||
serviceProvider.rpcSubscribe("user-get-info", IType.STRING, request -> {
|
||||
return request.render("用户信息: " + request.getValue());
|
||||
});
|
||||
|
||||
// 多个 RPC 服务(使用TypeToken)
|
||||
serviceProvider.rpcSubscribe("user-get-info,user-get-profile", new TypeToken<UserQueryRequest>(){}, request -> {
|
||||
switch (request.getQueryType()) {
|
||||
case "getInfo":
|
||||
return request.render(new UserInfoResponse(request.getUserId(), "张三", "zhangsan@example.com", System.currentTimeMillis()));
|
||||
case "getProfile":
|
||||
return request.render(new UserProfileResponse(request.getUserId(), "张三", 25, "北京"));
|
||||
default:
|
||||
return request.render(new UserInfoResponse(request.getUserId(), "未知用户", "", 0));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**客户端A**:
|
||||
```java
|
||||
ZHubClient clientA = new ZHubClient("127.0.0.1:1216", "client-group", "client-a-001", "token-12345");
|
||||
RpcResult<String> result = clientA.rpc("user-get-info", "user123", IType.STRING);
|
||||
System.out.println("结果: " + result.getResult());
|
||||
```
|
||||
|
||||
**客户端B**:
|
||||
```java
|
||||
ZHubClient clientB = new ZHubClient("127.0.0.1:1216", "client-group", "client-b-002", "token-12345");
|
||||
UserQueryRequest request = new UserQueryRequest("user456", "basic");
|
||||
RpcResult<UserInfoResponse> result = clientB.rpc("user-get-info", request, new TypeToken<UserInfoResponse>(){});
|
||||
if (result.isSuccess()) {
|
||||
System.out.println("用户: " + result.getResult().getUsername());
|
||||
}
|
||||
```
|
||||
|
||||
## 类型化 RPC
|
||||
|
||||
### 使用 TypeToken 构建具体类型
|
||||
|
||||
**服务端**:
|
||||
```java
|
||||
// 定义请求和响应类型
|
||||
public class OrderRequest {
|
||||
private String orderId;
|
||||
private String queryType;
|
||||
// getter/setter...
|
||||
}
|
||||
|
||||
public class OrderResponse {
|
||||
private String orderId;
|
||||
private String status;
|
||||
private BigDecimal amount;
|
||||
// getter/setter...
|
||||
}
|
||||
|
||||
// 订阅类型化 RPC
|
||||
zhub.rpcSubscribe("order-get-details", new TypeToken<OrderRequest>(){}, request -> {
|
||||
OrderResponse response = new OrderResponse();
|
||||
response.setOrderId(request.getOrderId());
|
||||
response.setStatus("已支付");
|
||||
response.setAmount(new BigDecimal("99.99"));
|
||||
return request.render(response);
|
||||
});
|
||||
```
|
||||
|
||||
**客户端**:
|
||||
```java
|
||||
// 调用类型化 RPC
|
||||
OrderRequest request = new OrderRequest("ORDER-123", "details");
|
||||
RpcResult<OrderResponse> result = zhub.rpc("order-get-details", request, new TypeToken<OrderResponse>(){});
|
||||
|
||||
if (result.isSuccess()) {
|
||||
OrderResponse order = result.getResult();
|
||||
System.out.println("订单状态: " + order.getStatus());
|
||||
System.out.println("订单金额: " + order.getAmount());
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user