Soul网关源码阅读04-体验sofa代理

结合sofa插件,发起http请求soul网关,体验sofa代理
一、启动服务:

soul-examples-sofa 启动报如下错误,同时会影响网关测的服务调用,导致服务无法调通。

  • 解决方式:这里的 bolt-port: 8888 可能被占用,修改一下这个端口
# soul/soul-examples/soul-examples-sofa/src/main/resources/application.yml
com:
  alipay:
    sofa:
      rpc:
        registry-address: zookeeper://127.0.0.1:2181
        bolt-port: 8888  # bolt 协议端口
  • 错误日志:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-01-18 14:47:27.139 ERROR 11863 --- [           main] o.s.boot.SpringApplication               : Application run failed
com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException: Failed to start bolt server, see more detail from bolt log.
    at com.alipay.sofa.rpc.server.bolt.BoltServer.start(BoltServer.java:121) ~[sofa-rpc-all-5.5.7.jar:5.5.7]
    at com.alipay.sofa.rpc.boot.container.ServerConfigContainer.startServers(ServerConfigContainer.java:87) ~[rpc-sofa-boot-core-6.0.4.jar:6.0.4]
    at com.alipay.sofa.rpc.boot.context.SofaBootRpcStartListener.onApplicationEvent(SofaBootRpcStartListener.java:73) ~[rpc-sofa-boot-core-6.0.4.jar:6.0.4]
    at com.alipay.sofa.rpc.boot.context.SofaBootRpcStartListener.onApplicationEvent(SofaBootRpcStartListener.java:41) ~[rpc-sofa-boot-core-6.0.4.jar:6.0.4]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    ......
二、通过sofa来看一下soul网关元数据同步原理

soul-bootstrap 加入了 soul-spring-boot-starter-plugin-sofa 依赖,来看一下这部分源码

1、 soul-spring-boot-starter-plugin-sofa

soul-spring-boot-starter-plugin-sofa/src/main/resources/META-INF/spring.factories

// 自动注入 SofaPluginConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.soul.spring.boot.starter.plugin.sofa.SofaPluginConfiguration

SofaPluginConfiguration 向容器中注入 MetaDataSubscriber bean对象

/**
 * Sofa meta data subscriber meta data subscriber.
 *
 * @return the meta data subscriber
 */
@Bean
public MetaDataSubscriber sofaMetaDataSubscriber() {
    return new SofaMetaDataSubscriber();
}

2、MetaDataSubscriber 负责订阅 soul-admin 发布的元数据更新

将订阅的消息更新到 META_DATA,这里看到的只是订阅的具体实现,MetaDataSubscriber 又是如何被调用的?

/**
 * The sofa metadata subscribe.
 * @author tydhot
 */
public class SofaMetaDataSubscriber implements MetaDataSubscriber {
    private static final ConcurrentMap<String, MetaData> META_DATA = Maps.newConcurrentMap();
    @Override
    public void onSubscribe(final MetaData metaData) {
        if (RpcTypeEnum.SOFA.getName().equals(metaData.getRpcType())) {
            MetaData exist = META_DATA.get(metaData.getPath());
            if (Objects.isNull(exist) || Objects.isNull(ApplicationConfigCache.getInstance().get(exist.getPath()).refer())) {
                // The first initialization
                ApplicationConfigCache.getInstance().initRef(metaData);
            } else {
                if (!exist.getServiceName().equals(metaData.getServiceName()) || !exist.getRpcExt().equals(metaData.getRpcExt())) {
                    // update
                    ApplicationConfigCache.getInstance().build(metaData);
                }
            }
            META_DATA.put(metaData.getPath(), metaData);
        }
    }
}

3、在 SofaMetaDataSubscriber -> onSubscribe 打上断点,可以看到方法调用栈,中的

SoulWebsocketClient-> onMessage 方法
在这里插入图片描述
4、SoulWebsocketClient 类属于 soul-sync-data-websocket 模块
SoulWebsocketClient 继承了 WebSocketClient 负责监听soul-admin WebSocket 发布的元数据更新通知

