JAVA总结 - spring cloud alibaba

JAVA总结 - spring cloud alibaba,第1张

JAVA总结 - spring cloud alibaba

JAVA
  • dubbo
  • 注册中心
    • 一、简单dubbo服务调用示例:client + server服务
    • 二、spring boot dubbo服务调用示例
    • 三、spring cloud dubbo服务调用示例
    • 四、dubbo多注册 中心(nacos+zookeeper)
    • 五、多协议支持
    • 六、负载均衡
    • 七、集群容错
    • 八、dubbo泛化
    • 九、服务降级
    • 十、常见的配置
  • dubbo服务注册流程源码分析
  • dubbo服务发布流程源码分析
    • 1、dubbo服务发布 ServiceConfig.doExportUrlsFor1Protocol
    • 2、PROTOCOL:动态生成适配器类,根据传递进来的参数来选择合适的协议来发布服务。遍历registryURLs发布registry://ip:port
    • 3、RegistryProtocol.export
    • 4、doLocalExport 发布服务
    • 5、Invoker
    • 6、服务注册流程继续 【3、RegistryProtocol.export】
    • 7、服务消费流程继续

dubbo

注册中心

consul、zookeeper、eureka、nacos、redis、etcd

一、简单dubbo服务调用示例:client + server服务

.
 1.1、server-api接口

public interface ILoginFacade {
    String login(String username,String password);
}

.
 1.2、server服务

//1、pom依赖

    
        org.example
        spring-dubbo-server-api
        1.0-SNAPSHOT
    

    
        org.apache.dubbo
        dubbo
        2.7.8
    



//2、启动类
import org.apache.dubbo.container.Main;
public class App {
    public static void main(String[] args) {
        Main.main(args);
    }
}

//3、ILoginFacade 接口实现类
public class LoginServiceImpl implements ILoginFacade {
    public String login(String username, String password) {
        //写业务逻辑
        if(username.equals("admin")&&password.equals("admin")){
            return "SUCCESS";
        }
        return "FAILED";
    }
}

//4、meta-INF/spring/application.xml


    
	
     
    
    
    
    
    

.
 1.3、client服务(依赖server-api接口)

//1、pom依赖
 
     org.example
     spring-dubbo-server-api
     1.0-SNAPSHOT
 
 
     org.apache.dubbo
     dubbo
     2.7.8
 

//2、启动类
import com.sk.dubbo.server.api.ILoginFacade;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:meta-INF/spring/application.xml");
        ILoginFacade loginFacade = context.getBean(ILoginFacade.class);
        System.out.println(loginFacade.login("admin","admin"));
    }
}

//3、meta-INF/spring/application.xml配置



    


    
    
    
二、spring boot dubbo服务调用示例

.
 2.1、server-api接口

		public interface ISayHelloService {
		    String sayHello(String msg);
		}

.
 2.2、server服务

//1、pom依赖
	
        
            org.example
            spring-boot-dubbo-api
            1.0-SNAPSHOT
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
            2.7.7
        
        
            com.alibaba.nacos
            nacos-client
            1.2.1
        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper
            2.7.7
        
    

//2、启动类
	import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan;
	import org.springframework.boot.SpringApplication;
	import org.springframework.boot.autoconfigure.SpringBootApplication;
	
	@DubboComponentScan(basePackages = "com.sk.spring.boot.dubbo.server.service")
	@SpringBootApplication
	public class App {
	    public static void main(String[] args) {
	        SpringApplication.run(App.class,args);
	    }
	}

//3、实现类
//3.1、LoginImpl类
import com.sk.spring.boot.bubbo.api.ILoginFacade;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(registry = {"shanghai","hunan"},version = "1.0")
public class LoginImpl implements ILoginFacade {

    public String login(String username, String password) {
        return "[Version1.0]-账号:"+username+",密码:"+password;
    }
}

//3.2、LoginImpl2 类
import com.sk.spring.boot.bubbo.api.ILoginFacade;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(registry = {"shanghai","hunan"},version = "2.0")
public class LoginImpl2 implements ILoginFacade {
    public String login(String username, String password) {
        return "[Version2.0]-账号:"+username+",密码:"+password;
    }
}

//4、application.properties
spring.application.name=spring-boot-dubbo-server

dubbo.protocol.name=dubbo
dubbo.protocol.port=-1

dubbo.registries.shanghai.address=zookeeper://127.0.0.1:2181
dubbo.registries.shanghai.timeout=10000
dubbo.registries.shanghai.default=true

dubbo.registries.hunan.address=nacos://127.0.0.1:8848

.
 2.3、client服务

//1、pom依赖

    
        
            org.example
            spring-boot-dubbo-api
            1.0-SNAPSHOT
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.apache.dubbo
            dubbo-spring-boot-starter
            2.7.7
        
        
            com.alibaba.nacos
            nacos-client
            1.2.1
        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper
            2.7.7
        
    
    
//2、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
}

//3、application.properties
spring.application.name=spring-boot-dubbo-client

dubbo.registries.shanghai.address=zookeeper://192.168.216.128:2181
dubbo.registries.shanghai.timeout=10000
dubbo.registries.shanghai.zone=shanghai
dubbo.registries.shanghai.weight=100

dubbo.registries.hunan.address=nacos://192.168.216.128:8848
dubbo.registries.hunan.weight=10
dubbo.registries.hunan.preferred=true

server.port=8888

//4、实现类
import com.sk.spring.boot.bubbo.api.ILoginFacade;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {
    @DubboReference(registry = {"shanghai","hunan"},version = "2.0")
    ILoginFacade loginFacade;

    @GetMapping("/login")
    public String login(String userName, String passWord){
        return loginFacade.login(userName,passWord);
    }
}
三、spring cloud dubbo服务调用示例
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/52b6bc8ecf914af8bf36d4264f7013b3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA56We56eR,size_20,color_FFFFFF,t_70,g_se,x_16)

.
 3.1、server-api接口  
 3.2、server-api接口

//1、pom依赖
    
        
            org.example
            spring-cloud-dubbo-api
            1.0-SNAPSHOT
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            com.alibaba.cloud
            spring-cloud-starter-dubbo
            2.2.1.RELEASE
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
            2.2.1.RELEASE
        
    

//2、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
}

//3、application.properties配置
spring.application.name=spring-cloud-dubbo-server

dubbo.scan.base-packages=com.sk.spring.cloud.dubbo.server.service

dubbo.protocol.port=20882
dubbo.protocol.name=dubbo

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

//4、实现类     
import com.sk.spring.cloud.dubbo.api.ILoginFacade;
import org.apache.dubbo.config.annotation.Service;

@Service
public class LoginImpl  implements ILoginFacade {
    public String login(String username, String password) {
        return "[Version1.0]-账号:"+username+",密码:"+password;
    }
}

.
 3.3、client服务

