Solon rpc 之 SocketD 協議 – 消息鑒權模式

  • 2021 年 1 月 12 日
  • 筆記

Solon rpc 之 SocketD 協議系列
Solon rpc 之 SocketD 協議 – 概述
Solon rpc 之 SocketD 協議 – 消息上報模式
Solon rpc 之 SocketD 協議 – 消息應答模式
Solon rpc 之 SocketD 協議 – 消息訂閱模式
Solon rpc 之 SocketD 協議 – RPC調用模式
Solon rpc 之 SocketD 協議 – 單鏈接雙向RPC模式
Solon rpc 之 SocketD 協議 – 消息加密模式
Solon rpc 之 SocketD 協議 – 消息鑒權模式

SocketD 是一種二進位的點對點通訊協議,是一種新的網路通訊第七層協議。旨在用於分散式應用程式中。從這個意義上講,SocketD可以是RSocket等其他類似協議的替代方案。它的消息協議規範具有非同步,背壓的雙向,多路復用,斷線重連,基於消息等特性。暫時只提供Java實現,目前做為Solon rpc的sockte通道協議。

本案在消息上報模式的基礎上增加簽權為例演示:

服務端

//啟動服務端
public class ServerApp {
    public static void main(String[] args) {
        //啟動Solon容器(SocketD bean&plugin 由solon容器管理)
        Solon.start(ServerApp.class, args, app -> app.enableSocketD(true));
    }
}

//定義服務端監聽
@ServerEndpoint
public class ServerListener implements Listener {
    @Override
    public void onOpen(Session session) {
        System.out.println("有客戶端鏈上來嘍...");
    }

    @Override
    public void onMessage(Session session, Message message) throws IOException {
        if (session.getHandshaked() == false) {
            //消息是執行緒池分發的,確保鑒權時的消息順序鎖一下
            synchronized (session) {
                onMessage0(session, message);
            }
        } else {
            onMessage0(session, message);
        }
    }

    private void onMessage0(Session session, Message message) throws IOException {
        //如果是握手,則做鑒權處理
        if (message.flag() == MessageFlag.handshake) {
            if (Utils.isEmpty(message.header())) {
                session.close();
            } else {
                Map<String, String> headers = HeaderUtil.decodeHeaderMap(message.header());
                if ("1".equals(headers.get("token"))) {
                    //如果token是1,則設為成功握手
                    System.out.println("簽權成功");
                    session.setHandshaked(true);
                } else {
                    session.close();
                }
            }

            return;
        }

        //沒有握手成功之前,不能做別的事;且自動斷開鏈接
        if (session.getHandshaked() == false) {
            System.out.println("這個客戶端很壞,沒簽權就想發包:(");
            session.close();
        }

        //如果是心跳,則乎略
        if (message.flag() == MessageFlag.heartbeat) {
            System.out.println("服務端:我收到心跳");
            return;
        }

        //業務處理
        System.out.println("服務端:我收到:" + message.bodyAsString());
    }
}

客戶端

//啟動客戶端
public class ClientApp {
    public static void main(String[] args) throws Throwable {
        //啟動Solon容器(SocketD bean&plugin 由solon容器管理)
        Solon.start(ClientApp.class, args);

        //創建會話(如果後端是WebSocekt,協議頭為:ws)
        Session session = SocketD.createSession("tcp://localhost:28080");

        //發送業務握手(進行簽權)
        session.sendHandshake(Message.wrapHandshake("sn=1&token=1"));

        //設定30秒自動上發心跳(如果斷開了,也嘗試自動重鏈)
        session.sendHeartbeatAuto(30);

        //上報消息
        session.send("Helloworld server!");
    }
}

附:示例源碼