您的位置:首页 > 理论基础 > 计算机网络

大型分布式网络架构设计与实践笔记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:

风格示例备注
RPChttp://hostname/provider.do?service=com.http.sayhello&format=json×tamp=2016-09-05-20-36-00&arg1=arg1&arg2=arg2hostname/format/timestamp/args
RESTfulPOST http://hostname/people GET http://hostname/people/land PUT http://hostname/people/land DELETE http://hostname/people/landRESTful = Representational State Transfer, 表现层状态转换. 利用了 HTTP 协议里的几种操作. POST: 创建,GET: 返回,PUT: 更新,DELETE: 删除
变通POST arg1=hello arg2=123 URL http://hostname/provider/sayhelloservice/2016-09-05-20-36-00.jsonprovider=服务提供方;sayhelloservice=服务接口名称;.json=服务端返回的数据格式;2016-09-05-20-36-00=客户端访问的时间戳

实现 HTTP RPC

可以使用 Servlet、Struts、Spring MVC 实现 HTTP RPC。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分布式 rpc