//1、pom依赖
    
        
            org.example
            spring-cloud-dubbo-api
            1.0-SNAPSHOT
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            com.alibaba.cloud
            spring-cloud-starter-dubbo
            2.2.1.RELEASE
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
            2.2.1.RELEASE
        
    
    
//2、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
}

//3、application.properties配置
spring.application.name=spring-cloud-dubbo-client

spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848

//4、实现类
import com.sk.spring.cloud.dubbo.api.ILoginFacade;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {

    @Reference
    ILoginFacade loginFacade;

    @GetMapping("/login")
    public String login(String userName, String passWord){
        return loginFacade.login(userName,passWord);
    }
}
四、dubbo多注册 中心(nacos+zookeeper)
  区域优先:
  权重:
  优先选择:
  版本路由:
五、多协议支持

dubbo(netty)
   dubbo.protocols.dubbo.name=dubbo
   dubbo.protocols.dubbo,port=-1
 rest(jetty)
   dubbo.protocols.rest.name=rest
   dubbo.protocols.rest,port=-1
   dubbo.protocols.server=jetty

六、负载均衡

Random:加权随机(默认)
 roundrobin:轮询
 一致性hash负载:
 最小活跃度:

七、集群容错

1、fialover(默认)失败重试
   @DubboService(cluster = “failover”,retries = 2)
 2、failfast cluster 快速失败,立马报错
 3、failsafe cluster 失败安全,出现异常直接吞掉
 4、failback cluster 失败自动恢复,定时重发
 5、forking cluster 广播发送,成功一条返回

八、dubbo泛化
@RestController
public class DemoController {

    @DubboReference(interfaceName = "com.sk.springboot.dubbo.springbootdubbosampleprovider.services.IDemoService",generic = true,check = false)
    GenericService genericService;

    @GetMapping("/demo")
    public String demo(){
        return genericService.$invoke("getTxt",new String[0],null).toString();
    }
}

入参是对象:
 

九、服务降级

    @DubboReference(registry = {"shanghai","hunan"},
            protocol = "dubbo",
            loadbalance = "consistenthash",
            mock = "com.sk.springboot.dubbo.springbootdubbosampleconsumer.MockSayHelloService",
            timeout = 500,
            cluster = "failfast")
    ISayHelloService sayHelloService;
    
 	@GetMapping("/say")
    public String say(){
        return sayHelloService.sayHello("hello sk");
    }
十、常见的配置

1、check 启动检查

		//1、服务配置:服务启动注册失败正常启动
		dubbo.registries.shanghai.check=false
		
		//2、客户端请求服务校验:false不校验依赖接口服务是否注册
	    @DubboReference(registry = {"shanghai","hunan"},
           protocol = "dubbo",
           loadbalance = "consistenthash",
           mock = "com.gupaoedu.springboot.dubbo.springbootdubbosampleconsumer.MockSayHelloService",
           timeout = 500,
           cluster = "failfast",check = true)
   		ISayHelloService sayHelloService;

.
 2、主机绑定问题

String host = findConfigedHosts(protocolConfig, registryURLs, map); 
Integer port = findConfigedPorts(protocolConfig, name, map);
在这里插入代码片

.
   1、查找环境变量中是否存在启动参数 [DUBBO_IP_TO_BIND] =服务注册的ip
   2、读取配置文件, dubbo.protocols.dubbo.host= 服务注册的ip
   3、InetAddress.getLocalHost().getHostAddress() 获得本机ip地址
   4、通过Socket去连接注册中心,从而获取本机IP
   5、会轮询本机的网卡,直到找到合适的IP地址
   6、上面获取到的ip地址是bindip,如果需要作为服务注册中心的ip,DUBBO_IP_TO_REGISTRY -dDUBBO_IP_TO_REGISTRY=ip
   
 3、配置优先级
   3.1、服务配置优先级
.
 3.2、环境配置优先级

3、序列化

4、性能调优的参数

5、Dubbo缓存文件
   dubbo.registries.shanghai.file=${user.home}/dubboshanghai.cache
 
 6、dubbo admin
 注意:配置校验 -> 远程配置加载 (移除定制化配置)

		dubbo.config-center.address=zookeeper://192.168.216.128:2181
		dubbo.config-center.timeout=10000
dubbo服务注册流程源码分析
        1.1、服务发布代码
        注解
        
		@DubboService(
	       loadbalance = "random",
	       cluster = "failover",
	       retries = 2)

.
   注解扫描

		@DubboComponentScan(

.
   1.2、逻辑步骤
   扫描注解
   url驱动(url组装)
   注册到zookeeper
   启动服务(根据url配置协议、端口发布对应的服务)
 2、对应源码
   2.1、dubbo服务发布两种方式
      xml形式:dubbo:servce
      @DubboService/@Service
   2.2、dubbo注解的解析流程
      DubboComponetScan:把ServiceAnnotationBeanPostProcessor注册到spring ioc

    public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
    	//1、扫描basePackages包
        Set packagesToScan = this.getPackagesToScan(importingClassmetadata);
        //2、注册ServiceAnnotationBeanPostProcessor
        this.registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
        DubboBeanUtils.registerCommonBeans(registry);
    }

.
      ServiceAnnotationBeanPostProcessor

public ServiceAnnotationBeanPostProcessor(Set packagesToScan) {
        super(packagesToScan);
    }

.
      ServiceClassPostProcessor 继承BeanDefinitionRegistryPostProcessor

//1、bean装载完成之后,会触发这个方法
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        AnnotatedBeanDefinitionRegistryUtils.registerBeans(registry, new Class[]{DubboBootstrapApplicationListener.class});
        Set resolvedPackagesToScan = this.resolvePackagesToScan(this.packagesToScan);
        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            this.registerServiceBeans(resolvedPackagesToScan, registry);
        } else if (this.logger.isWarnEnabled()) {
            this.logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }

    }

.
      注册一个DubboBootstrapApplicationListener :在spring容器上下文装载之后触发监听

public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener
        implements Ordered {

    
    public static final String BEAN_NAME = "dubboBootstrapApplicationListener";

    private final DubboBootstrap dubboBootstrap;

    public DubboBootstrapApplicationListener() {
        this.dubboBootstrap = DubboBootstrap.getInstance();
    }

    @Override
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }

    private void onContextRefreshedEvent(ContextRefreshedEvent event) {
        dubboBootstrap.start();
    }

    private void onContextClosedEvent(ContextClosedEvent event) {
        dubboBootstrap.stop();
    }

    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }
}

