smart-rpc客户端
来源:互联网 发布:电脑打不开软件没反应 编辑:程序博客网 时间:2024/06/06 01:38
学习黄勇smart-rpc的笔记
黄勇的码云地址:https://gitee.com/huangyong/rpc
黄勇的oschina博客地址:https://my.oschina.net/huangyong/blog/361751
rpc是客户端把请求对象序列化成二进制通过网络传给服务端,服务端拿到这些二进制后反序列化成本地对象,执行本地方法调用,把生成的结果再用同样的方式传给客户端。如何获取服务端的地址,如何让对象在网络上传输,这两个过程中我们可以做很多自己的操作,比如服务注册,负载均衡,nio等。
1、客户端使用动态代理创建代理对象,smart-rpc使用jdk的动态代理
/** * 动态代理对接口进行实现 * 代理的好处,不管哪个方法都要进行这样的操作 * * @param interfaceClass * @param serviceVersion * @param <T> * @return */ public <T> T create(final Class<?> interfaceClass, final String serviceVersion) { // 创建动态代理对象 return (T) Proxy.newProxyInstance( interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() { // invoke方法方法调用时执行 // 真正发送请求,接受响应的方法都在这里 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 创建 RPC 请求对象并设置请求属性 RpcRequest request = new RpcRequest(); // uuid做requestId request.setRequestId(UUID.randomUUID().toString()); // 接口类型 request.setInterfaceName(method.getDeclaringClass().getName()); // 接口版本 request.setServiceVersion(serviceVersion); // 方法名称 request.setMethodName(method.getName()); // 方法参数 request.setParameterTypes(method.getParameterTypes()); request.setParameters(args); // 获取 RPC 服务地址 if (serviceDiscovery != null) { String serviceName = interfaceClass.getName(); if (StringUtil.isNotEmpty(serviceVersion)) { serviceName += "-" + serviceVersion; } // 从注册中心找到服务端的地址(ip+ port) serviceAddress = serviceDiscovery.discover(serviceName); LOGGER.debug("discover service: {} => {}", serviceName, serviceAddress); } if (StringUtil.isEmpty(serviceAddress)) { throw new RuntimeException("server address is empty"); } // 从 RPC 服务地址中解析主机名与端口号 String[] array = StringUtil.split(serviceAddress, ":"); String host = array[0]; int port = Integer.parseInt(array[1]); // 创建 RPC 客户端对象并发送 RPC 请求 RpcClient client = new RpcClient(host, port); long time = System.currentTimeMillis(); // 通过网络远程传输请求数据 // 接受返回的响应 RpcResponse response = client.send(request); LOGGER.debug("time: {}ms", System.currentTimeMillis() - time); if (response == null) { throw new RuntimeException("response is null"); } if (response.hasException()) { throw response.getException(); } else { return response.getResult(); } } } ); }
2、客户端将请求对象写入网络中
/** * 向远程服务器发送请求的过程 * 实际上就是把我们自己封装的请求对象写进输出流中 * @param request * @return * @throws Exception */ public RpcResponse send(RpcRequest request) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { // 创建并初始化 Netty 客户端 Bootstrap 对象 // 使用netty 传输数据 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group); bootstrap.channel(NioSocketChannel.class); bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); // 设置对传输的数据的处理 // 对RpcRequest对象要编码处理 pipeline.addLast(new RpcEncoder(RpcRequest.class)); // 编码 RPC 请求 // 对RpcResponse对象要解码处理 pipeline.addLast(new RpcDecoder(RpcResponse.class)); // 解码 RPC 响应 // 对通道返回数据的处理,保存到Response对象 pipeline.addLast(RpcClient.this); // 处理 RPC 响应 } }); bootstrap.option(ChannelOption.TCP_NODELAY, true); // 连接 RPC 服务器 // 知道服务器地址,真正建立连接 ChannelFuture future = bootstrap.connect(host, port).sync(); // 写入 RPC 请求数据并关闭连接 // 建立通道 Channel channel = future.channel(); // rpc请求对象在这被写入了通道中 channel.writeAndFlush(request).sync(); // 关闭通道 channel.closeFuture().sync(); // 返回 RPC 响应对象 System.out.println("响应要被返回了"); // 响应被保存到了Response对象中 return response; } finally { group.shutdownGracefully(); } }
阅读全文
0 0
- smart-rpc客户端
- smart-rpc服务端
- smart-rpc注册中心
- 智能客户端(Smart Client)
- 智能客户端(Smart Client)
- Smart Client (智能客户端)
- Smart Client 智能客户端介绍
- 简单webservice rpc 客户端
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- Smart Client智能客户端技术初探
- 深拷贝和浅拷贝
- POSIX定时器:timer_settime()的使用
- PI/4 dqpsk 非相干解调原理与matlab实现
- PHP SPL使用方法和他的威力
- xshell 无法连接ubuntu
- smart-rpc客户端
- freemarker标签里date数据的显示问题
- 《Android开发艺术探索》之Android的线程和线程池(一)
- R语言 关于package'***' is not available(for R version 3.4.1)
- Psping四大功能介绍:ICMP Ping/TCP Ping/延迟测试/带宽测试
- DOS查看端口占用及杀掉进程命令
- easyui tree树组件无限循环
- Java基础——优先级
- spring boot 中application.properties 介绍及配置