服务框架HSF分析之三Consumer启动和处理

本文详细介绍了HSF框架中Consumer端的启动流程,包括服务代理创建与服务订阅过程,重点阐述了如何通过动态代理返回HSFServiceProxy以及如何通过Diamond订阅路由规则和服务地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前两篇文章为大家带来了HSF容器启动和Porvider的分享。这篇来分析下consumer端的运行机制。

一. Consumer的启动

1. 服务代理

在HSFSpringConsumer的启动中会返回一个HSFServiceProxy的jdk动态代理,后续调用其实都是通过这个代理类来实现的。

Java代码 复制代码 收藏代码
  1. InvocationHandler handler = newHSFServiceProxy(metadata);
  2. Object proxyObj =Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {interfaceClass }, handler);
InvocationHandler handler = newHSFServiceProxy(metadata);
        Object proxyObj =Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {interfaceClass }, handler);

2. 服务订阅

通过metadataService的subscribe订阅服务的信息,主要是接口的所有地址,路由规则和机房流量规则

a. 路由规则

通过diamond订阅路由规则

Java代码 复制代码 收藏代码
  1. DiamondManager diamondManager = newDefaultDiamondManager(group, dataId, new ManagerListenerAdapter() {
  2. @Override
  3. public voidreceiveConfigInfo(String configInfo) {
  4. registerRule(serviceUniqueName, configInfo);
  5. }
  6. });
  7. .......
  8. registerRule(serviceUniqueName,configInfo);
DiamondManager diamondManager = newDefaultDiamondManager(group, dataId, new ManagerListenerAdapter() {
                @Override
                public voidreceiveConfigInfo(String configInfo) {
                   registerRule(serviceUniqueName, configInfo);
                }
            });
            .......
            registerRule(serviceUniqueName,configInfo);

当consumer端会有定时线程去diamond端获取单个服务的配置信息,默认周期15s,同时diamond使用了pushit进行实时通知,当有变更时会实时拿到变更信息,当有规则变更时都会刷新本地规则。

b. 路由规则注册

主要分2部分,路由规则(机器路由),机房流量规则(是否本地机房优先)

b.1 路由规则注册

b.1.1规则解析

代码:

Java代码 复制代码 收藏代码
  1. // 处理路由规则
  2. if (splitter.has(HSFConstants.HEADER_ROUTING_RULE)) {
  3. final String routingRule =splitter.get(HSFConstants.HEADER_ROUTING_RULE);
  4. addressService.setServiceRouteRule(serviceUniqueName, routingRule);
  5. }
// 处理路由规则
       if (splitter.has(HSFConstants.HEADER_ROUTING_RULE)) {
            final String routingRule =splitter.get(HSFConstants.HEADER_ROUTING_RULE);
           addressService.setServiceRouteRule(serviceUniqueName, routingRule);
        }

当在diamond里配置了路由规则时触发更新,规则内容类似于

Java代码 复制代码 收藏代码
  1. Groovy_v200907@package hqm.test.groovy
  2. public class RoutingRule{
  3. Map<String,List<String>> routingRuleMap(){
  4. return[
  5. "DETAIL":[
  6. "172.23.172.101:*",
  7. "172.24.165.63:*",
  8. "172.23.204.170:*",
  9. "172.23.204.185:*",
  10. ……
  11. ]
  12. ];
  13. }
  14. String interfaceRoutingRule(){
  15. return null;
  16. }
  17. String mathodRoutingRule(String methodName, String[] paramTypeStrs){
  18. return "DETAIL";
  19. }
  20. Object argsRoutingRule(String methodName, String[] paramTypeStrs){
  21. return null;
  22. }
  23. }
Groovy_v200907@package hqm.test.groovy
public class  RoutingRule{
 
  Map<String,List<String>> routingRuleMap(){
         return[
                        "DETAIL":[
"172.23.172.101:*",
"172.24.165.63:*",
"172.23.204.170:*",
"172.23.204.185:*",
……
]
                  ];
     }
 
 String interfaceRoutingRule(){
       return null;
   }
 String mathodRoutingRule(String methodName, String[] paramTypeStrs){
          return "DETAIL";
     }
 Object argsRoutingRule(String methodName, String[] paramTypeStrs){
       return null;
   }
 
}

在setServiceRouteRule中,hsf会调用parser来解析这些规则,上面那个规则将被GroovyRouteRuleParser解析成RouteRule实体,代码:

Java代码 复制代码 收藏代码
  1. RouteRule<String> rule = null;
  2. for (RouteRuleParser parser : this.ruleParsers) {
  3. ...
  4. rule =parser.parse(rawRouteRuleObj, allMethodSigs);
  5. ...
  6. }
RouteRule<String> rule = null;
       for (RouteRuleParser parser : this.ruleParsers) {
            ...
                rule =parser.parse(rawRouteRuleObj, allMethodSigs);
            ...
        }

具体parse过程:

1. 拿到Groovy的Classloader:GroovyClassLoader loader = newGroovyClassLoader(GroovyRouteRuleParser.class.getClassLoader());

2. 将规则加载成Class实例 c_groovy = loader.parseClass(groovyRule);

3. 反射生成实例 ruleObj = c_groovy.newInstance();

4. 反射调用routingRuleMap方法,拿到规则索引的Map,后续的类级,方法级规则等的处理都是基于这个规则索引的

5. 反射调用interfaceRoutingRule方法,拿到接口级别的规则名称

6. 反射调用mathodRoutingRule方法,拿到方法级别的规则名称

7. 反射调用argsRoutingRule方法,拿到参数级别的规则名称

8. 组装RouteRule实体对象,返回之

b.1.2 地址结果更新

规则实体解析之后,就需要对现有的地址进行更新了,这样就可以让配置在调用方起效。代码:

Java代码 复制代码 收藏代码
  1. RouteResultCache<String>addressCache = getRouteResultCache(serviceUniqueName);
  2. addressCache.setRouteRule(rule);
  3. addressCache.reset();  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值