SOFA source code analysis - generalized call

foreword

Usually, the RPC call requires the client to use the interface provided by the server, and the specific form is to use the jar package to obtain the specific information of the interface by referencing the jar package, such as interface name, method name, parameter type, return value type.

But there are also some situations, for example, the client does not have a jar package, or it is a cross-language call. In this case, the client needs to use a string to make a generalization call.

how to use

Let's take a look at the official example:

ConsumerConfig<GenericService> consumerConfig = new ConsumerConfig<GenericService>()
           .setInterfaceId("com.alipay.sofa.rpc.quickstart.HelloService")
           .setGeneric(true);
GenericService testService = consumerConfig.refer();

String result = (String) testService.$invoke("sayHello", new String[] { "java.lang.String" },new Object[] { "1111" });

We can see that, in fact, setting the interface ID is similar to the normal call, except that a Generic property needs to be added to true.

Then a proxy object of type GenericService is returned. Through this object, you can initiate a call to the service. The way to call is to use the $invoke method of GenericService, and you need to pass the method name, parameter type, and parameter value. and specify the return value.

How is SOFA implemented?

source code implementation

Since the normal call just changes the Generic property, let's see where this property is used.

We quickly found a filter: ConsumerGenericFilter, which takes effect "whether the client is configured with generics". If generics are set, added to the filter chain.

The invoke method of the filter must have performed some special operations on the call, as follows:

  1. The serialized type is obtained according to the method name , such as normal serialization, generic serialization, and mixed serialization. The value returned by our example here is 0 (normal serialization), and then the serialization factory type is set, that is, normal serialization (varies according to the method name).
  2. Get the method name, parameter type string, and method parameters from the Request object. And reset it to the Request object, which is equivalent to rearranging it again.
  3. Then reset the call type based on the method name just set.

In this way, the generic call is modified to be the same as the ordinary call.
Also note: when the call is made, the default order of this filter is -18000, so it will be executed before most (except exception handling and context).

When using Bolt's RpcClient to make a call, it will decide whether to perform generic serialization according to the serialization type.

The specific process is that when called, the InvokeContext context will be created, and the custom serializer will be stored in the Map, where the key is SerializeFactoryTypeand the value is 0(we are here). In the invokeXXX method of RpcRemoting, a RemotingCommand object will be created, that is Execute the toRemotingCommandmethod , SerializeFactoryTypeobtain the enumeration value of the serialization factory according to the InvokeContext, and set it to the RemotingCommand object.

In the SofaRpcSerialization class, the serializer will be obtained according to the serialized enumeration value stored in the invokeContext. The specific code is as follows:

// 根据SerializeType信息决定序列化器
boolean genericSerialize = genericSerializeRequest(invokeContext);
if (genericSerialize) {
    output.setSerializerFactory(genericSerializerFactory);
} else {
    output.setSerializerFactory(serializerFactory);
}

Determines the serializer based on the SerializeType information. The generic specific serializer factory is the GenericMultipleClassLoaderSofaSerializerFactory class, which generates serializers and deserializers. and used in Bolt.

Summarize

From the design of SOFA, it can be seen that the generalization call mainly depends on the GenericService class and the corresponding ConsumerGenericFilter filter. If a client sets generalization, this filter will be enabled during the calling process.

This filter will rearrange the requested data. And modify it to look like a normal call.

At the same time, a serialized enumeration of generic calls is also set to be placed in the context, and the context will dynamically obtain different serializers and deserializers according to the enumeration value in Bolt, and process the output parameters and return values.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325813618&siteId=291194637