.
      registerServiceBeans

 
    private void registerServiceBeans(Set packagesToScan, BeanDefinitionRegistry registry) {

        DubboClassPathBeanDefinitionScanner scanner =
                new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

        BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

        scanner.setBeanNameGenerator(beanNameGenerator);

        // refactor @since 2.7.7
        serviceAnnotationTypes.forEach(annotationType -> {
            scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
        });

        for (String packageToScan : packagesToScan) {

            // Registers @Service Bean first
            scanner.scan(packageToScan);

            // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
            Set beanDefinitionHolders =
                    findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

            if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

                for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                    registerServiceBean(beanDefinitionHolder, registry, scanner);
                }

                if (logger.isInfoEnabled()) {
                    logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
                            beanDefinitionHolders +
                            " } were scanned under package[" + packageToScan + "]");
                }

            } else {

                if (logger.isWarnEnabled()) {
                    logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
                            + packageToScan + "]");
                }

            }

        }

    }

.
      registerServiceBean

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {

        Class beanClass = resolveClass(beanDefinitionHolder);

        Annotation service = findServiceAnnotation(beanClass);

        
        AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);

        Class interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);

        String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

        AbstractBeanDefinition serviceBeanDefinition =
                buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

        // ServiceBean Bean name
        String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

        if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        	//dubbo中提供的ServiceBean注入到Spring IOC容器
            registry.registerBeanDefinition(beanName, serviceBeanDefinition);

            if (logger.isInfoEnabled()) {
                logger.info("The BeanDefinition[" + serviceBeanDefinition +
                        "] of ServiceBean has been registered with name : " + beanName);
            }

        } else {

            if (logger.isWarnEnabled()) {
                logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition +
                        "] of ServiceBean[ bean name : " + beanName +
                        "] was be found , Did @DubboComponentScan scan to same package in many times?");
            }

        }

    }

.
      ServiceBean的初始化阶段

public ServiceBean() {
    super();
    this.service = null;
}

//当ServiceBean初始化完成之后,会调用下面的方法.
@Override
public void afterPropertiesSet() throws Exception {
    if (StringUtils.isEmpty(getPath())) {
        if (StringUtils.isNotEmpty(beanName)
            && StringUtils.isNotEmpty(getInterface())
            && beanName.startsWith(getInterface())) {
            setPath(beanName);
        }
    }
}

.
      DubboBootstrapApplicationListener 启动dubbo服务

//启动dubbo服务
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
    dubboBootstrap.start();
}

//如果是dubbo协议,则启动netty server
public DubboBootstrap start() {
    if (started.compareAndSet(false, true)) {
        ready.set(false);
        initialize();
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " is starting...");
        }
        // 1. export Dubbo Services
        exportServices();

        // Not only provider register
        if (!isOnlyRegisterProvider() || hasExportedServices()) {
            // 2. export metadataService
            exportmetadataService();
            //3. Register the local ServiceInstance if required
            registerServiceInstance();
        }

        referServices();
        if (asyncExportingFutures.size() > 0) {
            new Thread(() -> {
                try {
                    this.awaitFinish();
                } catch (Exception e) {
                    logger.warn(NAME + " exportAsync occurred an exception.");
                }
                ready.set(true);
                if (logger.isInfoEnabled()) {
                    logger.info(NAME + " is ready.");
                }
            }).start();
        } else {
            ready.set(true);
            if (logger.isInfoEnabled()) {
                logger.info(NAME + " is ready.");
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " has started.");
        }
    }
    return this;
}

.
      exportServices发布dubbo服务

//遍历所有dubbo服务协议,进行服务发布
private void exportServices() {
    configManager.getServices().forEach(sc -> {
        // TODO, compatible with ServiceConfig.export()
        ServiceConfig serviceConfig = (ServiceConfig) sc;
        serviceConfig.setBootstrap(this);

        if (exportAsync) {
            ExecutorService executor = executorRepository.getServiceExporterExecutor();
            Future future = executor.submit(() -> {
                sc.export();
                exportedServices.add(sc);
            });
            asyncExportingFutures.add(future);
        } else {
            sc.export();
            exportedServices.add(sc);
        }
    });
}
          	      export发布
public synchronized void export() {
    if (!shouldExport()) {
        return;
    }

    if (bootstrap == null) {
        bootstrap = DubboBootstrap.getInstance();
        bootstrap.init();
    }

    checkAndUpdateSubConfigs();

    //init servicemetadata
    servicemetadata.setVersion(version);
    servicemetadata.setGroup(group);
    servicemetadata.setDefaultGroup(group);
    servicemetadata.setServiceType(getInterfaceClass());
    servicemetadata.setServiceInterfaceName(getInterface());
    servicemetadata.setTarget(getRef());

    if (shouldDelay()) {
        DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
    } else {
        doExport();
    }

    exported();
}

.
      doExportUrls:根据开发者配置的协议列表,遍历协议列表逐项进行发布

