SOFA RPC源码解析之Rest服务(1)-服务发布

版权声明: https://blog.csdn.net/beyondself_77/article/details/80862415

1.SOFA RPC源码解析

1.1  Rest服务

1.1.1 服务发布

        以SOFABoot自带的RPC案例sofaboot-sample-with-rpc为例,详细描述SOFABoot Rest服务发布原理。

        在此提前说明,源码分析主要分析主流程,以及本人认为比较重要的一些内容,对于其它部分,大家可以基于本文档,自行研读。

        RPC案例的SpringXML配置文件内容如下:

1.  <?xml version="1.0"encoding="UTF-8"?>
2.  <beansxmlns="http://www.springframework.org/schema/beans"
3.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4.         xmlns:sofa="http://sofastack.io/schema/sofaboot"
5.         xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
6.              http://sofastack.io/schema/sofaboot  http://sofastack.io/schema/sofaboot.xsd"
7.         default-autowire="byName">
8.   
9.      <bean id="personServiceImpl"class="com.alipay.sofa.boot.examples.demo.rpc.bean.PersonServiceImpl"/>
10.     
11.     <sofa:serviceref="personServiceImpl" interface="com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService">       
12.         <sofa:binding.rest/>
13.     </sofa:service>   
14.  
15.      <sofa:referenceid="personReferenceRest"interface="com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService"jvm-first="false">
16.          <sofa:binding.rest>
17.              <sofa:global-attrstimeout="300000" address-wait-time="2000"/>
18.              <sofa:routetarget-url="127.0.0.1:8341"/>
19.              <sofa:methodname="sayName" timeout="300000"/>
20.          </sofa:binding.rest>
21.      </sofa:reference>
22.  
23.     <bean id="personFilter"class="com.alipay.sofa.boot.examples.demo.rpc.bean.PersonServiceFilter"/>
24.  
25. </beans>

        在SpringXML配置文件中:

        1.   通过XML元素bean定义PersonService接口实现类PersonServiceImpl;

        2.   通过XML元素sofa:service以restful格式发布PersonService接口服务;

        启动本应用,启动流程在《启动原理》中已经详细描述,在此不再详述,直接到从SpringXML配置文件加载Bean定义开始分析。

        一、   注册ServiceFactoryBean类对应的Bean定义

        调用AnnotationConfigEmbeddedWebApplicationContext(AbstractApplicationContext).refresh())方法刷新Spring应用上下文过程,通过invokeBeanFactoryPostProcessors(beanFactory)方法调用beanFactory中所有实现了BeanFactoryPostProcessor接口的类。当调用到ConfigurationClassPostProcessor类processConfigBeanDefinitions方法时,在循环处理@Configuration配置类过程中,调用ConfigurationClassBeanDefinitionReader类loadBeanDefinitions(configClasses)方法,处理解析完成的@Configuration配置类。此时,其中有一步是调用ConfigurationClassBeanDefinitionReader类loadBeanDefinitionsFromImportedResources(configClass.getImportedResources())方法,加载@ImportResource注解里面配置的SpringXML配置文件中定义的Bean。在这个方法中,使用XMLBeanDefinitionReader加载SpringXML配置文件中定义的Bean。

        接下来就是SpringXML配置文件中各种标签的解析过程。

        对于XML标签bean,由于是最基本的SpringXML标签,大家都应用比较熟悉了,在此不再详述。

        对于XML标签sofa:service,其处理过程如下:

        XMLBeanDefinitionReader类调用DefaultBeanDefinitionDocumentReader类registerBeanDefinitions方法注册Bean定义;

        DefaultBeanDefinitionDocumentReader类调用BeanDefinitionParserDelegate类parseCustomElement方法解析自定义的XML元素。

        在此,对于XML标签sofa:service,根据命名空间sofa对应的值http://sofastack.io/schema/sofaboot,在spring.handlers(此文件位于infra-sofa-boot-starter.jar)文件中,查找到XML标签的处理类SofaBootNamespaceHandler:

