sofa-rpc源码分析 2-服务启动

一、服务启动(dubbo协议)

ApplicationConfig applicationConfig = new ApplicationConfig().setAppName("dubbo-server");//应用信息
        //声明dubbo协议,因为sofa-rpc是支持一个接口的多协议发布
        ServerConfig serverConfig = new ServerConfig()
            .setProtocol("dubbo")
            .setHost("127.0.0.1")
            .setPort(20080)
            .setSerialization("hessian2")//序列化协议
            .setDaemon(false);
        //发布服务,采用的是构造器模式,多次setServer就行
        ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
            .setInterfaceId(HelloService.class.getName())
            .setBootstrap("dubbo")
            .setApplication(applicationConfig)
            .setRef(new HelloServiceImpl())
            .setUniqueId("xxx")//UniqueId为了同一个接口能在发布为多个bean
            .setServer(serverConfig)
            .setRegister(false);

        ProviderConfig<EchoService> providerConfig2 = new ProviderConfig<EchoService>()
            .setInterfaceId(EchoService.class.getName())
            .setRef(new EchoServiceImpl())
            .setApplication(applicationConfig)
            .setBootstrap("dubbo")
            .setUniqueId("xxx")
            .setServer(serverConfig)
            .setRegister(false);

        //真正发布服务的入口,下面也是我们即将分析的代码
        providerConfig.export();
        providerConfig2.export();

        LOGGER.warn("started at pid {}", RpcRuntimeContext.PID);

        synchronized (DubboServerMain.class) {
            while (true) {
                try {
                    DubboServerMain.class.wait();
                } catch (InterruptedException e) {

                }
            }
        }
    }

二、源码分析

1.providerBootstrap = Bootstraps.from(this);//初始化ProviderBootstrap对象,ProviderBootstrap对象包装了各类bootstrap的发布和取消发布
    1.1 String bootstrap = providerConfig.getBootstrap();
        if (StringUtils.isEmpty(bootstrap)) {//如果没设置bootstrap则使用默认的bootstrap
            // Use default provider bootstrap
            bootstrap = RpcConfigs.getStringValue(RpcOptions.DEFAULT_PROVIDER_BOOTSTRAP);
            providerConfig.setBootstrap(bootstrap);
        }
        //通过SPI Extension反射获取providerBootstrap对象
        ProviderBootstrap providerBootstrap = ExtensionLoaderFactory.getExtensionLoader(ProviderBootstrap.class)
            .getExtension(bootstrap, new Class[] { ProviderConfig.class }, new Object[] { providerConfig });