private void doExportUrls() {
    ServiceRepository repository = ApplicationModel.getServiceRepository();
    ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
    repository.registerProvider(
        getUniqueServiceName(),
        ref,
        serviceDescriptor,
        this,
        servicemetadata
    );

    List registryURLs = ConfigValidationUtils.loadRegistries(this, true);

    for (ProtocolConfig protocolConfig : protocols) {
        String pathKey = URL.buildKey(getContextPath(protocolConfig)
                                      .map(p -> p + "/" + path)
                                      .orElse(path), group, version);
        // In case user specified path, register service one more time to map it to path.
        repository.registerService(pathKey, interfaceClass);
        // TODO, uncomment this line once service key is unified
        servicemetadata.setServiceKey(pathKey);
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}

.
      doExportUrlsFor1Protocol:生成url,根据url中配置的协议类型,调用指定协议进行服务的发布

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs) {
    String name = protocolConfig.getName();
    if (StringUtils.isEmpty(name)) {
        name = DUBBO;
    }
    //用来存储所有的配置信息
    * dubbo:service
        dubbo:method
            dubbo:argument
    Map map = new HashMap();
    map.put(SIDE_KEY, PROVIDER_SIDE);

    ServiceConfig.appendRuntimeParameters(map);
    AbstractConfig.appendParameters(map, getMetrics());
    AbstractConfig.appendParameters(map, getApplication());
    AbstractConfig.appendParameters(map, getModule());
    // remove 'default.' prefix for configs from ProviderConfig
    // appendParameters(map, provider, Constants.DEFAULT_KEY);
    AbstractConfig.appendParameters(map, provider);
    AbstractConfig.appendParameters(map, protocolConfig);
    AbstractConfig.appendParameters(map, this);
    metadataReportConfig metadataReportConfig = getmetadataReportConfig();
    if (metadataReportConfig != null && metadataReportConfig.isValid()) {
        map.putIfAbsent(metaDATA_KEY, REMOTE_metaDATA_STORAGE_TYPE);
    }
    if (CollectionUtils.isNotEmpty(getMethods())) {
        for (MethodConfig method : getMethods()) {
            AbstractConfig.appendParameters(map, method, method.getName());
            String retryKey = method.getName() + ".retry";
            if (map.containsKey(retryKey)) {
                String retryValue = map.remove(retryKey);
                if ("false".equals(retryValue)) {
                    map.put(method.getName() + ".retries", "0");
                }
            }
            List arguments = method.getArguments();
            if (CollectionUtils.isNotEmpty(arguments)) {
                for (ArgumentConfig argument : arguments) {
                    // convert argument type
                    if (argument.getType() != null && argument.getType().length() > 0) {
                        Method[] methods = interfaceClass.getMethods();
                        // visit all methods
                        if (methods.length > 0) {
                            for (int i = 0; i < methods.length; i++) {
                                String methodName = methods[i].getName();
                                // target the method, and get its signature
                                if (methodName.equals(method.getName())) {
                                    Class[] argtypes = methods[i].getParameterTypes();
                                    // one callback in the method
                                    if (argument.getIndex() != -1) {
                                        if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                                            AbstractConfig.appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                                        } else {
                                            throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                        }
                                    } else {
                                        // multiple callbacks in the method
                                        for (int j = 0; j < argtypes.length; j++) {
                                            Class argclazz = argtypes[j];
                                            if (argclazz.getName().equals(argument.getType())) {
                                                AbstractConfig.appendParameters(map, argument, method.getName() + "." + j);
                                                if (argument.getIndex() != -1 && argument.getIndex() != j) {
                                                    throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else if (argument.getIndex() != -1) {
                        AbstractConfig.appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                    } else {
                        throw new IllegalArgumentException("Argument config must set index or type attribute.eg:  or ");
                    }

                }
            }
        } // end of methods for
    }

    if (ProtocolUtils.isGeneric(generic)) {
        map.put(GENERIC_KEY, generic);
        map.put(METHODS_KEY, ANY_VALUE);
    } else {
        String revision = Version.getVersion(interfaceClass, version);
        if (revision != null && revision.length() > 0) {
            map.put(REVISION_KEY, revision);
        }

        String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
        if (methods.length == 0) {
            logger.warn("No method found in service interface " + interfaceClass.getName());
            map.put(METHODS_KEY, ANY_VALUE);
        } else {
            map.put(METHODS_KEY, StringUtils.join(new HashSet(Arrays.asList(methods)), ","));
        }
    }

    
    if(ConfigUtils.isEmpty(token) && provider != null) {
        token = provider.getToken();
    }

    if (!ConfigUtils.isEmpty(token)) {
        if (ConfigUtils.isDefault(token)) {
            map.put(TOKEN_KEY, UUID.randomUUID().toString());
        } else {
            map.put(TOKEN_KEY, token);
        }
    }
    //init servicemetadata attachments
    servicemetadata.getAttachments().putAll(map);

    // export service
    String host = findConfigedHosts(protocolConfig, registryURLs, map);
    Integer port = findConfigedPorts(protocolConfig, name, map);
    URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);

    // You can customize Configurator to append extra parameters
    if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
        .hasExtension(url.getProtocol())) {
        url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
            .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
    }

    String scope = url.getParameter(SCOPE_KEY);
    // don't export when none is configured
    if (!SCOPE_NONE.equalsIgnoreCase(scope)) {

        // export to local if the config is not remote (export to remote only when config is remote)
        if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
            exportLocal(url);
        }
        // export to remote if the config is not local (export to local only when config is local)
        if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
            if (CollectionUtils.isNotEmpty(registryURLs)) {
                for (URL registryURL : registryURLs) {
                    //if protocol is only injvm ,not register
                    if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
                        continue;
                    }
                    url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
                    URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
                    if (monitorUrl != null) {
                        url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
                    }
                    if (logger.isInfoEnabled()) {
                        if (url.getParameter(REGISTER_KEY, true)) {
                            logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                        } else {
                            logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                        }
                    }

                    // For providers, this is used to enable custom proxy to generate invoker
                    String proxy = url.getParameter(PROXY_KEY);
                    if (StringUtils.isNotEmpty(proxy)) {
                        registryURL = registryURL.addParameter(PROXY_KEY, proxy);
                    }

                    Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
                    DelegateProvidermetaDataInvoker wrapperInvoker = new DelegateProvidermetaDataInvoker(invoker, this);

                    Exporter exporter = PROTOCOL.export(wrapperInvoker);
                    exporters.add(exporter);
                }
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                }
                Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
                DelegateProvidermetaDataInvoker wrapperInvoker = new DelegateProvidermetaDataInvoker(invoker, this);

                Exporter exporter = PROTOCOL.export(wrapperInvoker);
                exporters.add(exporter);
            }
            
            WritablemetadataService metadataService = WritablemetadataService.getExtension(url.getParameter(metaDATA_KEY, DEFAULT_metaDATA_STORAGE_TYPE));
            if (metadataService != null) {
                metadataService.publishServiceDefinition(url);
            }
        }
    }
    this.urls.add(url);
}

.
   2.3、dubbo扩展
   在类级别标准@SPI(RandomLoadBalance.NAME).
       自定义扩展点
       在resource/meta-INF/dubbo/ org.apache.dubbo.rpc.cluster.LoadBalance

 public class GpDefineLoadBalance extends AbstractLoadBalance{
      @Override
      protected  Invoker doSelect(List> invokers, URL url, Invocation invocation) {
  
          return null;
      }
  }

.
       1)、指定名称扩展点
       内部扩展点Protocol的全路径名称, 在/meta-INF/dubbo/intenal