1.  http\://sofastack.io/schema/sofaboot=com.alipay.sofa.infra.config.spring.namespace.handler.SofaBootNamespaceHandler

        在SofaBootNamespaceHandler类中,调用findParserForElement方法,查找指定XML元素的解析类,此处service对应的BeanDefinitionParser解析类为com.alipay.sofa.runtime.spring.parser.ServiceDefinitionParser。

        使用ServiceDefinitionParser类把SpringXML配置文件中sofa:service标签定义的服务转换为ServiceFactoryBean,并注册到Spring应用上下文中。

        二、    创建ServiceFactoryBean类的实例

        调用AnnotationConfigEmbeddedWebApplicationContext(AbstractApplicationContext).refresh())方法刷新Spring应用上下文过程,通过finishBeanFactoryInitialization(beanFactory)方法实例化beanFactory中所有剩余的非延迟初始化的单实例对象。

        当实例化ServiceFactoryBean时,由于ServiceFactoryBean实现了Initializing接口,所以在调用ServiceFactoryBean类的初始化方法时,会调用ServiceFactoryBean类的afterPropertiesSet方法,进行实例的初始化操作。

        到现在为止,开始Rest服务发布流程:

        1.      根据XML标签sofa: service所包含的子标签sofa:binding.*(一个或多个,此处是sofa:binding.rest),解析出引用服务的类型,此处是restful风格的服务。

        2.      创建DefaultImplementation实例implementation,并设置其属性ref为SpringXML文件中sofa-service元素的ref属性中指定的接口实现,此处为SpringXML文件中id为personServiceImpl的com.alipay.sofa.boot.examples.demo.rpc.bean.PersonServiceImpl类的实例。

        3.   创建Service接口的实现ServiceImpl,其中,服务接口类型为com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService,接口模式为spring(表明此引用服务来自于SpringXML配置文件),target为ref(即id为personServiceImpl的PersonServiceImpl实例)。

        4.   如果解析出的bindings为空,则把JvmBinding增加到bindings列表中。

        5.   把解析出的binding(此处为RestBinding)增加到service实例的属性bindings列表中。

        6.   创建ServiceComponent实例componentInfo。

        7.   从sofaRuntimeContext实例中获取组件管理器实例componentManager,并调用其register方法注册刚才创建的服务组件componentInfo,具体注册操作在doRegister方法完成:

1.  private ComponentInfodoRegister(ComponentInfo ci) {
2.          ComponentName name = ci.getName();
3.          if (isRegistered(name)) {
4.              SofaLogger.error("Componentwas already registered: {0}", name);
5.              return getComponentInfo(name);
6.          }
7.   
8.          try {
9.              ci.register();
10.         } catch (Throwable e) {
11.             SofaLogger.error(e, "Failed toregister component: {0}", ci.getName());
12.             return null;
13.         }
14.  
15.         SofaLogger.info("Registeringcomponent: {0}", ci.getName());
16.  
17.         try {
18.             ComponentInfo old = registry.putIfAbsent(ci.getName(), ci);
19.             if (old != null) {
20.                 SofaLogger.error("Componentwas already registered: {0}", name);
21.                 return old;
22.             }
23.             if (ci.resolve()) {
24.                 typeRegistry(ci);
25.                 ci.activate();
26.             }
27.         } catch (Throwable e) {
28.             ci.exception(new Exception(e));
29.             SofaLogger.error(e, "Failed tocreate the component {0}", ci.getName());
30.         }
31.  
32.         return ci;
33.     }

    在组件管理器中注册组件的主要过程如下:

  • 获取组件名称,此处为service:com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService。
  • 判断组件管理器componentManager中是否存在指定名字的组件。如果有,则直接从组件管理器获取组件,并返回。如果没有,则继续注册流程。
  • 调用组件ServiceComponent类的register方法,更新组件状态为registered。
  • 把组件置入组件管理器的registry中(ConcurrentMap<ComponentName, ComponentInfo>)。
  • 调用组件ServiceComponent类的resolve方法,更新组件状态为resolved。
  • 把组件置入组件管理器的resolvedRegistry中(ConcurrentMap<ComponentType, Map<ComponentName,ComponentInfo>>)。
  • 调用组件ServiceComponent的activate方法,激活组件,并更新组件状态为activated。
1.      public void activate() throwsServiceRuntimeException {
2.   
3.          activateBinding();
4.          super.activate();
5.      }

    调用activateBinding方法,激活服务组件的所有Binding。