2.providerBootstrap.export();//目前sofa-rpc提供了两种bootstrap,DefaultProviderBootstrap和DubboProviderBootstrap
    2.1 DubboProviderBootstrap
        //将providerBootstrap转换为dubbo 原生的ServiceConfig
        2.1.1 covert(providerConfig, serviceConfig);
            2.1.1.1copyApplication(providerConfig, serviceConfig);//复制应用信息
            //复制服务提供者需要的注册中心信息,提供了本地缓存映射,提升复制性能
            2.1.1.2DubboConvertor.copyRegistries(providerConfig, serviceConfig);
            //复制ProtocolConfig协议相关的信息,包括序列化器、IO线程大小、业务线程大小、线程池、报文长度限制
            2.1.1.3copyServers(providerConfig, serviceConfig);
            //复制ServiceConfig相关的服务提供者信息,包括相关的接口、bean引用等,但是代码里强制set了dubbo的服务版本是1.0,如果你想用sofa-rpc去发布dubbo 2.0协议的服务,发布出来的永远是1.0的服务,因为现在sofa-rpc并没提供服务版本的概念
            [issues](https://github.com/alipay/sofa-rpc/issues/587)
            2.1.1.4copyProvider(providerConfig, serviceConfig);
            //复制MethodConfig
            2.1.1.5copyMethods(providerConfig, serviceConfig);
        //通过duubo 的ServiceConfig.export方法将服务发布
        2.1.2 serviceConfig.export();
    //sofa-rpc还提供了默认的发布协议
    2.2 DefaultProviderBootstrap
        //校验参数,组装方法发布的黑白名单
        2.2.1checkParameters()
        // 构造请求调用器,主要是初始化服务端的Filter过滤器,包含了系统自定义的服务端的过滤器和用户自定义的过滤器
        2.2.2providerProxyInvoker = new ProviderProxyInvoker(providerConfig);
              //初始化过滤器链FilterChain
              2.2.2.1 this.filterChain = FilterChain.buildProviderChain(providerConfig,
            new ProviderInvoker(providerConfig))
                //获取服务端需要加载的过滤器,providerConfig里包含了用户通过别名和Filter示例自定义的过滤器,PROVIDER_AUTO_ACTIVES是static加载的系统默认Filter过滤器,相关的过滤器我们在后续Filter过滤器原理分析
                2.2.2.1.1selectActualFilters(providerConfig, PROVIDER_AUTO_ACTIVES)
                //判断优先加载用户自定义的过滤器,并且只加载能加载的过滤器(这个判定在各子类定义)
                2.2.2.1.2 new FilterChain(selectActualFilters(providerConfig, PROVIDER_AUTO_ACTIVES), lastFilter, providerConfig)
      //根据注册中心配置获取注册中心对象
      2.2.3 RegistryFactory.getRegistry(registryConfig)
      //根据服务配置已经用户选择发布的服务类型初始化server对象,目前sofa-rpc仅支持三种服务端,http、sofa-bolt、rest(netty-resteasy)
      2.2.4 Server server = serverConfig.buildIfAbsent();
      //注册请求调用器(这里我们分析rest方式)
      2.2.5 server.registerProcessor(providerConfig, providerProxyInvoker)
        //初始化发布的服务bean,并将上面初始化好的ProviderProxyInvoker对象通过字节增加jdk/javassist将Invoker对象动态注入到bean里,ProviderProxyInvoker包含和服务发布后请求进入的filterchain
        2.2.5.1 Object obj = ProxyFactory.buildProxy(providerConfig.getProxy(), providerConfig.getProxyClass(), instance);
        //通过netty resteasy进行rest服务发布
        2.2.5.2 httpServer.getDeployment().getRegistry().addResourceFactory(new SofaResourceFactory(providerConfig, obj), serverConfig.getContextPath());
          //初始化SofaResteasyDeployment,展示简单的重写了ResteasyDeployment的start方法,SynchronousDispatcher里重写同步分发器的Registry
          2.2.5.2.1 SynchronousDispatcher dis = new SofaSynchronousDispatcher(providerFactory)
          //往资源发布工厂添加一个自定义的节点
          2.2.5.2.2 SofaResourceMethodRegistry.addResourceFactory(ref, basePath)
      //生成rest接口服务,这个sofa-rpc参照了jboss 的NettyJaxrsServer ,重写了其start方法,主要指支持了守护线程、支持epoll、支持线程池
      2.2.6 server.start()
      //监听配置文件的变化,重新加载providerConfig对象的配置属性,并重新发布rest服务
      2.2.7 providerConfig.setConfigListener(new ProviderAttributeListener())
      //根据发布配置,将服务发布,目前支持Consul、Service Mesh、Nacos、Zookeeper、Local、Mock方式
      //注册服务,这里就是接入各类客户端的初始化和注册,不过多赘述
      2.2.8 register();
         2.2.8.1 registry.init();
         2.2.8.2 registry.start();
         2.2.8.3 registry.register(providerConfig);

三、总结

ProviderConfig:服务发布相关配置,维护了服务发布相关的基础配置信息和服务发布后的相关服务信息维护
ProviderBootstrap:服务发布的实操启动类,提供对ProviderConfig各类发布类型的export和unexport
Registry:服务发布的真正的接口,目前sofa-rpc支持ConsulRegistry、LocalRegistry、MeshRegistry(并非service mesh,只是HTTP方式)、NacosRegistry、ZookeeperRegistry、MockTestRegistry(MockTestSlowRegistry)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容