random=org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
roundrobin=org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
leastactive=org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance
consistenthash=org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance
shortestresponse=org.apache.dubbo.rpc.cluster.loadbalance.ShortestResponseLoadBalance
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("name");


       源码分析:
       ExtensionLoader.getExtensionLoader:加载扩展点的class类型的参数,该参数必须是接口,且注解@SPI。检查通过之后,首先检查ExtensionLoader缓存中是否存在该扩展对应的ExtensionLoader,有则返回,否则创建新的ExtensionLoader负责加载扩展实现,并缓存起来。对于每一个class扩展,dubbo只会有一个对应的ExtensionLoader实例

	
	public static  ExtensionLoader getExtensionLoader(Class type) {
        if (type == null) {
            throw new IllegalArgumentException("Extension type == null");
        }
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        //缓存获取扩展类型ExtensionLoader
        ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        if (loader == null) {
        	//2、创建扩展类型ExtensionLoader
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
            loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }

	
   private ExtensionLoader(Class type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

.
       ExtensionLoader.getExtensionLoader(@SPI interface).getExtension:根据名字获取对应的实例

    public T getExtension(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Extension name == null");
        }
        //如果name=true,表示返回一个默认的扩展点
        if ("true".equals(name)) {
            return getDefaultExtension();
        }
        final Holder holder = getOrCreateHolder(name);
        //缓存一下,如果实例已经加载过了,直接从缓存读取 @SPI(默认)
        Object instance = holder.get();
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                 	//根据名称创建实例
                    instance = createExtension(name);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }
 

.
       getExtensionClasses 返回一个map对象, key = name(扩展点的名字), clazz=name对应的扩
展点类
       例如name是:random, 那么此时clazz=RandomLoadBalance(RandomLoadBalance rd=
(RandomLoadBalance)ExtensionLoader.getExtensionLoader(Loadbalance.class).getExtension(“random”);)

	
	private T createExtension(String name) {
		//2、getExtensionClasses 获取/meta-INF/dubbo/intenal 配置
       Class clazz = getExtensionClasses().get(name);
       if (clazz == null) {
           throw findException(name);
       }
       try {
           T instance = (T) EXTENSION_INSTANCES.get(clazz);
           if (instance == null) {
               EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
               instance = (T) EXTENSION_INSTANCES.get(clazz);
           }
           //实例注入,可以猜到,这里应该是对这个实例中的成员属性来实现依赖注入的功能:如果被加载的实例中,有成员属性,比如【AdaptiveCompiler】 这个类,它里面提供了一个setDefaultCompiler的方法,那么这个方法,那么当前injectExtension会扫描到这个set方法,进行依赖注入
           injectExtension(instance);
           Set> wrapperClasses = cachedWrapperClasses;
           if (CollectionUtils.isNotEmpty(wrapperClasses)) {
               for (Class wrapperClass : wrapperClasses) {
                   instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
               }
           }
           initExtension(instance);
           return instance;
       } catch (Throwable t) {
           throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                   type + ") couldn't be instantiated: " + t.getMessage(), t);
       }
   }

	
    private Map> getExtensionClasses() {
        Map> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                	//3、扫描策略
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

	
    private Map> loadExtensionClasses() {
        cacheDefaultExtensionName();

        Map> extensionClasses = new HashMap<>();
		// strategies: meta-INF/dubbo   meta-INF/dubbo/internal   meta-INF/services
        for (LoadingStrategy strategy : strategies) {
            loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
            loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
        }

        return extensionClasses;
    }

加载指定路径下的文件内容,保存到map集合中
对存在依赖注入的扩展点进行依赖注入
对存在wrapper类的扩展点,实现扩展点的包装
.
       2)、自适应扩展点:在运行期间,根据上下文决定返回哪个扩展点

ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

标识:@Adaptive 类或方法上
实现:类直接返回修饰的类;方法创建一个代理类

	
  	public T getAdaptiveExtension() {
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            if (createAdaptiveInstanceError != null) {
                throw new IllegalStateException("Failed to create adaptive instance: " +
                        createAdaptiveInstanceError.toString(),
                        createAdaptiveInstanceError);
            }

            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        }

        return (T) instance;
    }
    
	
    private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
    
	
    private Class getAdaptiveExtensionClass() {
        getExtensionClasses();
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
	
  private Class createAdaptiveExtensionClass() {
        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
        ClassLoader classLoader = findClassLoader();
        org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
    }

自适应扩展点 injectExtension

	private T injectExtension(T instance) {

        if (objectFactory == null) {
            return instance;
        }

        try {
            for (Method method : instance.getClass().getMethods()) {
                if (!isSetter(method)) {
                    continue;
                }
                
                if (method.getAnnotation(DisableInject.class) != null) {
                    continue;
                }
                //获得这个方法的参 数参数类型
                Class pt = method.getParameterTypes()[0];
                if (ReflectUtils.isPrimitives(pt)) {
                	//如果不是对象类型,则跳过
                    continue;
                }

                try {
                	//获得这个方法 的属性名称
                    String property = getSetterProperty(method);
                    //根据class以及name,使用自适应扩展点进行加载并且赋值到当前的set方法中
                    Object object = objectFactory.getExtension(pt, property);
                    if (object != null) {
                        method.invoke(instance, object);
                    }
                } catch (Exception e) {
                    logger.error("Failed to inject via method " + method.getName()
                            + " of interface " + type.getName() + ": " + e.getMessage(), e);
                }

            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }

objectFactory
获取ExtensionLoader的时候,对objectFactory进行了初始化。

   private ExtensionLoader(Class type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

public T getAdaptiveExtension() {
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            if (createAdaptiveInstanceError != null) {
                throw new IllegalStateException("Failed to create adaptive instance: " +
                        createAdaptiveInstanceError.toString(),
                        createAdaptiveInstanceError);
            }

            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        }

        return (T) instance;
    }

    private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }

 private Class getAdaptiveExtensionClass() {
        getExtensionClasses();
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }


adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List factories;

    public AdaptiveExtensionFactory() {
        ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List list = new ArrayList();
        for (String name : loader.getSupportedExtensions()) {
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

	//除了自定义的自适应适配器类以外,还有两个实现类,一个是SPI,一个是Spring。AdaptiveExtensionFactory轮询这2个,从一个中获取到就返回
    @Override
    public  T getExtension(Class type, String name) {
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }

}

.
   
       3)、激活扩展点

ExtensionLoader.getExtensionLoader(Protocol.class).getActiveExtension

标识:@Activate
实现:只要url参数中包含CACHE_KEY,那么 CacheFilter就会被激活
@Activate(group = {CONSUMER, PROVIDER}, value = CACHE_KEY)
  public class CacheFilter implements Filter {
}
使用:

		//原来10 -> 11
        ExtensionLoader extensionLoader=ExtensionLoader.getExtensionLoader(Filter.class);
        URL url=new URL("","",0);
        url=url.addParameter("cache","cache");
        List filters=extensionLoader.getActivateExtension(url,"cache");
        System.out.println(filters.size());

wrapper包装:isWrapperClass -> loadDirectory -> loadResource -> loadClass -> cacheWrapperClass-> ProtocolListenerWrapper

qos=org.apache.dubbo.qos.protocol.QosProtocolWrapper filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper

QosProtocolWrapper :在线运维,提供telnet命令
ProtocolFilterWrapper :对invoker进行filter的包装,实现请求的过滤
ProtocolListenerWrapper:用于服务export时候插入监听机制

getExtension->createExtension:会对cacheWrapperClass集合进行判断,如果集合
不为空,则进行包装

    private T createExtension(String name) {
        Class clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);
            Set> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            initExtension(instance);
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                    type + ") couldn't be instantiated: " + t.getMessage(), t);
        }
    }
dubbo服务发布流程源码分析

.

