使用 Websocket
推送模式
在 Portal 触发链接一个 websocket,将接收到的数据发送给 各子应用,子应用内部进行消费
前端使用方式
一、Portal 中开启 Websocket 推送配置
说明: 若子应用需要单独建立 websocket, 配置步骤一致
- 在对应环境的 portal-ui 工程中打开推送配置,在子应用中不再需要打开此配置,即只有 portal-ui 进行链接 websocket
const config = {
// ...
definePlugin: {
//...
// 是否启用webscoket
ENABLE_WEBSOCKET: true,
// 是否启用websocket自动重连
ENABLE_WEBSOCKET_AUTO_RECONNECT: true,
},
};
- 在 app/layouts/index.ts 文件中按需传入初始化 websocket 配置项
// 默认提供配置项
layouts.ws = {
site?: string; // 服务地址,默认值:'msgcenter'
path?: string; // 路径,默认值: '/event/endpoint'
params?: {}; // 需要拼装到 url 上的参数
config?: Config; // 其他配置项
onpublish?: (data: IMessage) => any; // 接收到 websocket 数据后的回调
}
二、业务代码中使用
说明:子应用需要知道的只是具体要消费的名称和数据,不需要关注消息来自于哪(是数据 portal 的消息还是数据自己子应用的消息)
import { msgCenter } from '@gza/quantex-utils';
import React, { useEffect } from 'react';
const ApplicationComponent = () => {
useEffect(() => {
let msgToken= msgCenter.subscribe(topic | [topic1, topic2, ...], (topic, data) => {
// 消费数据
...
});
return () => {
msgToken && msgCenter.unsubscribe(msgToken);
}
}, [])
}
// 订阅消息提醒
msgToken = msgCenter.subscribe(MSG_TYPE_REMINDER, (topic, res) => {
setTotal(res.data?.totalUnRead);
});
// 连接websocket
const initEvent = () => {
const { store } = props;
const { requestId } = store;
token = msgCenter.subscribe(['VALUATION_RESULT'], (topic, res) => {
// console.log('接受到的消息数据===:', topic, res.msgType);
if (requestId === res.requestId && topic === 'VALUATION_RESULT') {
store.setTableHeaderData(res.data);
store.tableStore.addOrUpdateRowData([res.data]);
store.tableStore.getGridApi().redrawRows();
}
});
};
前端主动拉取消息方式
说明: 目前只支持拉取消息中心主动发送的消息,例如 message-reminder, 不支持前端主动去取消息中心转发的消息,例如子应用去拉取属于子应用的消息数据
import { browserWS } from 'utils';
browserWS?.ws.client?.send(JSON.stringify({ msgType: 'MESSAGE_REMINDER' }));
前端接收消息数据结构
- 消息类型定义
// 具体消息数据类型,例如子应用发给portal的消息体
interface IMessageData {
data: Record<string, any>; // 一条消息记录数据
msgType: string; // 前端业务逻辑中消费的消息事件名称
requestId?: string;
}
// 消息中心发出来的完整的消息数据结构
interface IMessage {
code: ResponseCode;
data: {
msgType: string, // 指明消息来源的类型,目前有:'heartbeat', 'message-center', 'message-${appId}'
data: IMessageData,
};
msg?: string;
msgDetail?: string;
requestId?: string;
sessionId?: string;
}
- 消息数据示例
// 消息中心发送的消息,主要是 portal 发出来的
{
"code": 200,
"data": {
"ack": false,
"data": { // 消息中心的消息体(完整消息数据结构)
"data": {
"valuationDate": 1595347200000,
"productCode": "test01",
"failedNum": 0,
"totalNum": 1,
"successNum": 0,
"productName": "test01",
"status": "running"
},
"msgType": "MESSAGE_REMINDER" // 具体业务事件名称:消息中心消息-业务未读消息
"requestId": "040a0625-ac06-4193-92a6-c8a2b8814f01",
},
"msgType": "message-center" // 标识来自于消息中心
},
"msg": null,
"msgDetail": null,
"requestId": "null",
"sessionId": "82a"
}
- 消息中心转发 子应用 的消息,例如 ibor 应用的消息
{
"code": 200,
"data": {
"ack": false,
"data": { // 子应用的消息体(完整消息数据结构)
"data": {
"valuationDate": 1595347200000,
"productCode": "test01",
"failedNum": 0,
"totalNum": 1,
"successNum": 0,
"productName": "test01",
"status": "running"
},
"msgType": "VALUATION_RESULT" // 具体业务事件名称:估值结果
"requestId": "040a0625-ac06-4193-92a6-c8a2b8814f01", // 这个是调用估值结果的 requestId
},
"msgType": "message-ibor" // 标识对应子应用的消息, message-appId
},
"msg": null,
"msgDetail": null,
"requestId": "null",
"sessionId": "82a"
}
- msgType 值说明
// 外层的 msgType 标识消息来源,值如下:
"heartbeat": // 心跳消息 客户端接受并转发心跳数据
"message-center": // 属于消息中心的消息
"message-${appId}": // 某个子应用消息,例如 message-ibor
// 内层的 msgType 值标识消息中心(转)发出来消息的具体事件名称,例如
"MESSAGE_REMINDER": // 消息中心消息-业务未读消息
"MESSAGE_PENDING": // 消息中心待办-业务到截止但未处理
后端改动参考文档
若没有访问权限,可找 韦斌 进行赋权
https://gitlab.iquantex.com/godzilla/portal/portal-message-center
对应环境页面添加消息系统和消息主题(这一步需要后端同事配置)
2.1 配置消息系统:添加一个转发消息的子应用
2.2 配置消息主题:为对应的消息系统添加具体的消息事件,消息事件名称命名规范:大写且下划线连接