preface

cim

Looking at something written a year or two ago and always wondering if it was really written by yourself? Some places just can’t stand it anymore and start rebuilding.

Before and after contrast

Before we begin, a brief introduction to the CIM project is given. Here is its architecture diagram:

Simply put, it is an IM instant messaging system, which mainly consists of the following parts:

  • IM-serverThe server, of course, is used to maintain a long connection with the client.
  • IM-clientClient, can be simply considered to be similar to QQ such client tools; Of course, the function is certainly not so rich, only provides some simple message sending, receiving functions.
  • RouteRouting services are used for client authentication and message forwarding. Provides HTTP interfaces for viewing system status and the number of online users.

Of course, both servers and routes can be extended horizontally.


This is A flowchart for sending A message, assuming that two servers, A and B, and A routing service are deployed; ClientA and ClientB maintain A long connection with server A and server B respectively.

When ClientA sends a Hello World to ClientB, the entire message flow looks like this:

  1. Through the firsthttpSend the message toRouteService.
  2. Routing Service informationClientBIs connected to theServerBOn; So it passes againhttpSend the message toServerB.
  3. In the endServerBPass the message through withClientBLong connection channelpushGo down, the message has been sent successfully.

Here I’ve captured the code for ClientA’s request to Route:

okhttp
http

For example: suppose we need to connect to the interface of Alipay, here send an HTTP request naturally no problem; However, the original HTTP request should not be used when the internal departments of Alipay directly call each other’s interfaces.

The service provider should provide an API package that the service consumer only needs to rely on to implement the interface invocation.

It doesn’t matter whether you end up using HTTP or a custom proprietary protocol.

Similarly, when we use Dubbo or SpringCloud, we often rely directly on an API package to call remote services as if they were local methods, completely masking the underlying details, whether it’s HTTP or some other proprietary protocol. Not at all for the caller.

There is something insidious about it. This is the official explanation of RPC.

The same is true here. Client, Route and Server are all a system in essence, and it is reasonable for them to call each other through RPC.

So my refactoring looks like this:

The code is much cleaner, just like calling a local method, and this has several advantages:

  • It completely hides the low-level details, making it easier to implement the business and maintain the code.
  • Even if the service provider changes the parameters, it is quickly discovered at compile time, while invoking as before without knowing it, thus increasing the risk.

Undoable dynamic proxy

So let’s talk about how it works.

In fact, the principle is similar as described in the practical Application of dynamic proxy above.

To be insensitive to callers, create a proxy object for the interface; The process of encoding, calling, and decoding is implemented in this proxy object.

This corresponds to creating a routeApi proxy object. The key is this code:

RouteApi routeApi = new ProxyManager<>(RouteApi.class, routeUrl, okHttpClient).getInstance();
Copy the code

The complete source code is as follows:

The getInstance() function returns the interface object to be propped; The ProxyInvocation is a class that implements the InvocationHandler interface. This code uses JDK to implement dynamic invocation.

Looking at the source code for the ProxyInvocation, the invoke() method here is invoked when we invoke any method on the proxy interface.

The Invoke () method naturally implements the above steps: code, remote call, and decode; I’m sure it’s easy for you to see, but I won’t say much about it because it’s not the focus of this discussion.

conclusion

In fact, it is easy to understand the core source code of RPC framework such as Dubbo, the general idea is similar, but the use of private protocol, so the encoding and decoding will be different.

So if you want to implement a RPC framework by yourself, you might as well refer to this idea to try, when you write your own code to run through an RPC HelloWorld feeling is completely different from their own integration of a third party framework such as Dubbo, SpringCloud feeling.

All source code for this article:

Github.com/crossoverJi…

Your likes and shares are the biggest support for me