1.  private void activateBinding() {
2.   
3.          Object target = service.getTarget();
4.          ……
5.          if (service.hasBinding()) {
6.              boolean allPassed = true;
7.              Set<Binding> bindings =service.getBindings();
8.              for(Binding binding : bindings) {
9.                  BindingAdapter<Binding>bindingAdapter = this.bindingAdapterFactory
10.                     .getBindingAdapter(binding.getBindingType());
11.  
12.                 if (bindingAdapter == null) {
13.                     throw newServiceRuntimeException(……);
14.                 }
15.  
16.                 Object outBindingResult;
17.                 ……
18.                 try {
19.                     outBindingResult =bindingAdapter.outBinding(service, binding, target,
20.                         getContext());
21.                 } catch (Throwable t) {
22.                     allPassed = false;
23.                    ……
24.                     continue;
25.                 }
26.                 if(!Boolean.FALSE.equals(outBindingResult)) {
27.                     ……
28.                 } else {
29.                     binding.setHealthy(false);
30.                     SofaLogger.info("<<Out Binding [{0}] Fails, Don't publish service - {1}.",
31.                         binding.getBindingType(),service);
32.                 }
33.             }
34.  
35.             if (!allPassed) {
36.                 throw newServiceRuntimeException(……);
37.             }
38.         }
39.  
40.         SofaLogger.info("Register Service- {0}", service);
41.     }

        获取服务的目标类target;

        依次遍历服务所有Binding,分别为每种Binding发布服务,具体过程如下:

        根据Binding类型(此处为rest),获取BindingAdapter接口的实现,此处为:com.alipay.sofa.rpc.boot.runtime.adapter.RestBindingAdapter。

        调用RestBindingAdapter类outBinding方法,对外发布服务:

1.  public Object outBinding(Object contract,RpcBinding binding, Object target, SofaRuntimeContext sofaRuntimeContext) {
2.   
3.          String uniqueName = SpringBridge.getProviderConfigContainer().createUniqueName((Contract)contract, binding);
4.          ProviderConfig providerConfig =SpringBridge.getProviderConfigContainer().getProviderConfig(uniqueName);
5.   
6.          if (providerConfig == null) {
7.              throw new ServiceRuntimeException(……);
8.          }
9.   
10.         try {
11.             providerConfig.export();
12.         } catch (Exception e) {
13.             throw new ServiceRuntimeException(……);
14.         }
15.  
16.         if(SpringBridge.getProviderConfigContainer().isAllowPublish()) {
17.             Registry registry =SpringBridge.getRegistryConfigContainer().getRegistry();
18.             providerConfig.setRegister(true);
19.             registry.register(providerConfig);
20.         }
21.         return Boolean.TRUE;
22.     }

        通过工具类SpringBridge获取服务提供者配置容器类ProviderConfigContainer,然后调用ProviderConfigContainer类createUniqueName方法,根据接口类型和Binding类型,创建唯一ID,例如:com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService:1.0:rest。

        根据ID从ProviderConfigContainer中获取服务提供者配置类ProviderConfig。

        调用服务提供者配置类ProviderConfig的export方法,开始指定Binding类型的发布服务流程,此处为RestBinding类型的发布服务流程。

1.      public synchronized void export() {
2.          if (providerBootstrap == null) {
3.              providerBootstrap =Bootstraps.from(this);
4.          }
5.          providerBootstrap.export();
6.      }

        通过工具类Bootstraps,使用ExtensionLoader扩展机制,获取名字为ProviderConfig实例中bootstrap属性(此处为rest)指定的ProviderBootstrap接口实现类,此处为com.alipay.sofa.rpc.bootstrap.rest.RestProviderBootstrap。

        调用RestProviderBootstrap类export方法,开始真正的Rest服务发布流程:

1.  public void export() {
2.          if (providerConfig.getDelay() > 0) {// 延迟加载,单位毫秒
3.              Thread thread = new Thread(newRunnable() {
4.                  @Override
5.                  public void run() {
6.                      try {
7.                          Thread.sleep(providerConfig.getDelay());
8.                      } catch (Throwable ignore){ // NOPMD
9.                      }
10.                     doExport();
11.                 }
12.             });
13.             thread.setDaemon(true);
14.             thread.setName("DelayExportThread");
15.             thread.start();
16.         } else {
17.             doExport();
18.         }
19.     }

        如果服务提供者配置类中delay值大于0,表示延时加载,则启动新线程,在新线程运行过程中,休眠delay毫秒,然后调用doExport方法发布服务。否则,直接调用doExport方法发布服务。

