大型分布式网络架构设计与实践笔记01. RPC
2016-08-22 00:00
411 查看
RPC
定义
RPC, Remote Process Call, 远程方法调用.RPC 将本地调用转变为远程服务器上的调用,给系统的处理能力和吞吐量无限制提升提供了可能,是实现分布式计算的基础。
服务 Provider
扩容、服务隔离与分组 => 服务路由和负载均衡(router & load balance)服务 consumer 通过 服务 provider的分组信息和地址信息进行路由,通常服务 provider 是一个集群,需要采用一定负载均衡策略,选取其中一台进行调用。
对象的序列化
序列化与反序列化
序列化: 将对象转化为二进制流的过程。反序列化: 将二进制流转化为对象的过程。
常用的解决方案
Java build-in、Google's Protocal Buffers、Hessian; JSON, XML。Protocal Buffers: 高性能,跨平台;需要编写 proto 文件,无法直接使用 Java 对象。
Hessian: 对各种语言的支持,性能稳定。
Java build-in: 无需引入第三方 jar、简单;但是性能不高。
JSON/XML: 跨平台,移动互联网领域广泛使用.
基于 TCP 协议实现 RPC
可以基于 Java 的 Socket API,实现一个简单 RPC 调用.模型
Demo
|- ISayHello|-- SayHelloService
|-- TCPRPCConsumer
|-- TCPRPCProvider
package com.land.rpc; public interface ISayHello { public String sayHello(String arg); }
package com.land.rpc; public class SayHelloService implements ISayHello { public String sayHello(String arg) { if ("hello".equals(arg)) { return "hello"; } return "bye"; } }
package com.land.rpc; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.net.Socket; public class TCPRPCConsumer { public static void main(String[] args) throws NoSuchMethodException, IOException, ClassNotFoundException { final String interfaceName = ISayHello.class.getName(); Method method = ISayHello.class.getMethod("sayHello", java.lang.String.class); Object[] methodArgs = {"hello"}; Socket socket = new Socket("127.0.0.1", 4080); // 对象传输协议 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); output.writeUTF(interfaceName); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(methodArgs); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); // 阻塞式 I/O String result = (String)input.readObject(); System.out.println(result); } }
package com.land.rpc; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class TCPRPCProvider { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Map<String, Object> services = new HashMap<String, Object>(); services.put("com.land.rpc.ISayHello", new SayHelloService()); final ServerSocket server = new ServerSocket(4080); while (true) { Socket socket = server.accept(); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); String interaceName = input.readUTF(); String methodName = input.readUTF(); Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); Object[] methodArgs = (Object[]) input.readObject(); Object service = services.get(interaceName); Class<?> serviceInterfaceClass = Class.forName(interaceName); Method method = serviceInterfaceClass.getMethod(methodName, parameterTypes); Object result = method.invoke(service, methodArgs); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); output.writeObject(result); } } }
基于 HTTP 协议实现 RPC
HTTP 请求与响应
浏览器根据所使用的 HTTP 协议,解析出 url 对应的域名。通过 DNS 域名解析,查询出改域名对应的 IP 地址。
通过 url 解析出端口号(默认80)。
浏览器发起并建立该 IP 的 该端口的连接。
浏览器向服务器发起 GET/POST 请求。
服务器响应浏览器的请求,浏览器读取响应,渲染网页。
浏览器关闭与服务器的连接。
通过 HttpClient 发送 HTTP 请求
如果使用 Socket API 来处理 HTTP 请求,一方面工作量比较大,效果还不一定好(底层的流处理,并发控制 etc)。 HttpClient 提供了一个成熟的解决方案。###RPC: HTTP vs. TCP
Protocol | 优点 | 缺点 |
---|---|---|
TCP | 处于协议栈的下层,可以对协议字段进行定制,减少网络开销字节数,降低网络开销,提高性能,实现更大的吞吐量和并发数 | 实现成本高(需要考虑多线程并发、锁、I/O etc 复杂的底层细节),难以跨平台 |
HTTP | 很多成熟的容器已经很好处理, like. Tomcat, Apache, Jboss; 成熟的响应格式,like. JSON, XML | 处于协议栈的上层,同等内容信息比 TCP的字节数多,效率相对要低 => gzip 改善 |
RESTful & RPC URL 链接风格
两种主流的 URL:风格 | 示例 | 备注 |
---|---|---|
RPC | http://hostname/provider.do?service=com.http.sayhello&format=json×tamp=2016-09-05-20-36-00&arg1=arg1&arg2=arg2 | hostname/format/timestamp/args |
RESTful | POST http://hostname/people GET http://hostname/people/land PUT http://hostname/people/land DELETE http://hostname/people/land | RESTful = Representational State Transfer, 表现层状态转换. 利用了 HTTP 协议里的几种操作. POST: 创建,GET: 返回,PUT: 更新,DELETE: 删除 |
变通 | POST arg1=hello arg2=123 URL http://hostname/provider/sayhelloservice/2016-09-05-20-36-00.json | provider=服务提供方;sayhelloservice=服务接口名称;.json=服务端返回的数据格式;2016-09-05-20-36-00=客户端访问的时间戳 |
实现 HTTP RPC
可以使用 Servlet、Struts、Spring MVC 实现 HTTP RPC。相关文章推荐
- 架构设计实践:基于WCF大型分布式系统
- 架构设计实践:基于WCF大型分布式系统
- 大型网站分布式架构设计与实践(读书总结)
- 读书笔记-大型分布式网站架构-设计与实践【陈康贤】
- 基于WCF大型分布式系统的架构设计
- 大型网站系统架构实践(二)分布式模块之间的通信
- 大型网站系统架构实践(二)分布式模块之间的通信
- 大型网站系统架构实践(二)分布式模块之间的通信
- 大型网站系统架构实践(二)分布式模块之间的通信
- 基于WCF大型分布式系统的架构设计
- 大型网站系统架构实践(二)分布式模块之间的通信
- 基于WCF大型分布式系统的架构设计
- 新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践
- 大型分布式系统架构设计(一)------------大型系统解决方案的演变
- dba和运维专家们说有丰富的大型分布式系统架构设计经验纯属扯淡
- 一、创建Maven项目(大型分布式网站架构设计)
- 架构设计实践:基于WCF大型分布式系统
- Flume(NG)架构设计要点及配置实践 Flume NG是一个分布式、可靠、可用的系统,它能够将不同数据源的海量日志数据进行高效收集
- 分布式服务架构:原理、设计与实践
- 第四十五课 分布式系统、大型网络架构、MogileFS 基础应用