1、dubbo服务发布 ServiceConfig.doExportUrlsFor1Protocol
        
        String scope = url.getParameter(SCOPE_KEY);
        // don't export when none is configured
        if (!SCOPE_NONE.equalsIgnoreCase(scope)) {

            // export to local if the config is not remote (export to remote only when config is remote)
            // 如果scope!=remote, 则先本地暴露服务
            if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
                exportLocal(url);
            }
            // export to remote if the config is not local (export to local only when config is local)
            // 暴露远程服务
            if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
                if (CollectionUtils.isNotEmpty(registryURLs)) {
                    for (URL registryURL : registryURLs) {
                        //if protocol is only injvm ,not register
                        //如果设置的protocol是injvm,跳过
                        if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
                            continue;
                        }
                        url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
                        URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
                        if (monitorUrl != null) {
                            url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
                        }
                        if (logger.isInfoEnabled()) {
                            if (url.getParameter(REGISTER_KEY, true)) {
                                logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                            } else {
                                logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                            }
                        }

                        // For providers, this is used to enable custom proxy to generate invoker
                        // 是否采用自定义的动态代理机制,默认是javassist
                        String proxy = url.getParameter(PROXY_KEY);
                        if (StringUtils.isNotEmpty(proxy)) {
                            registryURL = registryURL.addParameter(PROXY_KEY, proxy);
                        }
                        //获得一个自适应扩展点,这个时候返回的Invoker是一个动态代理类。 url:registry://ip
                        Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
                        DelegateProvidermetaDataInvoker wrapperInvoker = new DelegateProvidermetaDataInvoker(invoker, this);

                        Exporter exporter = PROTOCOL.export(wrapperInvoker);
                        exporters.add(exporter);
                    }
                } else {
                    if (logger.isInfoEnabled()) {
                        logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                    }
                    //Invoker ,调用器. 服务提供者、服务的消费者 
                    Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
                    DelegateProvidermetaDataInvoker wrapperInvoker = new DelegateProvidermetaDataInvoker(invoker, this);
					//2、RegistryProtocol发布协议 -> Protocol$Adaptive -> 得到一个具体的扩展点协议[QosProtocolWrapper(ProtocolFilterWrapper(ProtocolListenerWrapper(RegistryProtocol))]:registry://ip:port
                    Exporter exporter = PROTOCOL.export(wrapperInvoker);
                    exporters.add(exporter);
                }
                
                WritablemetadataService metadataService = WritablemetadataService.getExtension(url.getParameter(metaDATA_KEY, DEFAULT_metaDATA_STORAGE_TYPE));
                if (metadataService != null) {
                    metadataService.publishServiceDefinition(url);
                }
            }
        }
        this.urls.add(url);
    }

.

2、PROTOCOL:动态生成适配器类,根据传递进来的参数来选择合适的协议来发布服务。遍历registryURLs发布registry://ip:port
          	        private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
import org.apache.dubbo.common.extension.ExtensionLoader;

public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
    public void destroy() {
        throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    public int getDefaultPort() {
        throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
        org.apache.dubbo.common.URL url = arg0.getUrl();
        //url为registry://ip
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
            //获得RegistryProtocol
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dub bo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
    }

    public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg1;
        
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dub bo.rpc.Protocol.class).getExtension(extName);
        return extension.refer(arg0, arg1);
    }

    public java.util.List getServers() {
        throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }
}

.

3、RegistryProtocol.export
 public  Exporter export(final Invoker originInvoker) throws RpcException {
 		//这里获得的是zookeeper注册中心的url: zookeeper://ip:port
        URL registryUrl = getRegistryUrl(originInvoker);
        // url to export locally
        //这里是获得服务提供者的url, dubbo://ip:port...
        URL providerUrl = getProviderUrl(originInvoker);

        // Subscribe the override data
        // FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call
        //  the same service. Because the subscribed is cached key with the name of the service, it causes the
        //  subscription information to cover.
        //订阅override数据。在admin控制台可以针对服务进行治理,比如修改权重,修改路由机制等,当 注册中心有此服务的覆盖配置注册进来时,推送消息给提供者,重新暴露服务
        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl);
        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);

        providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener);
        //export invoker 启动一个NettyServer,发布Dubbo协议的服务
        //这里就交给了具体的协议去暴露服务(很重要)
        final ExporterChangeableWrapper exporter = doLocalExport(originInvoker, providerUrl);

        // url to registry
        // 6、根据invoker中的url获取Registry实例: zookeeperRegistry(服务注册实际上就是把dubbo的协议url地址保存到第三方注册中心上)
        final Registry registry = getRegistry(originInvoker);
        //获取要注册到注册中心的URL: dubbo://ip:port
        final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl);

        // decide if we need to delay publish
        boolean register = providerUrl.getParameter(REGISTER_KEY, true);
        if (register) {
        	//服务注册:是否配置了注册中心,如果是, 则需要注册
            register(registryUrl, registeredProviderUrl);
        }

        // register stated url on provider model
        registerStatedUrl(registryUrl, registeredProviderUrl, register);

        // Deprecated! Subscribe to override rules in 2.6.x or before.
        //设置注册中心的订阅
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);

        exporter.setRegisterUrl(registeredProviderUrl);
        exporter.setSubscribeUrl(overrideSubscribeUrl);

        notifyExport(exporter);
        //Ensure that a new exporter instance is returned every time export
        //保证每次export都返回一个新的exporter实例
        return new DestroyableExporter<>(exporter);
    }

.

4、doLocalExport 发布服务

主要流程:
   构建一个exporterMap,以服务路径名称作为key,把invoker包装成了DubboExporter作为value
