1.前言
我们在学习Dubbo微服务框架的时候,肯定需要明白的就是RPC了,因为很多兄弟老哥总是把它与HTTP进行挂钩,所以明怀我呢就给大家介绍一下RPC吧
2.什么是RPC
什么是RPC呢?其实就是远程过程调用,在大学里面,当你完成图书管理系统的时候,实际上你做的就是本地的调用,但是当你模块一多的话,从serverA调用serverB的东西的时候,那么这就叫做远程调用。
简单的说本机上内部的?法调?都可以称为本地过程调?,?远程过程调?实际上就指的是你本地调?了远程机?上的某个?法,这就是远程过程调?,但也不全面,你在你的本机上,通过建立不同的两个服务,而且服务的端口号不同,而且一个服务去调用另一个服务,那么也可以叫做远程调用。
至于RPC如何调用远程的方法,也可以走HTTP或者TCP,所以说RPC和TCP就不是一个层面的东西
2.1HTTP和TCP的各自特点和区别
1.基于TCP的RPC实现:这是一个通过在服务端定义socket端口和定义和提供的方法名称,服务调用方负责连接服务提供方对应的端口,需要值得注意的是参数在传递的时候需要在服务调用端进行序列化然后在服务提供端进行反序列化,个人理解就行netty之间的通信方式,就是一种基于tcp的远程调用 2.基于HTTP的RPC实现:对于HTTP的RPC实现,本人觉得与现在的restful风格很类似,主要是在服务调用方通过标识请求,GET,POST然后通过url来定位到服务提供方提供的服务,数据通过xml或者json来传输,省去了TCP的序列化和反序列化。
区别:
RPC是基于socket通信,在协议层面处于较底层,优点是传输效率高,但是开发难度相对较高,而HTTP处于较高层面,开发难度相对较小,不用维护socket端口和数据序列化相关问题,但是传输效率比起TCP来低了一些
其实RPC的作用就是让服务与服务之间的调用更加方便,解决远程调用的一些困难。
3.如何设计一个RPC框架
3.1服务消费者
在这里面,消费者只需要考虑哪个接口,找到这个接口,直接进行调用即可,但是,光有接口还是不行滴啊,还需要有对接口的实现,于是消费者只管调用即可。 对了,你还需要告诉代理,你调用的方法是哪个,然后对应的参数是什么。 虽说代理帮你搞定但是代理也需要知道它到底要调哪个机?上的远程?法,所以需要有个注册中心,这样调??从注册中?可以知晓可以调?哪些服务提供方,?般??提供?不??个,毕竟只有?个挂了那不就没了。 所以提供??般都是集群部署,那调??需要通过负载均衡来选择?个调?,可以通过某些策略例如同机房优先调?啊啥的。 我们还需要提供一些容错的机制,因为网络并不是可靠的,还需要重试什么的。
还要和服务提供?约定?个协议,例如我们就? HTTP 来通信就好啦,也就是?家要讲?样的话,不然可能听不懂了。
当然序列化必不可少,毕竟我们本地的结构是“?体”的,需要序列化之后才能传输,因此还需要约定序列化格式。
并且这过程中间可能还需要掺??些 Filter,来作?波统?的处理,例如调?计数啊等等。
这些都是框架需要做的,让消费者像在调?本地?法?样,?感知。
3.2服务提供者
服务提供者肯定要实现对应的接?这是毋庸置疑的。
然后需要把??的接?暴露出去,向注册中?注册??,暴露??所能提供的服务。
然后有消费者请求过来需要处理,提供者需要?和消费者协商好的协议来处理这个请求,然后做反序列化。
序列化完的请求应该扔到线程池??做处理,某个线程接受到这个请求之后找到对应的实现调?,然后再将结果原路返回。
3.3服务注册中心
上?其实我们都提到了注册中?,这东?就相当于?个平台,?家在上?暴露??的服务,也在上?得知??能调?哪些服务。
当然还能做配置中?,将配置集中化处理,动态变更通知订阅者。
3.4监控运维
?对众多的服务,精细化的监控和?便的运维必不可少。
这点很多开发者在开发的时候察觉不到,到你真正上线开始运?维护的时候,如果没有良好的监控措施,快速的运维?段,到时候就是睁眼瞎!???措,等着挨批把!
4.简单实现一个RPC框架
4.1首先是要定义一个接口和它的实现类
public interface AobingService {
String hello(String name);
}
public class AobingServiceImpl implements AobingService {
public String hello(String name) {
return "Yo man Hello,I am" + name;
}
}
4.2接下来就是实现服务提供者暴露服务的功能
public class AobingRpcFramework {
public static void export(Object service, int port) throws Exception {
ServerSocket server = new ServerSocket(port);
while(true) {
Socket socket = server.accept();
new Thread(new Runnable() {
ObjectInputStream input = new
ObjectInputStream(socket.getInputStream());
String methodName = input.read();
Class<?>[] parameterTypes = (Class<?>[])
input.readObject();
Object[] arguments = (Object[]) input.readObject();
数
Method method = service.getClass().getMethod(methodName,
parameterTypes);
Object result = method.invoke(service, arguments);
?法
ObjectOutputStream output = new
ObjectOutputStream(socket.getOutputStream());
output.writeObject(result);
}).start();
}
}
public static <T> T refer (Class<T> interfaceClass, String host, int
port) throws Exception {
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class<?>[] {interfaceClass},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[]
arguments) throws Throwable {
Socket socket = new Socket(host, port);
provider 的 ip 和端?
ObjectOutputStream output = new
ObjectOutputStream(socket.getOutputStream());
output.write(method.getName());
output.writeObject(method.getParameterTypes());
数类型
output.writeObject(arguments);
ObjectInputStream input = new
ObjectInputStream(socket.getInputStream());
Object result = input.readObject();
return result;
好了,这个 RPC 框架就这样好了,是不是很简单?就是调?者传递了?法名、参数类型和参数值,提 供者接收到这样参数之后调?对于的?法返回结果就好了!这就是远程过程调?。 我们来看看如何使?
AobingService service = new AobingServiceImpl ();
AobingRpcFramework.export(service, 2333);
AobingService service =
AobingRpcFramework.refer(AobingService.class, "127.0.0.1", 2333);
service.hello()
5.总结
好啦,今天的RPC总结就到这里啦,里面也包含了很多常见面试题中解决的观点和解析,比如让你说说什么是RPC,以及在调用它的过程中用到的http和TCP这些知识,让你能够搞懂和透彻。好啦,我是明怀,我们下期再见!
|