HSF 支持用户使用 Groovy 脚本配置服务的路由规则。 路由规则的配置方式,请参见 Routing Rule Wiki,在完成路由规则的配置后,您可能会发现路由规则没生效,这些没生效一般就是指调用并没有被路由到预期的机器上,然而这些没生效有可能是其他因素引起的,例如路由规则没写对、路由规则里的 IP 没有提供服务等。 这里,就来介绍下如何排查路由规则没有生效,共包含以下几步: 1. 客户端是否为本地调用、泛化调用 如果客户端通过本地调用、泛化调用的方式消费服务的话,那么是不会使用路由规则逻辑的,自然也就出现了路由规则不生效这种表象。 本地调用:指的是一个进程即是一个服务的发布者,又是这个服务的消费者,这个时候 HSF 默认优先走本地调用,即进程内的 Java 调用,而非 RPC 调用。这种情况,是不走路由规则的逻辑的。 泛化调用:指的是不依赖服务的二方包,直接通过 GenericService 通过服务描述进行消费的场景,这个时候 HSF 由于没有服务的 Class,无法执行路由规则里调用业务类的逻辑,因此也不走路由规则的逻辑。 HSFOPS 上的服务测试功能走的是泛化调用,因此也不会生效路由规则。 2. 客户端是否收到路由规则 HSF 的路由规则存放在 Diamond 上,在客户端启动时,会从 Diamond 上拉取服务对应的路由规则。 在 hsf.log(一般的路径是 HSF 2.2:${user.home}/logs/hsf/hsf-config.log 或 HSF 2.1:${user.home}/logs/hsf/hsf.log)中搜索服务名,如果正确收到路由规则,会看到类似如下的日志:
01 2015-10-09 13:20:06.402 WARN [com.taobao.diamond.client.Worker.default:t.hsf] [] [] [] [Metadata Component] Received rule for service [com.alibaba.dt.op.authclient.api.ResourceAPI:1.0.0.daily]: Groovy_v200907@package hqm.test.groovy public class RoutingRule{ Map<String, List > routingRuleMap(){ return [ "G1":["100.69.161.201:*"] ] }
String interfaceRoutingRule(){
return "G1";
}
}
如果没有收到路由规则,请检查: 路由规则的命名是否与服务名对应,具体请参见 Routing Rule Wiki。 路由规则配置在 diamond 上的环境和客户端所在的环境是否一致。 3. 路由规则是否正确解析 在 hsf.log 中搜索服务名,如果 HSF 的路由规则解析正确,会看到类似如下的日志:
01 2015-10-09 13:20:06.761 INFO [com.taobao.diamond.client.Worker.default:t.hsf] [] [] [] Parse route rule successed, RouteRule:com.taobao.hsf.route.service.RouteRule@4441ec5a{ keyedRules={G1=[100.69.161.201:*]}, interfaceRule=G1, methodRule={}, argsRule={} }
如果 HSF 的路由规则解析失败,会看到相关的失败信息,请对照日志和 Routing Rule Wiki 检查您的路由规则。 4. 路由规则的内容是否正确 路由规则收到了、也解析对了,如果路由规则执行的效果还与预期不同,请依次检查以下内容: 路由的目标机器是否真的提供了该服务 请在对应环境的 HSF 服务治理平台上查询服务,看路由的目标 IP 是否都在 Providers 列表中。 在老版本的 HSF 中,如果路由规则指定的 IP 没有提供服务,会报地址找不到错误 在新版本的 HSF 中(2.1.0.7 开始),如果路由规则指定的 IP 没提供服务,会提示开启空保护,那么此时路由规则就不再生效,HSF 会从 ConfigServer 存放的 Provider 地址列表中为客户端选取一个可用 IP 进行调用。在使用方法路由时,如果碰到算出的地址为空,这种情况下,在 hsf.log 中搜索服务名,会看到类似如下的日志。其中空保护开启的标志为倒数第二行的 EmptyProtection triggered [true]:
01 2015-10-09 13:20:06.761 WARN [HSF-AddressAndRule-2-thread-1:t.hsf] [] [] [] [Address Component] isEmptyProtection: true 01 2015-10-09 13:20:06.761 WARN [HSF-AddressAndRule-1-thread-1:t.hsf] [] [] [] [Address Component] isEmptyProtection: true 01 2015-10-09 13:20:06.761 WARN [HSF-AddressAndRule-2-thread-1:t.hsf] [] [] [] [Address Component] newAllAvailableAddresses is emtpy for service : com.alibaba.dt.op.authclient.api.ResourceAPI:1.0.0.daily 01 2015-10-09 13:20:06.761 INFO [HSF-AddressAndRule-2-thread-1:t.hsf] [] [] [] [AddressBucket-com.alibaba.dt.op.authclient.api.ResourceAPI:1.0.0.daily] Refresh: all amount [0], available amount [0], local preferred switch [off].Unit=UNIT 01 2015-10-09 13:20:06.761 INFO [HSF-AddressAndRule-1-thread-1:t.hsf] [] [] [] [Address Component] route result com.alibaba.dt.op.authclient.api.ResourceAPI:1.0.0.daily, addresses remain[1], EmptyProtection triggered [true] 01 2015-10-09 13:20:06.762 INFO [HSF-AddressAndRule-1-thread-1:t.hsf] [] [] [] [AddressBucket-com.alibaba.dt.op.authclient.api.ResourceAPI:1.0.0.daily] Refresh: all amount [1], available amount [1], local preferred switch [off].
路由规则是否正确 仔细检查您的接口路由、方法路由、参数路由,是否真的写对了。 地址计算优先级 如果开启了同机房规则,那么同机房的地址优先于路由规则的地址,路由规则的地址在同机房规则结果的地址集合里再计算。 路由规则分为接口级 > 方法级 > 参数级,若某一级的路由规则不存在,即其返回的 key 为 null,或在 routingRuleMap 中找不到相应值,则认为这一级对路由地址不做限制,地址取上一级的全部地址。 总体的计算过程如下: 接口级路由规则(正则式)最终地址列表会和同机房规则结果地址列表作交集 方法级路由规则(正则式)最终地址列表会和接口级地址列表作交集 参数级路由规则(正则式)最终地址列表会和方法级地址列表作交集 5. 路由规则是否真的被调用 如果按照以上内容排查后,都没有问题,请再确认路由规则指定的服务/方法是否真的被调用了? 如果相应的方法没有被调用,则在目标机器上肯定也搜不到调用日志。 可以通过 System.out.println() 在路由规则中打印内容来确认,同时注意返回的内容必须为一个闭包。例如:
ovy_v200907@package hqm.test.groovy public class RoutingRule { Map<String, List > routingRuleMap() { return [ "BSeller_address_filter_Key":["10.177.75.54:*"], "ASeller_address_filter_Key":["10.97.94.33:*"] ] }
Object argsRoutingRule(String methodName, String[] paramTypeStrs) {
if (methodName.startsWith("checkUrlPermission")) {
System.out.println("Match the checkUrlPermission method.");
return {
Object[] args ->
if(args[1] % 2 == 1 ) {
System.out.println("Route to BSeller_address_filter_Key");
return "BSeller_address_filter_Key.";
} else {
System.out.println("Route to ASeller_address_filter_Key");
return "ASeller_address_filter_Key.";
}
}
}
}
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。