存储
   针对同一台机器上的多个服务,只启动一个服务实例
   采用Netty4来发布服务

    
    private  ExporterChangeableWrapper doLocalExport(final Invoker originInvoker, URL providerUrl) {
        String key = getCacheKey(originInvoker);

        return (ExporterChangeableWrapper) bounds.computeIfAbsent(key, s -> {
            Invoker invokerDelegate = new InvokerDelegate<>(originInvoker, providerUrl);
            //发布服务
            return new ExporterChangeableWrapper<>((Exporter) protocol.export(invokerDelegate), originInvoker);
        });
    }

    
    public  Exporter export(Invoker invoker) throws RpcException {
        URL url = invoker.getUrl();

        // export service.
        String key = serviceKey(url);
        DubboExporter exporter = new DubboExporter(invoker, key, exporterMap);
        exporterMap.put(key, exporter);

        //export an stub service for dispatching event
        //是否是本地存根事件
        Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);
        //是否配置了参数回调机制
        Boolean isCallbackservice = url.getParameter(IS_CALLBACK_SERVICE, false);
        if (isStubSupportEvent && !isCallbackservice) {
            String stubServiceMethods = url.getParameter(STUB_EVENT_METHODS_KEY);
            if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
                if (logger.isWarnEnabled()) {
                    logger.warn(new IllegalStateException("consumer [" + url.getParameter(INTERFACE_KEY) +
                            "], has set stubproxy support event ,but no stub methods founded."));
                }

            }
        }
        //开启服务
        openServer(url);
        optimizeSerialization(url);

        return exporter;
    }

    
    private void openServer(URL url) {
        // find server.
        // 获取 host:port,并将其作为服务器实例的 key,用于标识当前的服务器实例
        String key = url.getAddress();
        //client can export a service which's only for server to invoke
        //client 也可以暴露一个只有server可以调用的服务
        boolean isServer = url.getParameter(IS_SERVER_KEY, true);
        if (isServer) {
        	//是否在serverMap中缓存了
            ProtocolServer server = serverMap.get(key);
            if (server == null) {
                synchronized (this) {
                    server = serverMap.get(key);
                    if (server == null) {
                    	// 创建服务器实例
                        serverMap.put(key, createServer(url));
                    }
                }
            } else {
                // server supports reset, use together with override
                // 服务器已创建,则根据 url 中的配置重置服务器
                server.reset(url);
            }
        }
    }

    
    private ProtocolServer createServer(URL url) {
    	//组装url,在url中添加心跳时间、编解码参数
        url = URLBuilder.from(url)
                // send readonly event when server closes, it's enabled by default
                .addParameterIfAbsent(CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString())
                // enable heartbeat by default
                .addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT))
                .addParameter(CODEC_KEY, DubboCodec.NAME)
                .build();
        String str = url.getParameter(SERVER_KEY, DEFAULT_REMOTING_SERVER);
		//通过 SPI 检测是否存在 server 参数所代表的 Transporter 拓展,不存在则抛出异常
        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) {
            throw new RpcException("Unsupported server type: " + str + ", url: " + url);
        }
		//创建ExchangeServer
        ExchangeServer server;
        try {
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }

        str = url.getParameter(CLIENT_KEY);
        if (str != null && str.length() > 0) {
            Set supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
            if (!supportedTypes.contains(str)) {
                throw new RpcException("Unsupported client type: " + str);
            }
        }

        return new DubboProtocolServer(server);
    }

    
    public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
        return getExchanger(url).bind(url, handler);
    }
    
	    
	    public static Exchanger getExchanger(URL url) {
	        String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER);
	        return getExchanger(type);
	    }
	    
		
	    public static Exchanger getExchanger(String type) {
	        return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
	    }
	    
		
		public class HeaderExchanger implements Exchanger {
		    public static final String NAME = "header";		
		    @Override
		    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
		        return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
		    }		
		}
		
		public static RemotingServer bind(URL url, ChannelHandler... handlers) throws RemotingException {
	        if (url == null) {
	            throw new IllegalArgumentException("url == null");
	        }
	        if (handlers == null || handlers.length == 0) {
	            throw new IllegalArgumentException("handlers == null");
	        }
	        ChannelHandler handler;
	        if (handlers.length == 1) {
	            handler = handlers[0];
	        } else {
	            handler = new ChannelHandlerDispatcher(handlers);
	        }
	        return getTransporter().bind(url, handler);
	    }
			
			 public static Transporter getTransporter() {
			       return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
			 }
		   	
			public class NettyTransporter implements Transporter {
			    public static final String NAME = "netty";
			    @Override
			    public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException {
			        return new NettyServer(url, handler);
			    }		
			}
				
			   public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
			        // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
			        // the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler
			        super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url));
			    }
			    
			    public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
			        super(url, handler);
			        localAddress = getUrl().toInetSocketAddress();
					// 获取 ip 和端口
			        String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost());
			        int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort());
			        if (url.getParameter(ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) {
			            bindIp = ANYHOST_VALUE;
			        }
			        bindAddress = new InetSocketAddress(bindIp, bindPort);
			        this.accepts = url.getParameter(ACCEPTS_KEY, DEFAULT_ACCEPTS);
			        this.idleTimeout = url.getParameter(IDLE_TIMEOUT_KEY, DEFAULT_IDLE_TIMEOUT);
			        try {
			       		// 调用模板方法 doOpen 启动服务器
			            doOpen();
			            if (logger.isInfoEnabled()) {
			                logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress());
			            }
			        } catch (Throwable t) {
			            throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName()
			                    + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t);
			        }
			        executor = executorRepository.createExecutorIfAbsent(url);
			    }
			   
			   //开启netty服务
				protected void doOpen() throws Throwable {
				        bootstrap = new ServerBootstrap();
				
				        bossGroup = NettyEventLoopFactory.eventLoopGroup(1, "NettyServerBoss");
				        workerGroup = NettyEventLoopFactory.eventLoopGroup(
				                getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
				                "NettyServerWorker");
				
				        final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
				        channels = nettyServerHandler.getChannels();
				
				        bootstrap.group(bossGroup, workerGroup)
				                .channel(NettyEventLoopFactory.serverSocketChannelClass())
				                .option(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
				                .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
				                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
				                .childHandler(new ChannelInitializer() {
				                    @Override
				                    protected void initChannel(SocketChannel ch) throws Exception {
				                        // FIXME: should we use getTimeout()?
				                        int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
				                        NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
				                        if (getUrl().getParameter(SSL_ENABLED_KEY, false)) {
				                            ch.pipeline().addLast("negotiation",
				                                    SslHandlerInitializer.sslServerHandler(getUrl(), nettyServerHandler));
				                        }
				                        ch.pipeline()
				                                .addLast("decoder", adapter.getDecoder())
				                                .addLast("encoder", adapter.getEncoder())
				                                .addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
				                                .addLast("handler", nettyServerHandler);
				                    }
				                });
				        // bind
				        ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
				        channelFuture.syncUninterruptibly();
				        channel = channelFuture.channel();
				
				    }

.

5、Invoker

5.1、ServiceConfig.doExportUrlsFor1Protocol中

  Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
  DelegateProvidermetaDataInvoker wrapperInvoker = new DelegateProvidermetaDataInvoker(invoker, this);

  Exporter exporter = PROTOCOL.export(wrapperInvoker);
  exporters.add(exporter);

	1)、通过ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName)获取了一个指定名称的扩展点
	2)、在dubbo-rpc-api/resources/meta-INF/com.alibaba.dubbo.rpc.ProxyFactory中,定义了javassis=JavassisProxyFactory
	3)、调用JavassisProxyFactory的getInvoker方法
		
		 private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

		
		 @SPI("javassist") public interface ProxyFactory {

		
		public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
		    public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
		        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
		        if (arg0.getUrl() == null)
		            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
		        org.apache.dubbo.common.URL url = arg0.getUrl();
		        String extName = url.getParameter("proxy", "javassist");
		        if (extName == null)
		            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
		        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
		        return extension.getProxy(arg0);
		    }
		
		    public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, boolean arg1) throws org.apache.dubbo.rpc.RpcException {
		        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
		        if (arg0.getUrl() == null)
		            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
		        org.apache.dubbo.common.URL url = arg0.getUrl();
		        String extName = url.getParameter("proxy", "javassist");
		        if (extName == null)
		            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
		        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
		        return extension.getProxy(arg0, arg1);
		    }
		
		    public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {
		        if (arg2 == null) throw new IllegalArgumentException("url == null");
		        org.apache.dubbo.common.URL url = arg2;
		        String extName = url.getParameter("proxy", "javassist");
		        if (extName == null)
		            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
		        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
		        return extension.getInvoker(arg0, arg1, arg2);
		    }
		}


