当前位置:网站首页>Myrpc version 3
Myrpc version 3
2022-06-30 04:12:00 【Winter dream chaser】
RPC The concept of
Background knowledge
- RPC Basic concepts of , Core functions
common RPC frame
Duboo Basic function
- Telematics
- Transparent remote procedure call based on interface method
- Load balancing
- Service registry
RPC The process
client Call the remote method -> request serialize -> Protocol code -> Network transmission -> Server side -> Deserialization request -> Call the local method to get response -> serialize -> code ->……
Version iteration process
Catalog
from 0 At the beginning RPC Iterative process of :
- version0 edition : Complete a with less than 100 lines of code RPC Example
- version1 edition : Improve the common message format (request,response), The client's dynamic proxy completes the request Encapsulation of message formats
- version2 edition : Support the server to expose multiple service interfaces , Server program abstraction , Normalization
- version3 edition : Use a high-performance network framework netty The realization of network communication , And the refactoring of client code
- version4 edition : Custom message format , Support multiple serialization methods (java Native , json…)
- version5 edition : Implementation of server registration and discovery ,zookeeper As a registry
- version6 edition : Implementation of load balancing strategy
3.MyRPC edition 3
Background knowledge
- netty The use of high-performance network framework
Questions in this section
How to improve this rpc Performance of ? We can start from two aspects , Network transmission from BIO To NIO, Serialization should reduce the length of byte stream , Improve serialization and deserialization efficiency
Well-known rpc frame :dubbo, grpc Is to use netty Bottom layer for communication
Upgrade process :
Premise : maven pom.xml The file import netty
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.51.Final</version>
</dependency>
upgrade 1: Refactoring client code
The client code is too messy , Let's refactor the code first , Only in this way can it be used later netty To implement the client , The clients with different network connections have the same structure , alike api
Suppose we now have two clients :SimpleRPCClient( Use java BIO The way ), NettyRPCClient( Use netty Network transmission ), So what are the commonalities between them ? Send request and get response It's commonness , The way to establish a connection is different from the way to send a request .
// Commonalities are extracted
public interface RPCClient {
RPCResponse sendRequest(RPCRequest response);
}
// SimpleRPCClient Implement this interface , Different network modes have different implementations
@AllArgsConstructor
public class SimpleRPCClient implements RPCClient{
private String host;
private int port;
// The client initiates a request call ,Socket Establishing a connection , Initiate request Request, Get a response Response
// there request It's packaged , Different service Different packaging is required , The client only knows Service Interface , A layer of dynamic proxy is needed to encapsulate different objects according to reflection Service
public RPCResponse sendRequest(RPCRequest request) {
try {
// Launch once Socket Connection request
Socket socket = new Socket(host, port);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
System.out.println(request);
objectOutputStream.writeObject(request);
objectOutputStream.flush();
RPCResponse response = (RPCResponse) objectInputStream.readObject();
//System.out.println(response.getData());
return response;
} catch (IOException | ClassNotFoundException e) {
System.out.println();
return null;
}
}
}
and RPCClientProxy Class needs to add a RPCClient Class variables , Introduce different client(simple,netty), You can call the public interface sendRequest Send a request , So the client code structure is very clear :
RPCClient: Different network connections , The client of network transmission mode implements this interface respectively
XXXRPCClient: Concrete implementation class
RPCClientProxy: A dynamic proxy Service class , Encapsulate different Service Request for Request object , And hold a RPCClient object , Responsible for the communication with the server ,
thus , The client code is refactored , The structure is clearer , A use case is :
// Build a use java Socket The client of the transmission
SimpleRPCClient simpleRPCClient = new SimpleRPCClient("127.0.0.1", 8899);
// Pass this client into the proxy client
RPCClientProxy rpcClientProxy = new RPCClientProxy(simpleRPCClient);
// The proxy client depends on different services , Get a proxy class , And the methods of this proxy class can be or enhanced ( Encapsulated data , Send a request )
UserService userService = rpcClientProxy.getProxy(UserService.class);
// Calling method
User userByUserId = userService.getUserByUserId(10);
upgrade 2: Use netty Way to transmit data : Realization NettyRPCServer, NettyRPCCLient, It is suggested to learn first netty Start code of
netty Server-side implementation
/** * Realization RPCServer Interface , Responsible for monitoring and sending data */
@AllArgsConstructor
public class NettyRPCServer implements RPCServer {
private ServiceProvider serviceProvider;
@Override
public void start(int port) {
// netty Service thread group boss Responsible for establishing connections , work Responsible for specific requests
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
System.out.printf("Netty The server has started ...");
try {
// start-up netty The server
ServerBootstrap serverBootstrap = new ServerBootstrap();
// initialization
serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class)
.childHandler(new NettyServerInitializer(serviceProvider));
// Synchronous blocking
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
// Loop monitoring
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
@Override
public void stop() {
}
}
netty server Initialization class
/** * initialization , Mainly responsible for serialization encoding and decoding , Need to be solved netty The problem of sticking to the package of */
@AllArgsConstructor
public class NettyServerInitializer extends ChannelInitializer<SocketChannel> {
private ServiceProvider serviceProvider;
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// The message format [ length ][ Message body ], Solve the sticking problem
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
// Calculate the length of the current message to be sent , Write to front 4 In bytes
pipeline.addLast(new LengthFieldPrepender(4));
// It's still used here java Serialization mode , netty The built-in decoding and encoding support the transmission structure
pipeline.addLast(new ObjectEncoder());
pipeline.addLast(new ObjectDecoder(new ClassResolver() {
@Override
public Class<?> resolve(String className) throws ClassNotFoundException {
return Class.forName(className);
}
}));
pipeline.addLast(new NettyRPCServerHandler(serviceProvider));
}
}
netty server Concrete handler
/** * Because it's the server side , We know that the format of the received request is RPCRequest * Object The type is OK , Just force the transformation */
@AllArgsConstructor
public class NettyRPCServerHandler extends SimpleChannelInboundHandler<RPCRequest> {
private ServiceProvider serviceProvider;
@Override
protected void channelRead0(ChannelHandlerContext ctx, RPCRequest msg) throws Exception {
//System.out.println(msg);
RPCResponse response = getResponse(msg);
ctx.writeAndFlush(response);
ctx.close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
RPCResponse getResponse(RPCRequest request) {
// Get the service name
String interfaceName = request.getInterfaceName();
// Get the corresponding service implementation class of the server
Object service = serviceProvider.getService(interfaceName);
// Reflection calls method
Method method = null;
try {
method = service.getClass().getMethod(request.getMethodName(), request.getParamsTypes());
Object invoke = method.invoke(service, request.getParams());
return RPCResponse.success(invoke);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
System.out.println(" Method execution error ");
return RPCResponse.fail();
}
}
}
client netty The implementation of the
/** * Realization RPCClient Interface */
public class NettyRPCClient implements RPCClient {
private static final Bootstrap bootstrap;
private static final EventLoopGroup eventLoopGroup;
private String host;
private int port;
public NettyRPCClient(String host, int port) {
this.host = host;
this.port = port;
}
// netty Client initialization , Reuse
static {
eventLoopGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
.handler(new NettyClientInitializer());
}
/** * Here we need to operate , because netty All transmissions are asynchronous , You send request, Will return immediately , Instead of the corresponding response */
@Override
public RPCResponse sendRequest(RPCRequest request) {
try {
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
Channel channel = channelFuture.channel();
// send data
channel.writeAndFlush(request);
channel.closeFuture().sync();
// The obtainable result of blocking , By giving channel Design alias , Get... Under a specific name channel The content in ( This is in hanlder Set in )
// AttributeKey yes , Thread isolated , There is no thread safety issue .
// In fact, it should not be blocked , You can use the callback function
AttributeKey<RPCResponse> key = AttributeKey.valueOf("RPCResponse");
RPCResponse response = channel.attr(key).get();
System.out.println(response);
return response;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
initialization : Consistent with the server , I won't post the code
ClientHandler Design :
public class NettyClientHandler extends SimpleChannelInboundHandler<RPCResponse> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, RPCResponse msg) throws Exception {
// Received response, to channel Design alias , Give Way sendRequest Read in response
AttributeKey<RPCResponse> key = AttributeKey.valueOf("RPCResponse");
ctx.channel().attr(key).set(msg);
ctx.channel().close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
result :
summary
In this version, we have completed the reconfiguration of the client , Enable it to support multiple versions of client extensions ( Realization RPCClient Interface )
And use netty The communication between client and server is realized
this RPC Maximum pain point
java It has its own serialization method (Java Serialization writing is not just a complete class name , It also contains the definition of the entire class , Contains all referenced classes ), Not universal enough , Not enough efficient
边栏推荐
- 第十二天 进阶编程技术
- Solve the problem of Navicat connecting to the database
- Thinkphp5 implements import function
- Daily summary of code knowledge
- Educoder group purchase suspension box page production
- GIS related data
- JS static method
- 第十一天 脚本与游戏AI
- [note] on May 28, 2022, data is obtained from the web page and written into the database
- (03).NET MAUI实战 基础控件
猜你喜欢
Linear interpolation of spectral response function
Cloud native -- websocket of Web real-time communication technology
尝试链接数据库时出现链接超时报错,如何解决?
How to analyze and solve the problem of easycvr kernel port error through process startup?
【图像融合】基于交叉双边滤波器和加权平均实现多焦点和多光谱图像融合附matlab代码
SQLyog导入数据库时报错,求帮解决!
声网自研传输层协议 AUT 的落地实践丨Dev for Dev 专栏
第十二天 进阶编程技术
How to use FME to create your own functional software
NER中BiLSTM-CRF解读score_sentence
随机推荐
How to analyze and solve the problem of easycvr kernel port error through process startup?
进程间通信之匿名管道
Graduation project EMS office management system (b/s structure) +j2ee+sqlserver8.0
Share an example of a simple MapReduce method using a virtual machine
Clients accessing the daytime service (TCP)
Modifier of JS regular expression
After the win10 system uses the browser to download, the content is moved or deleted without reason
Use ideal to connect to the database. The results show some warnings. How to deal with this part
(03).NET MAUI实战 基础控件
I get n offers in two months. I don't have any difficult interviewers here
Error in conditional filter (if) syntax in sum function in SQL Server2005
知识点滴 - 如何用3个简单的技巧在销售中建立融洽的关系
Solutions for project paths
【论文阅读|深读】Role2Vec:Role-Based Graph Embeddings
matplotlib. pyplot. Hist parameter introduction
487-3279(POJ1002)
When easycvr deploys a server cluster, what is the reason why one is online and the other is offline?
Unity 在編輯器中輸入字符串時,轉義字符的輸入
Day 12 advanced programming techniques
节点CODE相同会导致数据重复