长链接通信

  • isass 前后端长链接通信使用 socketio 实现。Socket.IO 是一个第三方库,可以在客户端和服务器之间实现低延迟、双向和基于事件的通信。它建立在 WebSocket 协议之上,并提供额外的保证,例如回退到 HTTP 长轮询或自动重新连接。

  • 单体服务的前后端长链接存在单点故障,无法高可用。

  • 对长链接消息通信进行了抽象封装,并实现了 socketio 的适配层(不仅限于 socketio 实现,日后能添加更多长链接实现),使用同一套 api 能同时支持 单体集群 两种形式的后端服务。

  • socketio 网关集成在 isass-service-gateway 微服务网关中。

  • 通过 redis 的 发布/订阅stream 实现集群长链接消息通信。

  • 采用 isass 开发的后端服务,原则上应使用封装的 api 来实现前后端长链接通信开发。

消息通信流向图

标签

  • 为了实现精准推送,即向指定一个或一批拥有相同特征指标的客户端推送消息,isass 提供了对长链接通道实例打标签的功能。

  • 标签键值对(tagPair) = 标签键(tagKey) + 标签值(tagValue)

  • 一个长链接通道,可以打上一个标签键(没有标签值)。例如客户端是安卓系统,则可把它打上 "android" 的标签,业务上就能简单精准的对所有安卓客户端的用户推送消息。只打标签键适用于长链接一旦建立,其标签特征就确定下来永远不变的场景。

  • 可以对长链接打上标签键值对。例如长链接登录就是把它加上一个 _uid=xxx 的标签,以后就能对指定用户推送消息。

使用

添加依赖

在微服务的项目代码添加以下依赖

<dependency>
    <groupId>vip.isass</groupId>
    <artifactId>kernel-net-socketio</artifactId>
</dependency>

<dependency>
    <groupId>vip.isass</groupId>
    <artifactId>kernel-net-transfer-service</artifactId>
</dependency>

配置

  • 如果是单体服务,则把网关中转功能关闭,本地 socketio 开启。集群微服务配置相反。

单体服务配置

kernel:
  net:
    enabled: true
    transfer:
      # 网关中转功能开关
      enabled: false

    socketio:
      # 本地服务 socketio 功能开关
      enabled: true
      # socketio 监听的 hostname
      hostname: 0.0.0.0
      # socketio 监听的端口
      port: xxxxx

集群微服务配置

kernel:
  net:
    enabled: true
    transfer:
      # 网关中转功能开关
      enabled: true

    socketio:
      # 本地服务 socketio 功能开关
      enabled: false

网关服务配置

kernel:
  net:
    enabled: true
    transfer:
      # 网关中转功能开关
      enabled: true

    socketio:
      # 本地服务 socketio 功能开关
      enabled: true
      # socketio 监听的 hostname
      hostname: 0.0.0.0
      # socketio 监听的端口
      port: 20001

发送消息

  • 使用 vip.isass.kernel.net.core.message.IMessageSender 接口

// 导包
import vip.isass.kernel.net.core.message.IMessageSender;

// 注入
@Resource
private IMessageSender messageSender;

// 广播消息
messageSender.broadcastMessage("/auth-service/signup", user);

// 给指定用户发送消息
messageSender.sendMessageByUserId("/auth-service/signup", "hello", "123456");

// 给拥有指定标签的用户发送消息
messageSender.sendMessageByTagPair("/auth-service/signup", "hello", "tagKey", "tagValue");

标签维护

  • 使用 vip.isass.kernel.net.core.message.IMessageSender 接口

// 导包
import vip.isass.kernel.net.core.tag.ITagService;

// 注入
@Resource
private ITagService tagService;

// 给指定长链接通道添加标签
tagService.addTagPair(message.getSenderSessionId(), "account", "abc");

// 给指定长链接通道移除指定标签
tagService.removeByTagKey(message.getSenderSessionId(), "account");

订阅消息

  • 实现 vip.isass.kernel.net.core.handler.OnMessageEventHandlerEventHandler 接口

@Component
public static class TestEvent implements OnMessageEventHandler<User> {

    @Override
    public String getCmd() {
        return "/auth-service/signup";
    }

    @Override
    public Object onMessage(Message message, User user) {
        System.out.println(user);
        return null;
    }
}

注意事项

发送消息和订阅消息都会用到参数 路由命令(cmd), cmd 会作为 socketio 的 event 传递给 socketio。为便于维护,区分出 cmd 是属于哪个微服务的,cmd 的格式与 restFull url 风格保持一致,前缀为 /{ms}-service/xxx

调试页面

  • 依赖了 kernel-net-socketio 的服务,自带一个 socketio 调试页面,可以打开 ip:port/socketio.html 访问。
socketio-test-page

更多方法

发送

更多方法请查看接口 IMessageSender

标签

更多方法请查看接口 ITagService

订阅

内置 cmd

框架内置的 cmd 以 /core 为前缀,内置 cmd 如下:

cmd payload 消息流向 作用
/core/ping c2s 客户端向服务端发送心跳
/core/pong s2c 服务端向客户端响应心跳
/core/login 字符串类型的 token,客户端先调用 http 登录接口获取token c2s 登录请求,把长链接绑定上用户 id,即添加 "_uid=xxx" 的标签
/core/logout c2s 登出请求,即移除长链接的 "_uid" 标签
/core/exception 字符串 s2c 推送通用异常消息给客户端