5.2、JavassistProxyFactory.getInvoker

	
   	@Override
    public  Invoker getInvoker(T proxy, Class type, URL url) {
        // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

5.3、 wrapper.invokeMethod
在Wrapper.getWrapper中的makeWrapper,会创建一个动态代理,核心的方法invokeMethod代码如下

    public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException {
        com.sk.spring.boot.bubbo.api.ILoginFacade w;
        try {
            w = ((com.sk.spring.boot.bubbo.api.ILoginFacade) );
        } catch (Throwable e) {
            throw new IllegalArgumentException(e);
        }
        try {
            if ("login".equals() && .length == 1) {
                return ($w) w.login((java.lang.String) [0]);
            }
        } catch (Throwable e) {
            throw new java.lang.reflect.InvocationTargetException(e);
        }
        throw new org.apache.dubbo.common.bytecode.NoSuchMethodException("Not found method "" +  + "" in class com.sk.spring.boot.bubbo.api.ILoginFacade.");
    }
6、服务注册流程继续 【3、RegistryProtocol.export】

6.1、根据invoker中的url获取Registry实例: zookeeperRegistry(服务注册实际上就是把dubbo的协议url地址保存到第三方注册中心上)
final Registry registry = getRegistry(originInvoker);

  
  protected Registry getRegistry(final Invoker originInvoker) {
  		//1. 把url转化为对应配置的注册中心的具体协议
        URL registryUrl = getRegistryUrl(originInvoker);
        //2. 根据具体协议,从registryFactory中获得指定的注册中心实现
        return registryFactory.getRegistry(registryUrl);
    }

	
	protected URL getRegistryUrl(Invoker originInvoker) {
        URL registryUrl = originInvoker.getUrl();
        if (REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {
            String protocol = registryUrl.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY);
            registryUrl = registryUrl.setProtocol(protocol).removeParameter(REGISTRY_KEY);
        }
        return registryUrl;
    }

6.2、 根据具体协议,从registryFactory中获得指定的注册中心实现

	
	private RegistryFactory registryFactory;
 	public void setRegistryFactory(RegistryFactory registryFactory) {
        this.registryFactory = registryFactory;
    }
	
	
	@SPI("dubbo")
	public interface RegistryFactory {
	 	@Adaptive({"protocol"})
    	Registry getRegistry(URL url);
	}

	
	service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryFactory
	wrapper=org.apache.dubbo.registry.RegistryFactoryWrapper
	dubbo=org.apache.dubbo.registry.dubbo.DubboRegistryFactory
	multicast=org.apache.dubbo.registry.multicast.MulticastRegistryFactory
	zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperRegistryFactory
	redis=org.apache.dubbo.registry.redis.RedisRegistryFactory
	consul=org.apache.dubbo.registry.consul.ConsulRegistryFactory
	
	etcd3=org.apache.dubbo.registry.etcd.EtcdRegistryFactory
	nacos=org.apache.dubbo.registry.nacos.NacosRegistryFactory
	sofa=org.apache.dubbo.registry.sofa.SofaRegistryFactory
	multiple=org.apache.dubbo.registry.multiple.MultipleRegistryFactory

	
	import org.apache.dubbo.common.extension.ExtensionLoader;
	public class RegistryFactory$Adaptive implements org.apache.dubbo.registry.RegistryFactory {
	    public org.apache.dubbo.registry.Registry getRegistry(org.apache.dubbo.common.URL arg0) {
	        if (arg0 == null) throw new IllegalArgumentException("url == null");
	        org.apache.dubbo.common.URL url = arg0;
	        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
	        if (extName == null)
	            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.registry.RegistryFactory) name from url (" + url.toString() + ") use keys([protocol])");
	        org.apache.dubbo.registry.RegistryFactory extension = (org.apache.dubbo.registry.RegistryFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.registry.RegistryFactory.class).getExtension(extName);
	        return extension.getRegistry(arg0);
	    }
	}

	
	public class RegistryFactoryWrapper implements RegistryFactory {
	    private RegistryFactory registryFactory;
	
	    public RegistryFactoryWrapper(RegistryFactory registryFactory) {
	        this.registryFactory = registryFactory;
	    }
	
	    @Override
	    public Registry getRegistry(URL url) {
	        return new ListenerRegistryWrapper(registryFactory.getRegistry(url),
	                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(RegistryServiceListener.class)
	                        .getActivateExtension(url, "registry.listeners")));
	    }
	}
	

6.3、register注册

		final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl);
        // decide if we need to delay publish
        //获得注册的服务提供者地址
        boolean register = providerUrl.getParameter(REGISTER_KEY, true);
        if (register) {
        	//调用register发起注册
            register(registryUrl, registeredProviderUrl);
        }

	
 	private void register(URL registryUrl, URL registeredProviderUrl) {
        Registry registry = registryFactory.getRegistry(registryUrl);
        registry.register(registeredProviderUrl);
    }
    
	
	@Override
    public void register(URL url) {
        try {
            registry.register(url);
        } finally {
            if (CollectionUtils.isNotEmpty(listeners)) {
                RuntimeException exception = null;
                for (RegistryServiceListener listener : listeners) {
                    if (listener != null) {
                        try {
                            listener.onRegister(url);
                        } catch (RuntimeException t) {
                            logger.error(t.getMessage(), t);
                            exception = t;
                        }
                    }
                }
                if (exception != null) {
                    throw exception;
                }
            }
        }
    }
    
	
 	@Override
    public void register(URL url) {
        if (!acceptable(url)) {
            logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type.");
            return;
        }
        //调用父类的register方法,讲当前url添加到缓存集合中
        super.register(url);
        removeFailedRegistered(url);
        removeFailedUnregistered(url);
        try {
            // Sending a registration request to the server side
            doRegister(url);
        } catch (Exception e) {
            Throwable t = e;

            // If the startup detection is opened, the Exception is thrown directly.
            boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                    && url.getParameter(Constants.CHECK_KEY, true)
                    && !CONSUMER_PROTOCOL.equals(url.getProtocol());
            boolean skipFailback = t instanceof SkipFailbackWrapperException;
            if (check || skipFailback) {
                if (skipFailback) {
                    t = t.getCause();
                }
                throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
            } else {
                logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
            }

            // Record a failed registration request to a failed list, retry regularly
            addFailedRegistered(url);
        }
    }
    
	
	@Override
    public void doRegister(URL url) {
        try {
            zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
        } catch (Throwable e) {
            throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
7、服务消费流程继续

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5664777.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)