-
Notifications
You must be signed in to change notification settings - Fork 1
Implement_callback
Callback指的是服务端调用客户端(多次)。 主要依赖的是服务端客户客户端的长连接,连接两端都可以发起请求。
public interface Callback<Q, S> {
/**
* 回调通知
*
* @param result 通知对象
* @return 返回值对象 s
*/
S notify(Q result);
}
不管是服务端发布者还是服务调用者,在启动时候都会扫描接口下的每个方法、 如果满足如下条件,则保存,要不然就报错。
- 不存在多个Callback参数,只能一个
- Callback类型必须指定类型,不能不指定或者泛型。 正确:例如:Callback<List,String>, 错误:Callback, Callback,?>, Callback<List<?>,String>, Callback<List<List>,String>,
记录到缓存中,格式为:{接口+方法名:实际类型}
-
客户端在调用有Callback参数的方法(以下简称Callback方法)的时候,会传递一个Callback实现类,例如:
helloService.register(param, new Callback<List<String>, String>() { @Override public String notify(List<String> result) { // do something } });
-
发现这个方法是一个Callback方法(之前启动阶段已解析),进行特殊处理
if (CallbackUtils.hasCallbackParameter(key)) { CallbackUtils.preMsgSend(request, this.channel); }
-
先对这个实现类生成一个CallbackInsKey,保留CallbackInsKey和实现类的关系
-
虚拟一个CallbackStub对象(保存CallbackInsKey),然后将Callback方法的Callback参数替换为CallbackStub
request.getArgs()[i] = new CallbackStub<>(callbackInsKey, reqClass);
-
视为一个正常请求,发送给服务端
服务端收到请求后,会经过服务端处理:
-
发现这个方法是一个Callback方法(之前启动阶段已解析),进行特殊处理
if (CallbackUtils.hasCallbackParameter(methodKey)) { CallbackUtils.preMsgHandle(request, channel); }
-
先根据当前长连接(客户端->服务端)生成一个反向长连接(服务端->客户端),按连接信息缓存起来
// 使用一个已有的channel虚拟化一个反向长连接 ClientTransport clientTransport = ClientTransportFactory.getReverseClientTransport(channel);
-
读取Callback方法的CallbackStub参数,然后将反向长连接设置到Stub中
stub.setClientTransport(clientTransport).initByMessage(request);
-
视为一个正常请求,进行调用。此时服务端实现类能拿到Callback对象。
-
服务端拿到Callback代理类(其实是CallbackStub)后可以调用
notify(Q)
方法。 -
服务端的CallbackStub拦截方法,拼装为RpcRequest,然后设置Head里的CallbackInsKey为stub的CallbackInsKey
-
服务端通过反向长连接,发送请求到客户端
-
客户端收到RpcRequest,发现Head里面带CallbackInsKey关键字,生成一个CallbackTask,异步执行
if (callbackInsKey != null) { // 服务端发来的callback请求 CallbackTask task = new CallbackTask(request, clientTransport.getChannel()); AsyncContext.getAsyncThreadPool().execute(task); }
-
客户端根据CallbackInsKey找到真正的Callback实例。
Callback callback = CallbackContext.getCallbackIns(callbackInsKey);
-
客户端执行真正调用后,作为一个正常的RpcResponse返回。
-
服务端收到响应后,根据连接信息,找到反向长连接,执行回复事件。
ClientTransport clientTransport = ClientTransportFactory.getReverseClientTransport(channelKey); clientTransport.receiveRpcResponse(response);
服务端主要维护如下:
- Callback方法缓存:启动时扫描加载,不回收。
- 反向长连接列表:在客户端断开长连接时候进行回收。
客户端主要维护如下:
- Callback方法缓存:启动时扫描加载,不回收。
- Callback实例列表:保留了callbackInsKey与真正Callback实例的对应关系**???**
Copyright www.bsoa.io 2016-2017