Gateway-调度

设计目标

现在我们能控制长连接被gateway所持有,那么下一步就是使用长连接来收发消息,控制长连接的单元是有state server实现的,在接入层我们的设计思想就是将资源和控制分离。

我们还需要一个rpc server,这个rpc server用来接收state server的rpc请求,向具体的conn发出消息,这个rpc叫做push,是下行消息操作,由state server调用。

还需要一个rpc client去请求state server,将上行消息传递给state server,state server负责协议解析,然后根据具体的内容决定是控制信号,还是消息传递,然后进行一定的业务逻辑处理,根据策略将消息转发到业务层,或者是关于连接的控制信号(心跳,超时,ack等),则直接做出判断调用push rpc通知gateway server做出相应的处理过程。

技术约束

  1. 转发过程延迟尽可能低
  2. 尽可能低减少解析性操作,是的内存/cpu消耗更少
  3. 处理rpc异常,和资源隔离,确保稳定性

技术方案

如何优化gateway和state通信的延迟?

由于拆解成两个服务,那么整体的转发过程性能在于网络通信,本地计算成本可以忽略不计。

rpc仅仅是一种通信协议,本质上还是一种应用程协议,和http对应,那么根据网络的分层模型,其实传输层和网络层可以不仅仅是tcp/ip协议,完全可以实现基于domain socket的本机多进程通信机制来代替传输层协议,上层还是rpc,也就是说两个进程在同一个物理机上,然后二者的rpc通信实际上是对多进程通信的封装,进程之间的通信速度,远快于网络通信,因此达到了极高的延迟优化效果。

但是rpc本地化的问题是部署复杂度的上升,以及在设计state server时需要考虑本地内存和分布式内存的区别,比如定时器等数据需要在本地存储,路由信息需要在分布式存储中,并且需要携带endpoint等信息。

同样在资源上,相同物理机上会抢占内存/CPU/IO等资源,state server会占用大量的资源,在资源隔离上较差。

一种这种的方式是将state server和gateway部署到两台物理机但是相同的机柜上,这样既可以做到机器的资源隔离,也能尽可能的应用就近原则优化其延迟,后续有待完善。

RPC需要哪些接口?

调用state server需要提供两种cmd:cancel/send,state sercer调用gateway控制长连接的逻辑只需要两个cmd:del/push,将接口设计成batch模式有利于提高吞吐,做成stream模式可以降低延迟。

如果使用cmd聚合的设计模式即定义cmd+data为参数,在一个rpc request/response中处理,好处是rpc的变更简单,方便扩展,坏处是在使用batch/stream时难以区分cmd之间的优先级。

假设使用本地通信rpc的成本不再是瓶颈,那么batch的处理ROI不高,可以在state sercer与gateway server内部维护一个cmd channel,异步处理cmd,这样做到削峰保证服务稳定,也能具有stream处理的优势,同时可以拆分多个cmd channel以便于不同的cmd处理优先级的区分。

gateway_pb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
syntax = "proto3";

option go_package = "./;service";

package sercive;

// 网关机的rpc sercer定义
// cd gateway/rpc 下执行protoc -I service --go_out=plugins=grpc:service service/gateway.proto
service Gateway{
rpc DelConn(GatewayRequest) returns (GatewayResponse);
rpc Push(GatewayRequest) returns (GatewayResponse);
}

message GatewayRequest {
int32 fd = 1;
bytes data = 2;
}

message GatewayResponse {
int32 code = 1;
string msg = 2;
}

state_pb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
syntax = "proto3";

option go_package = "./;service";

package service;
// 网关机的rpc server定义
// cd state/rpc 下执行 protoc -I service --go_out=plugins=grpc:service service/state.proto
service state {
rpc CancelConn(StateRequest) returns (StateResponse);
rpc SendMsg(StateRequest) returns (StateResponse);
}

message StateRequest {
string endpoint = 1;
int32 fd = 2;
bytes data = 3;
}

message StateResponse {
int32 code = 1;
string msg = 2;
}