Dynamic proxies are often used in the Java ecosystem, either directly or indirectly, to invoke remote services or to decouple services. This paper, combined with JINGdong service framework JSF, describes a practice of jingdong using dynamic proxy for abstraction, in order to achieve the purpose of upgrading the database access layer.

Liu Shijie, senior Java development engineer of JINGdong Mall, has been working from the server r&d. Currently, he is mainly responsible for the commodity master data basic service of jingdong overseas website. Personally like to read the source code, pay attention to details, some code cleanliness. Maintain an ongoing focus on high availability, high performance, and high concurrency technologies.

1. The background

Recently, I have been upgrading the database (MySQL). The current situation is that the database is directly connected by multiple applications at the same time, there are some problems:

  1. There is a lot of duplicate code, which is expensive to maintain and not elegant;

  2. SQL statement quality problems can not be quickly identified which application caused;

  3. The database callers are too scattered to be controlled uniformly, for example, reading and writing of some business data, shielding, etc.

  4. With the development of business, some table data volume has reached a certain scale, ranging from millions to tens of millions, database storage split is a must.

The solution to this problem is to abstract the DAO layer related to the service in each application into a single application (hereinafter referred to as internal-Rpc-app) for unified management.

2. Implementation

The internal communication between specific business applications and internal-Rpc-App uses THE company’s internal RPC framework with service governance function JSF. JSF is a stable and efficient framework, and its granularity of service governance is interface. The interface does service publishing and invocation configuration through Spring. Each interface corresponds to a CURD and special business of a data table.

2.1 Standard version 1.0

2.1.1. Application for interface registration

Register interface: com.jd.xx.bizrpcService1

Register interface: com.jd.xx.BizRpcService2

Register interface: com.jd.xx.BizRpcService3

.

Register interface: com.jd.xx.BizRpcServiceN

2.1.2. Service Provider configuration

<jsf:provider id=”rpc1″ interface=”com.jd.xx.BizRpcService1″/>

<jsf:provider id=”rpc2″ interface=”com.jd.xx.BizRpcService2″/>

<jsf:provider id=”rpc3″ interface=”com.jd.xx.BizRpcService3″/>

.

<jsf:provider id=”rpcN” interface=”com.jd.xx.BizRpcServiceN”/>

2.1.3. Client caller configuration

<jsf:consumer id=”rpc1″ interface=”com.jd.xx.BizRpcService1″/>

<jsf:consumer id=”rpc2″ interface=”com.jd.xx.BizRpcService2″/>

<jsf:consumer id=”rpc3″ interface=”com.jd.xx.BizRpcService3″/>

.

<jsf:consumer id=”rpcN” interface=”com.jd.xx.BizRpcServiceN”/>

2.1.4 summary

This version does what we set out to do, but there is a disadvantage that the configuration effort is too high. As mentioned earlier, the governance dimension of the JSF framework is interfaces. This also means that every time a new interface is added, it is necessary to submit the application operation and do the corresponding configuration in the consumer and provider. However, if there are dozens or hundreds of data tables, the repeated work will be very large. At the same time, the internal interface does not need to do too fine-grained service governance. This led to the second edition, whose main purpose was to simplify a lot of repeated configurations.

2.2 Optimized Call Experience version 2.0

2.2.1 Internal Implementation – Client

First define the call API:

BizRpcService1 bizRpcService1 = InternalPrxoyServices.BizRpcService1;

bizRpcService1.method1(param1, param2);

Internalprxy Services

BizProxyRpcService1

BaseProxyService key code:

InternalRpcService Interface definition:

2.2.2 Internal Implementation – Server

ServiceName, methodName, and Objects can be used to locate a specific service to a method and execute it directly.

2.2.3 summary

At this point, we have achieved a concrete goal through static proxies, by implementing concrete interface classes. We no longer need to define too many configurations, and client calls are straightforward.

So, is it over? No, while solving a large number of configuration problems, a new workload was introduced because a large number of proxy classes had to be written.

2.3 Final version 3.0

In this release, we have naturally introduced dynamically generated proxies.

2.3.1 Client implementation

Internalprxy Services is rewritten because of the introduction of dynamic proxies:

ProxyServiceFactory

InternalRpcProxy

2.4 summary

At this point, the problem of creating a large number of proxy classes mentioned in 2.2.3 has been solved. Of course, we also did a lot of things that were not mentioned in the article, such as:

  • By declaring which interfaces can go dynamic proxy

  • Method name and client interface validity check

  • Caches method

3. Summary

By establishing an independent application, the problem of database being read and write by multiple applications is solved. By developing a unified interface, the problem of server and client configuration is solved. The code was abstracted step by step, and a simple RPC prototype was implemented, but the communication layer was based on the company’s JSF framework. This leads to some framework thinking:

  1. Should the process of manual approval be removed?

  2. Should more flexible publishing services be allowed? For example: automatically scan publish services according to annotations, automatically obtain services according to annotations.

It’s not about technology, it’s about tradeoffs.

Java recruitment:

Our team is mainly responsible for the overseas business of JD, which is developing rapidly at present. Open team atmosphere, nice leadership, a lot of benefits. We need Java developers to join us, both junior and senior.

Please send your resume to [email protected]. [email protected].

Related reading:

  • An in-depth look at the new Java 9 features

  • New choice for Java microservices framework: Spring 5

  • Here comes Java10, with its new JIT compiler

  • Why server QPS not up? The definitive guide to Java thread tuning