4. Detailed explanation of Dubbo call module

overview:

1. Basic composition of Dubbo calling module

2. Call internal source code analysis

1. Basic composition of Dubbo calling module


Overview of Dubbo calling module:

The core function of the dubbo call module is to initiate a remote method call and get the returned result smoothly. Its system is composed as follows:

  1. Transparent proxy: Through dynamic proxy technology, remote call details are shielded to improve programming friendliness.
  2. Load balancing: When there are multiple providers, how to choose which load algorithm to call.
  3. Fault tolerance mechanism: the strategy adopted when the service call fails
  4. Call method: support synchronous call and asynchronous call

picture

Transparent proxy:

See source code:

com.alibaba.dubbo.config.ReferenceConfig#createProxy

com.alibaba.dubbo.common.bytecode.ClassGenerator

com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory

load balancing

Dubbo currently officially supports the following load balancing strategies:

  1. Random : Set random probability by weight. This is the default algorithm.
  2. round robin : set the round robin ratio according to the weight after the convention.
  3. Least active number of calls (leastactive): The same active number is random, and the active number refers to the count difference before and after calling.
  4. Consistent Hash (consistenthash): the same parameters are always sent to the same machine

The setting method supports the following four ways of setting, with priority from low to high

<!-- 服务端级别-->
<dubbo:service interface="..." loadbalance="roundrobin" />
<!-- 客户端级别-->
<dubbo:reference interface="..." loadbalance="roundrobin" />
<!-- 服务端方法级别-->
<dubbo:service interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
<!-- 客户端方法级别-->
<dubbo:reference interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>

#TODO Uniformity hash demo

  • configure loadbalance
  • Configure parameters that require hash and the number of virtual nodes
  • Initiate a remote call

Detailed explanation of unique hash algorithm:

picture

fault tolerance

Dubbo officially supports the following fault tolerance strategies:

  1. Automatic switching on failure: Retry other servers based on the retries="2" attribute after the call fails
  2. Fast fail: fast fail, only one call is made, and an error is reported immediately if it fails.
  3. Do not ignore failures: Do not ignore failures and do not throw exceptions to the client.
  4. Retry on failure: automatically recover from failure, record the failed request in the background, and resend it regularly. Usually used for message notification operations
  5. Parallel call: As long as one is successful, it will return, and the specified number of machines will be called in parallel, and the maximum number of parallel calls can be set by forks="2".
  6. Broadcast call: broadcast calls to all providers, one by one, if any one reports an error, it will report an error

The setting method supports the following two ways of setting, the priority is from low to high

<!-- 
Failover 失败自动切换 retries="1" 切换次数
Failfast 快速失败
Failsafe 勿略失败
Failback 失败重试,5秒后仅重试一次
Forking 并行调用  forks="2" 最大并行数
Broadcast 广播调用
-->
<dubbo:service interface="..." cluster="broadcast" />
<dubbo:reference interface="..." cluster="broadcast"/ >

Note: The fault tolerance mechanism is invalid when based on the API setting, such as referenceConfig.setCluster("failback"); it does not work after testing

asynchronous call

异步调用是指发起远程调用之后获取结果的方式。
  1. Synchronously wait for the result to return (default)
  2. Asynchronously wait for the result to return
  3. no need to return results

The implementation process of asynchronously waiting for the result return in Dubbo is as follows:

picture

Asynchronous call configuration:

<dubbo:reference id="asyncDemoService"
                 interface="com.tuling.teach.service.async.AsyncDemoService">
                 <!-- 异步调async:true 异步调用 false 同步调用-->
    <dubbo:method name="sayHello1" async="false"/>
    <dubbo:method name="sayHello2" async="false"/>
     <dubbo:method name="notReturn" return="false"/>
</dubbo:reference>

Note: The fault tolerance mechanism cannot be cluster="forking" or cluster="broadcast" when making asynchronous calls

Demo of asynchronously fetching results:

  • Write code for asynchronous calls
  • Write synchronous call code
  • Demonstrate the time-consuming of synchronous calls and asynchronous calls respectively

Asynchronous call result acquisition Demo

demoService.sayHello1("han");
Future<Object> future1 = RpcContext.getContext().getFuture();
demoService.sayHello2("han2");
Future<Object> future2 = RpcContext.getContext().getFuture();
Object r1 = null, r2 = null;
// wait 直到拿到结果 获超时
r1 = future1.get();
// wait 直到拿到结果 获超时
r2 = future2.get();

filter

** Similar to Filter in WEB, Dubbo itself provides Filter function to intercept remote method calls. It supports the use of custom filters and official filters:**

#TODO demonstrates adding log access filtering:

<dubbo:provider  filter="accesslog" accesslog="logs/dubbo.log"/>

The above configuration is to add a logging filter for the service provider, and all access logs will be printed centrally to the accesslog

2. Call internal source code analysis


knowledge points

  1. Analysis proxy class
  2. Analysis class structure
  3. initialization process
  4. Analysis proxy class

When calling the server, it is called in the form of an interface, which is the implementation of the Duboo dynamic proxy, and its specific implementation can be viewed through the decompilation tool:

Because the class is generated by a proxy, the arthas tool is used to decompile it. The specific operation is as follows:

#运行 arthas
java -jar arthas-boot.jar
#扫描类
sc *.proxy0
#反编译代理类
jad com.alibaba.dubbo.common.bytecode.proxy0

The decompiled code is as follows:

/*
 * Decompiled with CFR.
 *
 * Could not load the following classes:
 *  com.tuling.client.User
 *  com.tuling.client.UserService
 */
package org.apache.dubbo.common.bytecode;
import com.alibaba.dubbo.rpc.service.EchoService;
import com.tuling.client.User;
import com.tuling.client.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.dubbo.common.bytecode.ClassGenerator;
public class proxy0
implements ClassGenerator.DC,
EchoService,
UserService {
    public static Method[] methods;
    private InvocationHandler handler;
    public List findUser(String string, String string2) {
        Object[] arrobject = new Object[]{string, string2};
        Object object = this.handler.invoke(this, methods[0], arrobject);
        return (List)object;
    }
    public User getUser(Integer n) {
        Object[] arrobject = new Object[]{n};
        Object object = this.handler.invoke(this, methods[1], arrobject);
        return (User)object;
    }
    @Override
    public Object $echo(Object object) {
        Object[] arrobject = new Object[]{object};
        Object object2 = this.handler.invoke(this, methods[2], arrobject);
        return object2;
    }
    public proxy0() {
    }
    public proxy0(InvocationHandler invocationHandler) {
        this.handler = invocationHandler;
    }
}

It can be seen that its proxy implements the UserService interface. And proxy based on InvocationHandler. The actual class is InvokerInvocationHandler and its property is Invoker. That is to say, the Invoker will eventually be called to make a remote call.

  1. Analyzing Class Structure Relationships
  • prxoy$: proxy class
  • Invoker: Actuator
  • Invocation: execution parameters and environment
  • Result: return the result
  • Protocol: protocol

Guess you like

Origin blog.csdn.net/qq_39513430/article/details/108336854