RPC的一篇文章分析
现在Java这块的面试的要求真的是越来越高了,十年之后,SpringCloud,Double,K8S都有很多的要求,只是前端弱化了点,可能跟前后端分离有关系。现在去面试,不怎么考前端。但是Java的难度真的我感觉,已经是接近要上天了,源码,原理,比较偏的冷门知识都要会。比如关于RPC这块,涉及的就有double,openfeign等等。但是,我们不能被这些五花八门的框架,如果我们经常被这些框架带着
现在Java这块的面试的要求真的是越来越高了,十年之后,SpringCloud,Double,K8S都有很多的要求,只是前端弱化了点,可能跟前后端分离有关系。现在去面试,不怎么考前端。
但是Java的难度真的我感觉,已经是接近要上天了,源码,原理,比较偏的冷门知识都要会。
比如关于RPC这块,涉及的就有double,openfeign等等。但是,我们不能被这些五花八门的框架,如果我们经常被这些框架带着走,很容易就陷入到学不动了的境地。
关于RPC这块,实际上是构建在动态代理的基础上,文章链接地址为:
https://www.cnblogs.com/zyl2016/p/9875593.html
以下是点评:
其实咱们仔细想想,服务端大家都懂,要不就是restful接口,要不就是像double那样提供的service(不过我不建议再用double了)。
那我们要研究的就是客户端怎么就能把远过程调用RPC注入到接口呢?然后这里就涉及到动态代理,我们看文章的下面这段代码:
package socketrpc.client;
import socketrpc.IHello;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
public class RpcClientProxy<T> implements InvocationHandler {
private Class<T> serviceInterface;
private InetSocketAddress addr;
public RpcClientProxy(Class<T> serviceInterface, String ip,String port) {
this.serviceInterface = serviceInterface;
this.addr = new InetSocketAddress(ip, Integer.parseInt ( port ));
}
public T getClientIntance(){
return (T) Proxy.newProxyInstance (serviceInterface.getClassLoader(),new Class<?>[]{serviceInterface},this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket = null;
ObjectOutputStream output = null;
ObjectInputStream input = null;
try {
// 2.创建Socket客户端,根据指定地址连接远程服务提供者
socket = new Socket();
socket.connect(addr);
// 3.将远程服务调用所需的接口类、方法名、参数列表等编码后发送给服务提供者
output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(serviceInterface.getName());
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
// 4.同步阻塞等待服务器返回应答,获取应答后返回
input = new ObjectInputStream(socket.getInputStream());
return input.readObject();
} finally {
if (socket != null) socket.close();
if (output != null) output.close();
if (input != null) input.close();
}
}
public static void main(String[] args) {
RpcClientProxy client = new RpcClientProxy<>(IHello.class,"localhost","6666");
IHello hello = (IHello) client.getClientIntance ();
System.out.println (hello.sayHello ( "socket rpc" ));
}
}
重点是这里用到了动态代理:
RpcClientProxy client = new RpcClientProxy<>(IHello.class,"localhost","6666");
IHello hello = (IHello) client.getClientIntance ();
当然,在实现接口里面的方法时,作者这个例子是使用了socket,获取返回数据,这个也容易理解,为什么double服务端会有个端口20880,这个端口不就是底层socket-client获取数据的端口吗。
再给你看下feign的源码,几个地方:
再深入看下executeAndDecode看下这个方法:
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
response = client.execute(request, options);
// ensure the request is set. TODO: remove in Feign 12
response = response.toBuilder()
.request(request)
.requestTemplate(template)
.build();
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
if (decoder != null)
return decoder.decode(response, metadata.returnType());
CompletableFuture<Object> resultFuture = new CompletableFuture<>();
asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,
metadata.returnType(),
elapsedTime);
try {
if (!resultFuture.isDone())
throw new IllegalStateException("Response handling not done");
return resultFuture.join();
} catch (CompletionException e) {
Throwable cause = e.getCause();
if (cause != null)
throw cause;
throw e;
}
}
看到了吗,里面用的是Request,说明用的是http的请求:
总结一下,不管是dubble还是feign用的都是动态代理,所不同的是,double的在调用的时候用的是socket,而feign用的是http。
有了这个理解,就明白了,double为什么更能承受高并发,因为double用的是socket。而feign用的是http的通信协议,所以,feign当然用起来更方便。
更好的参考文章:https://blog.csdn.net/weixin_34066347/article/details/91631844
想要了解更多的同学们,请关注下我的公众号哟。最近忙于项目开发,加上我又不喜欢追热点,公众号粉丝一直不多,如果有你们的关注,那便是我努力的最大动力。
关注「动哒」
让你每天进步一点点
更多推荐
所有评论(0)