5. Analysis of calling module source code

overview:

1. Dubbo calls atypical usage scenarios

2. Call internal source code analysis

1. Dubbo calls atypical usage scenarios


Generalization provides & references

Generalization provides

是指不通过接口的方式直接将服务暴露出去。通常用于Mock框架或服务降级框架实现。
public static void doExportGenericService() {
    ApplicationConfig applicationConfig = new ApplicationConfig();
    applicationConfig.setName("demo-provider");
    // 注册中心
    RegistryConfig registryConfig = new RegistryConfig();
    registryConfig.setProtocol("zookeeper");
    registryConfig.setAddress("192.168.0.147:2181");
    ProtocolConfig protocol=new ProtocolConfig();
    protocol.setPort(-1);
    protocol.setName("dubbo");
    GenericService demoService = new MyGenericService();
    ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
    // 弱类型接口名
    service.setInterface("com.tuling.teach.service.DemoService");
    // 指向一个通用服务实现
    service.setRef(demoService);
    service.setApplication(applicationConfig);
    service.setRegistry(registryConfig);
    service.setProtocol(protocol);
    // 暴露及注册服务
    service.export();
}

Generic reference
refers to referencing services without conventional interfaces, usually used in testing frameworks.

ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-provider");
// 注册中心
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("192.168.0.147:2181");
// 引用远程服务
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.tuling.teach.service.DemoService");
// 声明为泛化接口
reference.setGeneric(true);
reference.setApplication(applicationConfig);
reference.setRegistry(registryConfig);
// 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
Object result = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"world"});

Implicit parameter passing

是指通过非常方法参数传递参数,类似于http 调用当中添加cookie值。通常用于分布式追踪框架的实现。使用方式如下 :
//客户端隐示设置值
RpcContext.getContext().setAttachment("index", "1"); // 隐式传参,后面的远程调用都会隐
//服务端隐示获取值
String index = RpcContext.getContext().getAttachment("index"); 

token verification

Control authority in the registration center through token verification to decide whether to issue tokens to consumers, which can prevent consumers from bypassing the registration center to access providers. In addition, the authorization method can be flexibly changed through the registration center without modification or upgrade provider

picture

use:

<!--随机token令牌,使用UUID生成--><dubbo:provider interface="com.foo.BarService" token="true" />

**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 centrally printed to the accesslog to
customize the filter:

1. Write a filter

package com.tuling.dubbo;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

@Activate(group = {CommonConstants.PROVIDER})
public class ProviderHelloFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        System.out.println("hello ok====================================>>>>>");
        return invoker.invoke(invocation);
    }
}

Add extension point:
Create a file path as follows:

# 文件路径
META-INF/dubbo/org.apache.dubbo.rpc.Filter
#内容:
helloFilter=com.tuling.dubbo.ProviderHelloFilter

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.

2. Dubbo call process:

Basic process:

picture

  1. client call

  2. transparent proxy

  3. load balancing

  4. fault tolerance

  5. asynchronous to synchronous

  6. get results

  7. server response

  8. Analyzing Class Structure Relationships

  • prxoy$: proxy class
  • Invoker: Actuator
  • Invocation: execution parameters and environment
  • Result: return the result
  • Protocol: protocol

calling procedure

insert image description here

call stack

//------ 6 protocol call
doInvoke:77, DubboInvoker {org.apache.dubbo.rpc.protocol.dubbo}
invoke:155, AbstractInvoker {org.apache.dubbo.rpc.protocol}
//--- --- 5 asynchronous to synchronous
invoke:52, AsyncToSyncInvoker {org.apache.dubbo.rpc.protocol} // asynchronous to synchronous, block the calling thread before returning the result
//----- 4 filter chain
invoke:92 , MonitorFilter {org.apache.dubbo.monitor.support} // filter chain -> monitor
invoke:54, FutureFilter {org.apache.dubbo.rpc.protocol.dubbo.filter} // filter chain -> callback parameter
invoke :14, ProviderHelloFilter {com.tuling.dubbo} // filter chain -> custom filter
invoke:60, ConsumerContextFilter {org.apache.dubbo.rpc.filter} // filter chain -> consumer environment initialization
//- -----3 cluster processing
doInvoke:82, FailoverClusterInvoker {org.apache.dubbo.rpc.cluster.support} // Set server - fail retry
invoke:248, AbstractClusterInvoker {org.apache.dubbo.rpc.cluster.support} //
//----- Mock service
invoke:78, MockClusterInvoker {org.apache.dubbo.rpc.cluster.support.wrapper} / / mock service
//----- 2 dynamic proxy--transparent
invoke:55, InvokerInvocationHandler {org.apache.dubbo.rpc.proxy}// proxy intermediate interface
getUser:-1, proxy0 {org.apache. dubbo.common.bytecode} // proxy object
//----- 1 call client
main:53, DubboClient {com.tuling.dubbo} // client

Protocol—>(Registration Agreement)—>MockClusterInvoker —>ClusterInvoker—> RegistryDirectory —>(DubboProtcol)->FilterChain–>DubboInvoker

Guess you like

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