1.  private void doExport() {
2.          if (exported) {
3.              return;
4.          }
5.          String key = providerConfig.buildKey();
6.          String appName =providerConfig.getAppName();
7.          // 检查参数
8.          checkParameters();
9.          ……
10.         // 注意同一interface,同一uniqleId,不同server情况
11.         AtomicInteger cnt = EXPORTED_KEYS.get(key);// 计数器
12.         if (cnt == null) { // 没有发布过
13.             cnt =CommonUtils.putToConcurrentMap(EXPORTED_KEYS, key, new AtomicInteger(0));
14.         }
15.         int c = cnt.incrementAndGet();
16.         int maxProxyCount =providerConfig.getRepeatedExportLimit();
17.         if (maxProxyCount > 0) {
18.             if (c > maxProxyCount) {
19.                 cnt.decrementAndGet();
20.                 // 超过最大数量,直接抛出异常
21.                 throw newSofaRpcRuntimeException(……);
22.             } else if (c > 1) {
23.                 ……
24.             }
25.         }
26.  
27.         try {
28.             // 构造请求调用器
29.             providerProxyInvoker = newProviderProxyInvoker(providerConfig);
30.             // 初始化注册中心
31.             if (providerConfig.isRegister()) {
32.                 List<RegistryConfig>registryConfigs = providerConfig.getRegistry();
33.                 if(CommonUtils.isNotEmpty(registryConfigs)) {
34.                     for (RegistryConfigregistryConfig : registryConfigs) {
35.                         RegistryFactory.getRegistry(registryConfig);// 提前初始化Registry
36.                     }
37.                 }
38.             }
39.             // 将处理器注册到server
40.             List<ServerConfig>serverConfigs = providerConfig.getServer();
41.             for (ServerConfig serverConfig :serverConfigs) {
42.                 try {
43.                     Server server =serverConfig.buildIfAbsent();
44.                     // 注册序列化接口
45.                     server.registerProcessor(providerConfig,providerProxyInvoker);
46.                     if(serverConfig.isAutoStart()) {
47.                         server.start();
48.                     }
49.                 } catch(SofaRpcRuntimeException e) {
50.                     throw e;
51.                 } catch (Exception e) {
52.                     LOGGER.errorWithApp(appName,"Catch exception when register processor to server: "
53.                         + serverConfig.getId(),e);
54.                 }
55.             }
56.  
57.             // 注册到注册中心
58.             providerConfig.setConfigListener(newProviderAttributeListener());
59.             register();
60.         } catch (Exception e) {
61.             cnt.decrementAndGet();
62.             if (e instanceofSofaRpcRuntimeException) {
63.                 throw (SofaRpcRuntimeException)e;
64.             } else {
65.                 throw newSofaRpcRuntimeException("Build provider proxy error!", e);
66.             }
67.         }
68.         // 记录一些缓存数据
69.         RpcRuntimeContext.cacheProviderConfig(this);
70.         exported = true;
71.     }

        在doExport方法中,其主要处理逻辑如下:

        1)   构建服务提供者配置类key:格式:interfaceId + ":" +uniqueId;例如: com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService:

        2)   检查参数,这是一个扩展点,通过在子类重写此方法,实现参数和属性的个性化处理。此处检查注入的ref是否是接口实现类、server不能为空。

        3)   判断该服务的发布数量(即创建代理的数量)是否超出最大重复发布数量repeatedExportLimit的设置,如果超出最大数量,则直接抛出异常。否则,继续。

        4)   创建请求调用器ProviderProxyInvoker实例,同时创建请求调用器中的过滤器链,最底层是调用过滤器ProviderInvoker;

1.      public ProviderProxyInvoker(ProviderConfigproviderConfig) {
2.          this.providerConfig = providerConfig;
3.          this.filterChain =FilterChain.buildProviderChain(providerConfig,
4.              newProviderInvoker(providerConfig));
5.      }

        5)   初始化注册中心,待细化;

        6)   遍历服务提供者配置的所有Server,依次创建Server实例server,将处理器注册到server,如果配置server自动启动,则启动server。此处只配置了一个server,即ServerConfig [protocol=rest, port=8341, host=0.0.0.0];

        针对每个Server,其主要处理过程如下:

        调用ServerConfig的buildIfAbsent方法,创建指定类型的Server:

1.      public synchronized Server buildIfAbsent(){
2.          if (server != null) {
3.              return server;
4.          }
5.          server= ServerFactory.getServer(this);
6.          return server;
7.      }

        通过ServerFactory类getServer方法初始化Server实例:

