Umbrella issue: #2846
目前我们在 Sentinel2.0 中分别抽象了InstanceManager、RouterFilter 以及 LoadBalancer 三个对象,并通过 ClusterManager 将它们管理起来。其中 InstanceManager 将地址列表按需进行存储与管理,RouterFilter做为流量路由能力实现的主体,LoadBalancer做为负载均衡能力实现的主体,并且尝试与Apache Dubbo的路由模型进行对接。
我们只需在 Dubbo 的 Router 中持有 ClusterManager 对象即可具备完整的路由能力。
Dubbo 在收到注册中心同步过来的 Provider URL 之后会生成对应的 Invoker ,Invoker 列表我们可以理解为就是可以调用的Provider节点列表的抽象。流量路由则是需要将传入的 Invoker 列表按照路由规则进行路由筛选,筛选出符合路由规则的服务提供者,即符合路由规则的 Invoker 列表。我们如何可以通过 Sentinel2.0 的抽象来实现流量路由的能力呢?当地址通知下来后,我们需要通过instanceManager#storeInstances将地址列表进行缓存。
@Override
public void notify(BitList<Invoker<T>> invokers) {
super.notify(invokers);
instanceManager.storeInstances(invokersToInstances(invokers));
}
在流量路由处,我们则调用clusterManager#route实现地址路由。
@Override
protected BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> routerSnapshotNodeHolder, Holder<String> messageHolder) throws RpcException {
TrafficContext trafficContext = getTrafficContext(invocation);
List<Instance> instances = clusterManager.route(trafficContext);
return instancesToInvokers(instances);
}
其中ClusterManager会将路由执行的逻辑交给RouterFiler.route进行执行。
public List<Instance> route(TrafficContext context) {
List<Instance> instances = instanceManager.getInstances();
for (RouterFilter routerFilter : routerFilterList) {
instances = routerFilter.filter(instances, context);
}
return instances;
}
每个 RouterFilter 服务路由都可以包含一条路由规则,路由规则决定了服务消费者的调用目标,即规定了服务消费者可调用哪些服务提供者;一次微服务调用的地址列表可以由多个 RouterFilter 服务路由共同影响,比如我们希望当前的 Consumer 流量访问到在同时符合灰度发布以及同可用区优先调用路由规则的节点上。我们可以按照需求增加路由链中的 RouterFilter,并且路由链的 Route 方法是循环调用每个 RouterFilter 的 Route 方法。并且上一个 Router 的输出 Invoker 列表会做为下一个 Router 的输入。
Sentinel ClusterManager 内置了 OpenSergo 数据源规则拉取模块,通过 OpenSergoDataSourceGroup 订阅 OpenSergo TrafficRouter 路由 规则。
1条答案
按热度按时间qyyhg6bp1#
Router逻辑前后的Instance对象实时转换,有优化的价值。