一:服务注册
1.Provider->register Consumer->subscribe Registry->notify Consumer->invoker
2.集群环境下有多台providers ,当providers有下线的要通知consumer,用zk实现注册发现,因为zk有watch心跳机制,还可以存储节点信息
3.provider->提供一个service,consumer->需要用这个远程的service接口
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<!-- declare the service interface to be exported -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>
4.provider register->ZK->创建( serviceName(PERSISTENT持久化节点),serverAddress(EPHEMERAL临时节点))
二.服务发现
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<!-- generate proxy for the remote service, then demoService can be used in the same way as the local regular interface --> <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>
1.consumer subscribe/notify ZK->discovery(serviceName(PERSISTENT持久化节点))->List<serverAddress>->slb取其中一个serviceName
在获取serviceName 之前要对List<serverAddress>监听保证取得是有效的[Listener]
2.ZK的心跳Watch机制
EventType.NodeCreated 、NodeDeleted 、NodeDataChanged 、None 、NodeChildrenChanged
private void registerWatch(String serviceNamePath){
List<serverAddress> -》chliderenListener(ZK(serviceNamePath))
add(this chliderenListener)
}
三.服务调用invoke
1.(socket BIO)NIO Netty
客户端:需要告诉服务端调用的信息:类名,方法名,方法参数,方法参数类型
class RpcRequest implements Serializable{
String className;
String methodName;
Class<?>[] types;
Object[] params;
}
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:被代理类的所有接口信息; 便于生成的代理类可以具有代理类接口中的所有方法
h:动态代理方法在执行时,会调用h里面的invoke方法去执行
Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class<T>[]{interfaceClass},(proxy,methods,args)-{
封装RpcRequest{request.setClassName(method.getDeclaringClass().getName),
requst.setTypes(methods.getParmeterTypes())...}
discovery(serviceName)
})
总结:先通过服务发现拿到服务端ip地址和端口,然后通过动态代理向服务端发送类相关信息,然后接受返回值
服务端invoke:RpcServerHandler extends ChannekInboundHandlerAdapter{
public void channelRead(ChannelHandlerContext ctx,Object msg){
RpcRequest rpcRequest = (RpcRequest)msg;
if(handlerMap.containsKey(rpcRequest.getClassName)){
Method method = clazz.getClass().getMethod(rpcRequest.getMethodName(),rpcRequest.getTypes());
method.invoke(clazz,rpcRequest.getParams())
}
}
}
总结:接受客服端消息,反射invoke方法,发送客户端消息