1.  public synchronized static ServergetServer(ServerConfig serverConfig) {
2.          try {
3.              Server server =SERVER_MAP.get(Integer.toString(serverConfig.getPort()));
4.              if (server == null) {
5.                  // 算下网卡和端口
6.                  resolveServerConfig(serverConfig);
7.   
8.                  ExtensionClass<Server>ext = ExtensionLoaderFactory.getExtensionLoader(Server.class)
9.                      .getExtensionClass(serverConfig.getProtocol());
10.                 if (ext == null) {
11.                     throwExceptionUtils.buildRuntime("server.protocol",serverConfig.getProtocol(),
12.                         "Unsupported protocol ofserver!");
13.                 }
14.                 server = ext.getExtInstance();
15.                 server.init(serverConfig);
16.                 SERVER_MAP.put(serverConfig.getPort()+ "", server);
17.             }
18.             return server;
19.         } catch (SofaRpcRuntimeException e) {
20.             throw e;
21.         } catch (Throwable e) {
22.             throw newSofaRpcRuntimeException(e.getMessage(), e);
23.         }
24.     }

        在getServer方法中,创建Server的主要处理过程如下:

        1)   从SERVER_MAP缓存中按照端口号获取指定端口的Server实现。如果有,则直接返回。否则,创建新的Server实例。

        2)   绑定Server的IP和端口;

        3)   利用RPC扩展机制获取Server接口扩展实现。此处别名为rest,所以获取到com.alipay.sofa.rpc.server.rest.RestServer类的实例;

        4)   调用RestServer的init方法,初始化server;

        5)   把server缓存到SERVER_MAP,key为端口号,value为server实例;

        在创建完Server实例以后,将处理器注册到server:

1.  public void registerProcessor(ProviderConfigproviderConfig, Invoker instance) {
2.          if (!isStarted()) {
3.              start();
4.          }
5.          // httpserver中注册此jaxrs服务
6.          if (LOGGER.isInfoEnabled()) {
7.              LOGGER.info("Register jaxrsservice to base url http://" + serverConfig.getHost() + ":"
8.                  + serverConfig.getPort() +serverConfig.getContextPath());
9.          }
10.         try {
11.             httpServer.getDeployment().getRegistry()
12.                 .addResourceFactory(newSofaResourceFactory(providerConfig), serverConfig.getContextPath());
13.  
14.             invokerCnt.incrementAndGet();
15.         } catch (Exception e) {
16.             LOGGER.error("Register jaxrsservice error", e);
17.         }
18.     }

        在registerProcessor方法中,首先判断server是否启动,如果没有启动,则启动server:

1.  public void start() {
2.          if (started) {
3.              return;
4.          }
5.          synchronized (this) {
6.              if (started) {
7.                  return;
8.              }
9.              // 绑定到端口
10.             try {
11.                 httpServer = buildServer();
12.                 httpServer.start();
13.                 if (LOGGER.isInfoEnabled()) {
14.                     LOGGER.info("Start thehttp rest server at port {}", serverConfig.getPort());
15.                 }
16.             } catch (Exception e) {
17.                 throw new SofaRpcRuntimeException(
18.                     "Failed to start jettyserver at port " + serverConfig.getPort() + ", cause: " +e.getMessage(), e);
19.             }
20.             started = true;
21.         }
22.     }

        Server启动的主要过程如下:

        1)  判断server是否启动

        如果没有启动,则同步代码块中启动server。在同步代码块开始部分,再次判断server是否启动,主要是避免在获取该Server的对象锁过程中,其它线程启动该Server。如果没有启动,则继续下面处理逻辑,启动Server。

        2)  创建Server实例

        此处是rest类型绑定,所以采用com.alipay.sofa.rpc.server.rest.SofaNettyJaxrsServer作为服务器。SofaNettyJaxrsServer参考NettyJaxrsServer实现(来自org.jboss.resteasy.plugins.server.netty.NettyJaxrsServer),增加了自定义功能,区别搜索CHANGE。在此不再详述。从名字可以看出,SofaNettyJaxrsServer采用Netty4作为网络通讯层,底层采用NIO,保证了网络通讯性能。

        设置Server实例,包括Worker线程数(此处boss和work采用同一个NioEventLoopGroup,所以是boss与worker线程总数)、业务线程池最大线程数,最大请求报文大小、主机名称、端口号、keepAlive、是否为Daemon线程、是否开启Telnet测试等。

        获取Server实例的属性deployment(接口类型为ResteasyDeployment),此处为com.alipay.sofa.rpc.server.rest.SofaResteasyDeployment。

        调用SofaResteasyDeployment类start方法,主要完成以下工作:

  • 为每个deployment设置其独有的ResteasyProviderFactory,以保证每个war包使用自己的provider集合。
  • 根据asyncJobServiceEnabled标志,选择创建异步请求分发器AsynchronousDispatcher或同步请求分发器SofaSynchronousDispatcher,此处创建同步请求分发器。
  • 设置同步请求分发器,主要包括上下文对象、providerFactory等;
  • 注册所有的provider;

        在providerFactory中注册provider,包含内置的和自定义的。

        最后返回创建好的Server实例。

        3)  启动Server

        调用Server实例的start方法,启动Server。