/**
 * The type Soul websocket client.
 */
@Slf4j
public final class SoulWebsocketClient extends WebSocketClient {
    ......
    
    @Override
    public void onMessage(final String result) {
        handleResult(result);
    }
    
    @SuppressWarnings("ALL")
    private void handleResult(final String result) {
        WebsocketData websocketData = GsonUtils.getInstance().fromJson(result, WebsocketData.class);
        ConfigGroupEnum groupEnum = ConfigGroupEnum.acquireByName(websocketData.getGroupType());
        String eventType = websocketData.getEventType();
        String json = GsonUtils.getInstance().toJson(websocketData.getData());
        websocketDataHandler.executor(groupEnum, json, eventType);
    }
}

5、WebsocketDataHandler 中实例化并加载了所有的订阅者,其中包含 MetaDataSubscriber

/**
 * The type Websocket cache handler.
 * @author xiaoyu(Myth)
 */
public class WebsocketDataHandler {
    private static final EnumMap<ConfigGroupEnum, DataHandler> ENUM_MAP = new EnumMap<>(ConfigGroupEnum.class);
    /**
     * Instantiates a new Websocket data handler.
     * @param pluginDataSubscriber the plugin data subscriber
     * @param metaDataSubscribers  the meta data subscribers
     * @param authDataSubscribers  the auth data subscribers
     */
    public WebsocketDataHandler(final PluginDataSubscriber pluginDataSubscriber,
                                final List<MetaDataSubscriber> metaDataSubscribers,
                                final List<AuthDataSubscriber> authDataSubscribers) {
        ENUM_MAP.put(ConfigGroupEnum.PLUGIN, new PluginDataHandler(pluginDataSubscriber));
        ENUM_MAP.put(ConfigGroupEnum.SELECTOR, new SelectorDataHandler(pluginDataSubscriber));
        ENUM_MAP.put(ConfigGroupEnum.RULE, new RuleDataHandler(pluginDataSubscriber));
        ENUM_MAP.put(ConfigGroupEnum.APP_AUTH, new AuthDataHandler(authDataSubscribers));
        ENUM_MAP.put(ConfigGroupEnum.META_DATA, new MetaDataHandler(metaDataSubscribers));
    }

    /**
     * Executor.
     * @param type      the type
     * @param json      the json
     * @param eventType the event type
     */
    public void executor(final ConfigGroupEnum type, final String json, final String eventType) {
        ENUM_MAP.get(type).handle(json, eventType);
    }
}

6、MetaDataHandler 中通过遍历的方式通知所有的订阅者更新元数据,至此我们看清楚了 sofa元数据同步的整个流程

public class MetaDataHandler extends AbstractDataHandler<MetaData> {
    private final List<MetaDataSubscriber> metaDataSubscribers;
    @Override
    public List<MetaData> convert(final String json) {
        return GsonUtils.getInstance().fromList(json, MetaData.class);
    }
    @Override
    protected void doRefresh(final List<MetaData> dataList) {
        metaDataSubscribers.forEach(MetaDataSubscriber::refresh);
        dataList.forEach(metaData -> metaDataSubscribers.forEach(metaDataSubscriber -> metaDataSubscriber.onSubscribe(metaData)));
    }
    @Override
    protected void doUpdate(final List<MetaData> dataList) {
        dataList.forEach(metaData -> metaDataSubscribers.forEach(metaDataSubscriber -> metaDataSubscriber.onSubscribe(metaData)));
    }
    @Override
    protected void doDelete(final List<MetaData> dataList) {
        dataList.forEach(metaData -> metaDataSubscribers.forEach(metaDataSubscriber -> metaDataSubscriber.unSubscribe(metaData)));
    }
}

7、sofa元数据同步原理思维导图
在这里插入图片描述

三、总结:

通过sofa元数据加载的过程,元数据同步是通过websocket来实现,这只是soul网关元数据同步的一种,其他还包括http,zookeeper。后续对其他元数据同步方式进行学习。

Soul网关元数据同步原理介绍-官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值