Soul API网关源码解析05

目标

  • 基于Sofa-Rpc协议的Demo演示

    • 引入网关(bootstarp)对sofa支持的插件
    • 使用XML方式引入实际业务接口
    • Publish service on server
    • 被代理业务增加yml配置
    • 配置接口注册admin地址信息
    • 启动真实业务服务
  • soul-spring-boot-starter-client-sofa注入解析

    • sofaConfig读取soul.sofa.xx配置信息
    • SofaServiceBeanPostProcessor类注入Bean
    • BeanPostProcessor执行
    • admin页面展示已经注册的接口
  • 演示和总结

  • Sofa-Rpc介绍

基于Sofa-Rpc协议的Demo演示

引入网关(bootstarp)对sofa支持的插件

  
com.alipay.sofa 
sofa-rpc-all 
5.7.6 
  
 
org.apache.curator 
curator-client 
4.0.1 
 
 
org.apache.curator 
curator-framework
 4.0.1 

  
org.apache.curator 
curator-recipes 
4.0.1 
 
 
org.dromara
 soul-spring-boot-starter-plugin-sofa
 2.2.1 

其中主要的依赖有sofa-rpc-all和封装的soul-spring-boot-starter-plugin-sofa

使用xml方式引入业务接口

    @ImportResource({ "classpath*:invoke-server-example.xml"})

使用注解@ImportResource() 自动注入

Publish service on server

Configure the followings in the xml file. When the Spring context is refreshed, SOFABoot registers the service implementation on the server, communicates with the client by bolt protocol, and publishes metadata such as address to registry center (local file is used as registry center by default).

上文从Sofa-rpc 官网Getting started 摘录,当被代理服务Bean注入完Spring Context刷新,SOFABoot 就开始将需要被代理的接口注入到Sofa server

被代理业务增加yml配置

  • 本实例sofa采用zookeeper作为注册中心,所以本地要启动一个zk,这里使用了之前dubbo实例中的zk,同时配置sofa配置如下:
com:  
   alipay: 
       sofa: 
          rpc: registry-address: zookeeper://127.0.0.1:2181
          bolt-port: 8888

Bolt protocol port 是8888

配置接口注册admin地址信息

soul:  
  sofa: 
    adminUrl: http://localhost:9095 
    contextPath: /sofa 
    appName: sofa

启动真实业务服务

image.png

说明Sofa客户端启动成功

image.png

从服务启动日志中可以看出 Sofa 与 soul-sofa-client 各个服务的配置先后顺序

Soul-Spring-boot-starter-client-sofa 注入解析

sofaConfig 读取soul.sofa.xx 配置信息

@Bean
@ConfigurationProperties(prefix = "soul.sofa")
public SofaConfig sofaConfig() {
    return new SofaConfig();
}

SofaServiceBeanPostProcessor 类注入Bean

public SofaServiceBeanPostProcessor(final SofaConfig sofaConfig) {
    String contextPath = sofaConfig.getContextPath();
    String adminUrl = sofaConfig.getAdminUrl();
    if (contextPath == null || "".equals(contextPath)
            || adminUrl == null || "".equals(adminUrl)) {
        throw new RuntimeException("sofa client must config the contextPath, adminUrl");
    }
    this.sofaConfig = sofaConfig;
    url = sofaConfig.getAdminUrl() + "/soul-client/sofa-register";
    executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
}

获取注册admin的sofa相关参数和创建执行注册的线程池

BeanPostProcessor执行

@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
    if (bean instanceof ServiceFactoryBean) {
        executorService.execute(() -> handler((ServiceFactoryBean) bean));
    }
    return bean;
}
private void handler(final ServiceFactoryBean serviceBean) {
    Class clazz;
    try {
        clazz = ((Service) Objects.requireNonNull(serviceBean.getObject())).getTarget().getClass();
    } catch (Exception e) {
        log.error("failed to get sofa target class");
        return;
    }
    if (ClassUtils.isCglibProxyClass(clazz)) {
        String superClassName = clazz.getGenericSuperclass().getTypeName();
        try {
            clazz = Class.forName(superClassName);
        } catch (ClassNotFoundException e) {
            log.error(String.format("class not found: %s", superClassName));
            return;
        }
    }
    final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz);
    for (Method method : methods) {
        SoulSofaClient soulSofaClient = method.getAnnotation(SoulSofaClient.class);
        if (Objects.nonNull(soulSofaClient)) {
            RegisterUtils.doRegister(buildJsonParams(serviceBean, soulSofaClient, method), url, RpcTypeEnum.SOFA);
        }
    }
}

主要是使用@SoulSofaClient注解配合反射拿到需要代理的接口

admin 页面展示已经注册的接口

image.png

到这里前期初始化工作完成,下面看下调用演示

演示与总结

image.png

前面几篇最后都没有总结,今天到此我们已经演示了SpringMvc/SpringCloud,Dubbo,Sofa不同协议的代理方式,总结一下,soul的设计思路:

  • 不同协议封装成独立的客户端包,至于使用的协议规范那一套全部在客户端中封装了,使用者只需要根据对应的附加配置信息即可。
  • 为每个客户端创建一个spring boot starter,使用了SpringBoot 自动化配置的原理,读取 META-INF/spring.factories 中的自动化配置类进行向admin注册
  • 每个协议的客户端基本实现一样,通过BeanPostProcessor和ApplicationListener加上自定义注解从而达到接口的注册

Sofa-Rpc介绍

SOFARPC 是蚂蚁金服开源的一款基于 Java 实现的 RPC 服务框架,为应用之间提供远程服务调用能力,具有高可伸缩性,高容错性,目前蚂蚁金服所有的业务的相互间的 RPC 调用都是采用 SOFARPC。SOFARPC 为用户提供了负载均衡,流量转发,链路追踪,链路数据透传,故障剔除等功能。

SOFARPC 还支持不同的协议,目前包括 bolt,RESTful,dubbo,H2C 协议进行通信。其中 bolt 是蚂蚁金融服务集团开放的基于 Netty 开发的网络通信框架。

基本原理

image.png

当一个 SOFARPC 的应用启动的时候,如果发现当前应用需要发布 RPC 服务的话,那么 SOFARPC 会将这些服务注册到服务注册中心上。如图中 Service 指向 Registry。

  1. 当引用这个服务的 SOFARPC 应用启动时,会从服务注册中心订阅到相应服务的元数据信息。服务注册中心收到订阅请求后,会将发布方的元数据列表实时推送给服务引用方。如图中 Registry 指向 Reference。
  2. 当服务引用方拿到地址以后,就可以从中选取地址发起调用了。如图中 Reference 指向 Service。

后面研究单独插件时候好好研究下他的源码

你可能感兴趣的:(Soul API网关源码解析05)