1.      public void start() {
2.          // CHANGE: 增加线程名字
3.          eventLoopGroup = newNioEventLoopGroup(ioWorkerCount, newNamedThreadFactory("SOFA-REST-IO-" + port, daemon));
4.          eventExecutor = newNioEventLoopGroup(executorThreadCount, newNamedThreadFactory("SOFA-REST-BIZ-" + port,
5.              daemon));
6.          // Configure the server.
7.          bootstrap.group(eventLoopGroup)
8.              .channel(NioServerSocketChannel.class)
9.              .childHandler(createChannelInitializer())
10.             .option(ChannelOption.SO_BACKLOG,backlog)
11.             .childOption(ChannelOption.SO_KEEPALIVE,keepAlive); // CHANGE:
12.  
13.         for (Map.Entry<ChannelOption,Object> entry : channelOptions.entrySet()) {
14.             bootstrap.option(entry.getKey(),entry.getValue());
15.         }
16.  
17.         for (Map.Entry<ChannelOption, Object>entry : childChannelOptions.entrySet()) {
18.             bootstrap.childOption(entry.getKey(),entry.getValue());
19.         }
20.  
21.         final InetSocketAddress socketAddress;
22.         if (null == hostname ||hostname.isEmpty()) {
23.             socketAddress = newInetSocketAddress(port);
24.         } else {
25.             socketAddress = newInetSocketAddress(hostname, port);
26.         }
27.  
28.         bootstrap.bind(socketAddress).syncUninterruptibly();
29.     }

        看到这里,熟悉Netty4的同学们都明白了吧。此处就是设置ServerBootstrap实例bootstrap的相关属性,然后调用bind方法开始监控指定的端口。

        Server启动以后,在httpserver中注册此jaxrs服务。

1.  httpServer.getDeployment().getRegistry()
2.                  .addResourceFactory(new SofaResourceFactory(providerConfig), serverConfig.getContextPath())

        判断autoStart是否为true。True表示自动启动Server。否则,不启动Server。此处为false,不自动启动Server。由于在把处理器注册到server时,已经启动了Server,所以此时Server已经启动。

        至此,Server启动成功,服务请求路径设置完成,准备接受客户端发起的restful类型的服务请求。

        再返回看看Rest服务发布的doExport方法:

1.  private void doExport() {
2.          ……
3.   
4.          try {
5.              // 构造请求调用器
6.              ……
7.              // 初始化注册中心
8.              ……
9.              // 将处理器注册到server
10.             List<ServerConfig>serverConfigs = providerConfig.getServer();
11.             for (ServerConfig serverConfig :serverConfigs) {
12.                 try {
13.                     Server server =serverConfig.buildIfAbsent();
14.                     // 注册序列化接口
15.                     server.registerProcessor(providerConfig,providerProxyInvoker);
16.                     if(serverConfig.isAutoStart()) {
17.                         server.start();
18.                     }
19.                 } catch (SofaRpcRuntimeException e) {
20.                     throw e;
21.                 } catch (Exception e) {
22.                    ……
23.                 }
24.             }
25.  
26.             // 注册到注册中心
27.             providerConfig.setConfigListener(newProviderAttributeListener());
28.             register();
29.         } catch (Exception e) {
30.             cnt.decrementAndGet();
31.             if (e instanceofSofaRpcRuntimeException) {
32.                 throw (SofaRpcRuntimeException)e;
33.             } else {
34.                 throw new SofaRpcRuntimeException("Buildprovider proxy error!", e);
35.             }
36.         }
37.         // 记录一些缓存数据
38.         RpcRuntimeContext.cacheProviderConfig(this);
39.         exported = true;
40.     }

        当服务配置的所有Server启动成功以后,设置服务提供者配置属性监听器ProviderAttributeListener,监听属性值变化。

        最后,在所有配置的注册中心中注册服务提供者。

        到现在为止,按照某种服务类型(如:restful风格服务)成功发布了指定的服务。

猜你喜欢

转载自blog.csdn.net/beyondself_77/article/details/80862415