分佈式網絡通信框架Netty
基於Netty+Zookeeper純手寫RPC遠程調用框架
2 Dubbo框架完整實現
學習總結
田超凡
2019年11月4日
1 創建生產者(Provider)和消費者(Consumer)
生產者:netty-zookeeper-dubbo-user-service-api 用戶服務-接口
netty-zookeeper-dubbo-user-service-provider 用戶服務-接口實現類
package com.tcf.netty.zookeeper.dubbo.user.service;
/***
* TODO TCF 用戶接口-生產者
* @author Hasee
*
*/
public interface UserService {
//TODO TCF 根據用戶id查詢用戶信息
public String getUserById(String id);
}
package com.tcf.netty.zookeeper.dubbo.user.service.impl;
import com.tcf.netty.zookeeper.dubbo.common.annotation.RpcRegistration;
import com.tcf.netty.zookeeper.dubbo.user.service.UserService;
/***
* TODO TCF 用戶接口實現類-生產者
* @author Hasee
*
*/
@RpcRegistration(UserService.class)
public class UserServiceImpl implements UserService {
//TODO TCF 根據用戶id查詢用戶信息
public String getUserById(String id)
{
return "張三";
}
}
消費者:netty-zookeeper-dubbo-order-service-api 訂單服務-接口
netty-zookeeper-dubbo-order-service-consumer 訂單服務-接口實現類
package com.tcf.netty.zookeeper.dubbo.order.service;
/***
* TODO TCF 訂單業務接口-消費者
* @author Hasee
*
*/
public interface OrderService {
//TODO TCF 根據用戶id查詢用戶訂單
public String getOrderByUserId(String id);
}
package com.tcf.netty.zookeeper.dubbo.order.service.impl;
import com.tcf.netty.zookeeper.dubbo.order.service.OrderService;
import com.tcf.netty.zookeeper.dubbo.order.util.DubboClientUtil;
import com.tcf.netty.zookeeper.dubbo.user.service.UserService;
/***
* TODO TCF 訂單服務-消費者
* @author Hasee
*
*/
public class OrderServiceImpl implements OrderService {
//TODO TCF 需要遠程調用的用戶服務接口
private UserService userService;
//TODO TCF 構造柱入
public OrderServiceImpl()
{
this.userService=DubboClientUtil.getDubboClient().createService(UserService.class);
}
//TODO TCF 根據用戶id獲取訂單信息,遠程調用用戶服務接口
public String getOrderByUserId(String id)
{
//TODO TCF 根據用戶id獲取用戶信息,遠程服務調用
String userInfo=userService.getUserById(id);
return userInfo;
}
}
2 創建Zookeeper註冊中心服務註冊接口ServerRegistration和實現類ServerRegistry
package com.tcf.netty.zookeeper.dubbo.server.registry;
/***
* TODO TCF Zookeeper註冊中心服務註冊接口,定義服務註冊類需要註冊的規範
* @author Hasee
*
*/
public interface ServerRegistration {
//TODO TCF 註冊服務到Zookeeper註冊中心
public void registry(String serverName,String serverClassAddr);
}
package com.tcf.netty.zookeeper.dubbo.server.registry.impl;
import java.net.URLEncoder;
import org.I0Itec.zkclient.ZkClient;
import com.tcf.netty.zookeeper.dubbo.server.registry.ServerRegistration;
/***
* TODO TCF Zookeeper註冊中心服務註冊工具類
* @author Hasee
*
*/
public class ServerRegistry implements ServerRegistration {
//TODO TCF Zookeeper註冊中心ip地址
private String host;
//TODO TCF Zookeeper註冊中心客戶端
private ZkClient zkClient;
//TODO TCF Zookeeper註冊中心連接超時時長
private int connectTimeout=5000;
//TODO TCF 服務註冊根目錄
private String rootPath="/netty-zookeeper-dubbo-user-service-api-v1.1";
//TODO TCF 註冊服務類型:生產者
private String serverSuffix="/providers";
//TODO TCF 構造柱入
public ServerRegistry(String host)
{
this.host=host;
this.zkClient=new ZkClient(host,connectTimeout);
}
//TODO TCF 註冊服務到Zookeeper註冊中心
public void registry(String serverName, String serverClassAddr)
{
try
{
//TODO TCF Zookeeper服務根目錄/rootPath
if(!zkClient.exists(rootPath))
{
zkClient.createPersistent(rootPath);
}
//TODO TCF Zookeeper服務二級目錄/rootPath/serverName
String secondLevelPath=rootPath+"/"+serverName;
if(!zkClient.exists(secondLevelPath))
{
zkClient.createPersistent(secondLevelPath);
}
//TODO TCF Zookeeper服務三級目錄/rootPath/serverName/serverSuffix
String thirdLevelPath=secondLevelPath+serverSuffix;
if(!zkClient.exists(thirdLevelPath))
{
zkClient.createPersistent(thirdLevelPath);
}
//TODO TCF Zookeeper服務四級目錄/rootPath/serverName/serverSuffix/serverClassPath
String nodePath=thirdLevelPath+"/"+URLEncoder.encode(serverClassAddr,"UTF-8");
if(zkClient.exists(nodePath))
{
//TODO TCF 服務節點已存在,先刪除該服務節點
zkClient.delete(nodePath);
}
//TODO TCF 創建服務節點,註冊服務
zkClient.createEphemeral(nodePath);
System.out.println("Zookeeper服務註冊成功,服務地址===>"+nodePath);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
3 創建Dubbo服務器:DubboServer
- .基於反射獲取需要註冊到Zookeeper註冊中心的服務並實現服務註冊,存入已註冊服務容器
- .初始化Netty服務器、通道,綁定事件驅動處理器、MarShalling編碼解碼器
- .創建DubboServerEventHandle事件驅動處理器,監聽通訊事件並處理
package com.tcf.netty.zookeeper.dubbo.server.core;
import java.util.HashMap;
import java.util.Map;
import com.tcf.netty.zookeeper.dubbo.common.annotation.RpcRegistration;
import com.tcf.netty.zookeeper.dubbo.common.coder.MarShallingCoderFactory;
import com.tcf.netty.zookeeper.dubbo.server.core.event.DubboServerEventHandle;
import com.tcf.netty.zookeeper.dubbo.server.registry.ServerRegistration;
import com.tcf.netty.zookeeper.dubbo.server.registry.impl.ServerRegistry;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/***
* TODO TCF Dubbo服務器,基於Netty服務器端實現
* @author Hasee
*
*/
public class DubboServer {
//TODO TCF 已經註冊到Zookeeper註冊中心的服務
private Map<String,Object> registryMap=new HashMap<String,Object>();
//TODO TCF Zookeeper註冊中心和Dubbo服務器ip地址
private String host="";
//TODO TCF 服務啓動端口號:20880(Dubbo默認)
private int port=20880;
//TODO TCF Zookeeper註冊中心註冊服務協議類型
private String protocol="tcf://";
//TODO TCF Zookeeper服務註冊工具類
private ServerRegistration serverRegistration=null;
//TODO TCF 構造柱入
public DubboServer(String host)
{
this.host=host;
this.serverRegistration=new ServerRegistry(host);
}
//TODO TCF 初始化Dubbo服務器,註冊服務到Zookeeper註冊中心
public void start(Object service)
{
//TODO TCF 基於反射獲取需要註冊到Zookeeper註冊中心的服務,註冊到Zookeeper註冊中心
serviceRegistry(service);
//TODO TCF 初始化Netty服務器
initServer();
}
//TODO TCF 基於反射獲取需要註冊到Zookeeper註冊中心的服務並進行服務註冊
public void serviceRegistry(Object service)
{
//TODO TCF 獲取需要註冊到Zookeeper註冊中心的服務上方標註的RPC註解
if(service.getClass().isAnnotationPresent(RpcRegistration.class))
{
RpcRegistration rpcRegistration=service.getClass().getAnnotation(RpcRegistration.class);
if(rpcRegistration!=null)
{
//TODO TCF 需要註冊到Zookeeper註冊中心的服務接口
Class<?> interfaceClass=rpcRegistration.value();
if(interfaceClass!=null)
{
//TODO TCF 需要註冊的服務名稱
String serviceName=interfaceClass.getName().replace("interface ","");
//TODO TCF 拼裝服務註冊二級地址(唯一標識需要註冊的服務)
String serviceClassAddr=protocol+host+":"+port+"//";
//TODO TCF 把服務註冊到Zookeeper註冊中心
serverRegistration.registry(serviceName,serviceClassAddr);
//TODO TCF 註冊成功的服務
registryMap.put(serviceName,service);
}
}
}
}
//TODO TCF 初始化Dubbo服務器端,使用Netty服務器
public void initServer()
{
//TODO TCF Boss線程組和工作線程組
NioEventLoopGroup bossGroup=new NioEventLoopGroup();
NioEventLoopGroup workGroup=new NioEventLoopGroup();
//TODO TCF Netty服務器初始化,綁定事件驅動處理器、編碼解碼器,初始化Netty通道
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
//TODO TCF Netty服務器加載通道時綁定編碼解碼器、事件驅動處理器
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception
{
//TODO TCF Netty-RPC請求編碼解碼器MarSharlling
socketChannel.pipeline().addLast(MarShallingCoderFactory.buildMarshallingEncoder());
socketChannel.pipeline().addLast(MarShallingCoderFactory.buildMarshallingDecoder());
//TODO TCF 綁定事件驅動處理器-事件監聽
socketChannel.pipeline().addLast(new DubboServerEventHandle(registryMap));
}
});
try
{
//TODO TCF 初始化Netty通道
ChannelFuture channelFuture=serverBootstrap.bind(port).sync();
System.out.println("====Dubbo 服務器啓動成功===="+port);
//TODO TCF 當斷開和客戶端的連接時,關閉通道,釋放資源,未斷開連接時,此次調用會產生阻塞
channelFuture.channel().closeFuture().sync();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
//TODO TCF 關閉Netty線程組,釋放資源
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
DubboSeverEventHandle事件驅動處理器
package com.tcf.netty.zookeeper.dubbo.server.core.event;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import com.tcf.netty.zookeeper.dubbo.common.model.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/***
* TODO TCF Dubbo服務器事件驅動處理器-實現事件監聽和處理
* @author Hasee
*
*/
public class DubboServerEventHandle extends ChannelInboundHandlerAdapter {
//TODO TCF 已經註冊到Zookeeper註冊中心的服務
private Map<String,Object> registryMap=new HashMap<String,Object>();
//TODO TCF 構造柱入
public DubboServerEventHandle(Map<String,Object> registryMap)
{
this.registryMap=registryMap;
}
//TODO TCF 監聽客戶端發送的消息
@Override
public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception
{
//TODO TCF 將數據解析爲客戶端發送的RPCRequest請求參數模型
if(msg!=null)
{
if(msg instanceof RpcRequest)
{
RpcRequest rpcRequest=(RpcRequest)msg;
System.out.println("====接收到客戶端發送的服務調用請求:"+rpcRequest.toString());
//TODO TCF 根據需要調用的服務名稱獲取對應的服務
Object serviceInstance=registryMap.get(rpcRequest.getServiceClass().getName());
if(serviceInstance!=null)
{
//TODO TCF 基於反射獲取對應服務需要調用的方法
Method method=serviceInstance.getClass().getMethod(rpcRequest.getMethodName(),rpcRequest.getParameterTypes());
//TODO TCF 執行對應方法,實現服務調用
Object invokeResult=method.invoke(serviceInstance,rpcRequest.getParameterValues());
//TODO TCF 返回調用方法執行結果給客戶端
ctx.writeAndFlush(invokeResult);
ctx.close();
}
}
}
}
}
4 創建Zookeeper註冊中心服務發現接口和實現類ZkFoundService、ZkFoundServiceImpl
package com.tcf.netty.zookeeper.dubbo.client.service.handle;
import java.util.List;
/***
* TODO TCF Zookeeper註冊中心服務發現接口
* @author Hasee
*
*/
public interface ZkFoundService {
//TODO TCF 根據服務名稱獲取註冊到Zookeeper註冊中心的服務訪問地址
public List<String> getServiceAddressList(String serviceName);
}
package com.tcf.netty.zookeeper.dubbo.client.service.handle.impl;
import java.util.List;
import org.I0Itec.zkclient.ZkClient;
import com.tcf.netty.zookeeper.dubbo.client.service.handle.ZkFoundService;
/***
* TODO TCF 根據服務名稱獲取Zookeeper註冊中心的服務訪問地址
* @author Hasee
*
*/
public class ZkFoundServiceImpl implements ZkFoundService {
//TODO TCF Zookeeper註冊中心地址
private String host="";
//TODO TCF Zookeeper註冊中心連接超時時長
private int connectTimeout=5000;
//TODO TCF Zookeeper服務節點根目錄
private String rootPath="/netty-zookeeper-dubbo-user-service-api-v1.1";
//TODO TCF Zookeeper服務註冊角色:生產者
private String serviceSuffix="/providers";
//TODO TCF Zookeeper客戶端
private ZkClient zkClient;
//TODO TCF 構造柱入,初始化Zookeeper客戶端
public ZkFoundServiceImpl(String host)
{
this.host=host;
this.zkClient=new ZkClient(host,connectTimeout);
}
//TODO TCF 根據服務名稱獲取註冊到Zookeeper註冊中心的服務訪問地址
public List<String> getServiceAddressList(String serviceName)
{
//TODO TCF 服務節點路由
String serviceNodePath=rootPath+"/"+serviceName+serviceSuffix;
List<String> addressList=zkClient.getChildren(serviceNodePath);
return addressList;
}
}
5 基於策略模式實現Dubbo負載均衡處理器DubboLoadBalance
- .提供隨機負載均衡策略實現類RandomLoadBalanceService
- .提供索引負載均衡策略實現類
IndexLoadBalanceService
(3).注意考慮多線程併發的情況
package com.tcf.netty.zookeeper.dubbo.client.loadbalance;
import java.util.List;
/***
* TODO TCF 基於策略模式實現Dubbo負載均衡處理器業務接口
* @author Hasee
*
*/
public interface DubboLoadBalanceService {
//TODO TCF 根據訪問服務地址進行負載均衡策略實現,返回最終需要調用的服務訪問地址
public String loadBalance(List<String> serviceAddressList);
}
package com.tcf.netty.zookeeper.dubbo.client.loadbalance.impl;
import java.util.List;
import java.util.Random;
import com.tcf.netty.zookeeper.dubbo.client.loadbalance.DubboLoadBalanceService;
/***
* TODO TCF 隨機負載均衡策略實現類
* @author Hasee
*
*/
public class RandomLoadBalanceService implements DubboLoadBalanceService {
//TODO TCF 隨機獲取服務調用地址中的某一個服務地址,實現隨機負載均衡策略
public String loadBalance(List<String> serviceAddressList)
{
String address=serviceAddressList.get(new Random().nextInt(serviceAddressList.size()));
return address;
}
}
package com.tcf.netty.zookeeper.dubbo.client.loadbalance.impl;
import java.util.List;
import com.tcf.netty.zookeeper.dubbo.client.loadbalance.DubboLoadBalanceService;
/***
* TODO TCF 基於索引的負載均衡處理器
* @author Hasee
*
*/
public class IndexLoadBalanceService implements DubboLoadBalanceService {
//TODO TCF 當前加載到第幾個服務訪問地址
private int index=0;
//TODO TCF 實現索引負載均衡策略
public synchronized String loadBalance(List<String> serviceAddressList)
{
String resultAddress="";
if(serviceAddressList!=null && serviceAddressList.size()>0)
{
if(index>=serviceAddressList.size())
{
index=0;
}
resultAddress=serviceAddressList.get(index++);
System.out.println("負載均衡處理後,服務調用地址===>"+resultAddress);
}
return resultAddress;
}
}
6 實現Dubbo客戶端DubboClient
- .根據需要調用的服務接口類型創建JDK動態代理實例,實現代理方法
- .在代理方法中實現服務發現和遠程調用具體邏輯實現,滿足開閉原則
- .創建DubboClientEventHandle事件驅動處理器實現Dubbo客戶端網絡通訊事件監聽和處理
package com.tcf.netty.zookeeper.dubbo.client.core;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.List;
import com.tcf.netty.zookeeper.dubbo.client.core.event.DubboClientEventHandle;
import com.tcf.netty.zookeeper.dubbo.client.loadbalance.DubboLoadBalanceService;
import com.tcf.netty.zookeeper.dubbo.client.loadbalance.impl.IndexLoadBalanceService;
import com.tcf.netty.zookeeper.dubbo.client.service.handle.ZkFoundService;
import com.tcf.netty.zookeeper.dubbo.client.service.handle.impl.ZkFoundServiceImpl;
import com.tcf.netty.zookeeper.dubbo.common.coder.MarShallingCoderFactory;
import com.tcf.netty.zookeeper.dubbo.common.model.RpcRequest;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/***
* TODO TCF Dubbo客戶端,創建需要調用的服務接口的JDK動態代理實例並調用代理方法,具體的服務發現和調用實現邏輯在代理方法中
* @author Hasee
*
*/
public class DubboClient {
//TODO TCF Zookeeper註冊服務發現類
private ZkFoundService zkFoundService;
//TODO TCF Dubbo負載均衡處理器
private DubboLoadBalanceService dubboLoadBalanceService;
//TODO TCF 構造注入
public DubboClient(String host)
{
this.zkFoundService=new ZkFoundServiceImpl(host);
//TODO TCF 默認採用索引負載均衡策略
this.dubboLoadBalanceService=new IndexLoadBalanceService();
}
//TODO TCF 創建需要調用的服務接口的JDK動態代理實例,實現Zookeeper服務發現和調用
@SuppressWarnings("unchecked")
public <T> T createService(final Class<T> interfaceClass)
{
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class[]{interfaceClass},
new InvocationHandler() {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
//TODO TCF 遠程服務調用後方法執行結果
Object invokeResult=null;
//TODO TCF 獲取需要調用的服務名稱
String serviceName=interfaceClass.getName();
//TODO TCF 根據服務名稱獲取已經註冊到Zookeeper註冊中心的服務訪問地址
List<String> addressList=zkFoundService.getServiceAddressList(serviceName);
if(addressList!=null && addressList.size()>0)
{
//TODO TCF 基於負載均衡策略獲取最終需要調用的服務地址
String address=dubboLoadBalanceService.loadBalance(addressList);
address=URLDecoder.decode(address,"UTF-8");
//TODO TCF 獲取ip地址和端口號
address=address.replace("//","").replace("/","");
String[] arrays=address.split(":");
//TODO TCF tcf://host:port//serviceName
String host=arrays[1];
Integer port=Integer.parseInt(arrays[2]);
//TODO TCF 封裝RPC遠程調用請求參數模型
final RpcRequest rpcRequest=new RpcRequest(interfaceClass,method.getName(),method.getParameterTypes(),args);
//TODO TCF 初始化Netty客戶端,連接遠程Netty服務器,傳遞RPC遠程調用請求參數,實現服務遠程調用
//TODO TCF 工作線程組
NioEventLoopGroup workGroup=new NioEventLoopGroup();
//TODO TCF Netty客戶端事件驅動處理器
final DubboClientEventHandle dubboClientEventHandle=new DubboClientEventHandle(rpcRequest);
//TODO TCF Netty客戶端初始化,綁定事件驅動處理器、MarShalling編碼解碼器,初始化Netty通道
Bootstrap client=new Bootstrap();
client.group(workGroup)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host,port.intValue()))
.handler(new ChannelInitializer<SocketChannel>() {
//TODO TCF Netty通道初始化
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception
{
//TODO TCF 綁定MarShalling編碼解碼器
socketChannel.pipeline().addLast(MarShallingCoderFactory.buildMarshallingEncoder());
socketChannel.pipeline().addLast(MarShallingCoderFactory.buildMarshallingDecoder());
//TODO TCF 綁定事件驅動處理器,實現事件監聽
socketChannel.pipeline().addLast(dubboClientEventHandle);
}
});
try
{
//TODO TCF 初始化Netty通道
ChannelFuture channelFuture=client.connect().sync();
//TODO TCF 斷開客戶端連接時關閉Netty通道,釋放資源
channelFuture.channel().closeFuture().sync();
System.out.println(serviceName+"服務的"+method.getName()+"方法遠程調用成功......");
//TODO TCF 服務調用之後,方法執行返回結果
invokeResult=dubboClientEventHandle.getResponseMessage();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
//TODO TCF 關閉線程組,釋放線程佔用資源
workGroup.shutdownGracefully();
}
}
return invokeResult;
}
});
}
}
Dubbo客戶端事件驅動處理器DubboClientEventHandle,發送RPC服務遠程調用請求到對應的Netty服務器並接收服務器返回的方法執行響應結果
package com.tcf.netty.zookeeper.dubbo.client.core.event;
import com.tcf.netty.zookeeper.dubbo.common.model.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/***
* TODO TCF Dubbo客戶端事件驅動處理器-監聽事件
* @author Hasee
*
*/
public class DubboClientEventHandle extends ChannelInboundHandlerAdapter {
//TODO TCF 服務遠程調用請求參數
private RpcRequest rpcRequest;
//TODO TCF Netty服務器返回的服務調用執行結果
private Object responseMessage;
//TODO TCF 構造柱入
public DubboClientEventHandle(RpcRequest rpcRequest)
{
this.rpcRequest=rpcRequest;
}
public Object getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(Object responseMessage) {
this.responseMessage = responseMessage;
}
//TODO TCF 接收到服務器返回的響應信息
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
if(msg!=null)
{
this.responseMessage=msg;
System.out.println("接收到服務器返回的響應信息(方法執行結果):"+msg);
ctx.close();
}
}
//TODO TCF 發送RPC服務遠程調用請求到Netty服務器端
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
ctx.writeAndFlush(rpcRequest);
}
}
7 創建自定義RPC服務註冊註解RpcRegistration
package com.tcf.netty.zookeeper.dubbo.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/***
* TODO TCF 標註需要註冊到Zookeeper註冊中心的服務接口實現類
* @author Hasee
*
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RpcRegistration {
//TODO TCF 需要註冊到Zookeeper註冊中心的服務接口類型
Class<?> value();
}
8 創建RPC遠程服務調用-數據傳輸載體RpcRequest模型類
package com.tcf.netty.zookeeper.dubbo.common.model;
import java.io.Serializable;
/***
* TODO TCF RPC遠程調用請求數據模型類
* @author Hasee
*
*/
public class RpcRequest implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
//TODO TCF 需要調用的服務接口
private Class<?> serviceClass;
//TODO TCF 需要調用的服務接口方法名
private String methodName;
//TODO TCF 需要調用的服務接口方法參數類型
private Class<?>[] parameterTypes;
//TODO TCF 需要調用的服務接口方法參數列表
private Object[] parameterValues;
//TODO TCF 構造柱入
public RpcRequest(Class<?> serviceClass,String methodName,Class<?>[] parameterTypes,Object[] parameterValues)
{
this.serviceClass=serviceClass;
this.methodName=methodName;
this.parameterTypes=parameterTypes;
this.parameterValues=parameterValues;
}
public Class<?> getServiceClass() {
return serviceClass;
}
public void setServiceClass(Class<?> serviceClass) {
this.serviceClass = serviceClass;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Class<?>[] getParameterTypes() {
return parameterTypes;
}
public void setParameterTypes(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
public Object[] getParameterValues() {
return parameterValues;
}
public void setParameterValues(Object[] parameterValues) {
this.parameterValues = parameterValues;
}
}
9 創建Netty編碼器和解碼器工廠MarShallingCoderFactory,創建MarShalling編碼器Encoder和解碼器Decoder,實現RpcRequest請求數據傳輸時的序列化和反序列化
package com.tcf.netty.zookeeper.dubbo.common.coder;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;
public class MarShallingCoderFactory {
/**
* 創建Jboss Marshalling解碼器MarshallingDecoder
* @return MarshallingDecoder
*/
public static MarshallingDecoder buildMarshallingDecoder()
{
//首先通過Marshalling工具類的精通方法獲取Marshalling實例對象 參數serial標識創建的是java序列化工廠對象。
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//創建了MarshallingConfiguration對象,配置了版本號爲5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//根據marshallerFactory和configuration創建provider
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//構建Netty的MarshallingDecoder對象,倆個參數分別爲provider和單個消息序列化後的最大長度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024 * 1024 * 1);
return decoder;
}
/**
* 創建Jboss Marshalling編碼器MarshallingEncoder
* @return MarshallingEncoder
*/
public static MarshallingEncoder buildMarshallingEncoder()
{
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//構建Netty的MarshallingEncoder對象,MarshallingEncoder用於實現序列化接口的POJO對象序列化爲二進制數組
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}
}
10 創建啓動類,查看運行效果
Dubbo客戶端工具類:DubboClientUtil
生成並獲取單例的Dubbo客戶端實例
生產者ProviderApplication:
註冊服務到Zookeeper註冊中心,初始化並啓動Dubbo服務器
package com.tcf.netty.zookeeper.dubbo.core;
import com.tcf.netty.zookeeper.dubbo.server.core.DubboServer;
import com.tcf.netty.zookeeper.dubbo.user.service.impl.UserServiceImpl;
/***
* TODO TCF 用戶服務-生產者,應用啓動類,實現服務註冊
* @author Hasee
*
*/
public class ProviderApplication {
public static void main(String[] args)
{
//TODO TCF 初始化Dubbo服務器,基於反射獲取需要註冊到Zookeeper註冊中心的服務並實現服務註冊,初始化Netty服務器(Dubbo服務器)
DubboServer dubboServer=new DubboServer("127.0.0.1");
dubboServer.start(new UserServiceImpl());
}
}
消費者ConsumerApplication:
RPC遠程調用指定服務的指定方法,獲取方法執行返回結果
package com.tcf.netty.zookeeper.dubbo.order.core;
import com.tcf.netty.zookeeper.dubbo.order.service.OrderService;
import com.tcf.netty.zookeeper.dubbo.order.service.impl.OrderServiceImpl;
/***
* TODO TCF 訂單服務-消費者,應用啓動,發起遠程調用服務請求
* @author Hasee
*
*/
public class ConsumerApplication {
public static void main(String[] args)
{
OrderService orderService=new OrderServiceImpl();
String userInfo=orderService.getOrderByUserId("1");
System.out.println("UserInfo ===> "+userInfo);
}
}
maven相關依賴
<dependencies>
<groupId>com.tcf.netty.zookeeper.dubbo.common</groupId>
|
轉載請註明原作者