High-Speed Service Framework (HSF) allows you to use Groovy scripts to configure service routing rules.

For more information about how to configure routing rules, see Routing Rule Wiki. After the routing rules are configured, you may find that the routing rules do not take effect. Such failures usually occur when the call is not routed to the expected instance. However, in this case, the failures may be caused by other factors, such as improper routing rules and failure to provide services to IP addresses in the routing rules.

The following describes how to troubleshoot the failure of the routing rule, which consists of the following steps:

1. Check whether the consumer uses a local call or generic call

2. Check whether the consumer receives the routing rule

3. Check whether the routing rule is correctly parsed

4. Check whether the routing rule is correct

5. Check whether the routing rule is actually called

1. Check whether the consumer uses a local call or generic call

If the consumer consumes services by using local calls or generic calls, the routing rule logic is not used, and naturally, the routing rule does not take effect.

  • In local call mode, a process is both the service provider and the service consumer. By default, HSF uses local calls, namely, Java calls in the process, instead of RPC calls. In this case, the routing rule logic is not used.
  • In generic call mode, services are consumed directly by calling GenericService to describe the service without depending on the second-party package of the service. In this case, HSF has no service class and cannot execute the service logic in the routing rule, and therefore the routing rule logic is not used.

The service test function on HSFOPS uses generic calls, and therefore the routing rules do not take effect.

2. Check whether the consumer receives the routing rule

HSF routing rules are stored in Diamond. When the consumer starts, the corresponding routing rules of the service are pulled from Diamond.

In hsf.log (the default path is ${user.home}/logs/hsf/hsf-config.log for HSF 2.2 or ${user.home}/logs/hsf/hsf.log for HSF 2.1), search for the service name. If the routing rule is received correctly, a log similar to the following exists:

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<String>> routingRuleMap(){
        return [
            "G1":["100.69.161.201:*"]
        ]
    }

    String interfaceRoutingRule(){
        return "G1";
    }
}
			

If no routing rule is received, check the following items:

  1. Check whether the routing rule name corresponds to the service name. For more information, see Routing Rule Wiki.
  2. Check whether the environment of the routing rule configured on Diamond is consistent with that of the consumer.

3. Check whether the routing rule is correctly parsed

In hsf.log, search for the service name. If the HSF routing rule is correctly parsed, a log similar to the following exists:

01 2015-10-09 13:20:06.761 INFO [com.taobao.diamond.client.Worker.default:t.hsf] [] [] [] Parse route rule succeeded, RouteRule:com.taobao.hsf.route.service.RouteRule@4441ec5a{
keyedRules={G1=[100.69.161.201:*]},
interfaceRule=G1,
methodRule={},
argsRule={}
}
			

If the HSF routing rule parsing fails, the error message appears. Check the routing rule by referring to the log and Routing Rule Wiki.

4. Check whether the routing rule is correct

If the routing rule has been received and parsed correctly, check the following items in sequence:

  1. Check whether the destination instance of the route actually provides this service.

    Query the service on the HSF service governance platform in the corresponding environment and check whether the destination IP addresses of the routes are in the providers list.

    • In an earlier version of HSF, if the IP address specified by the routing rule does not provide services, an error message is returned, indicating that the IP address cannot be found.
    • In HSF 2.1.0.7 or later, if the IP address specified by the routing rule does not provide services, the system prompts you to enable empty protection. In this case, the routing rule does not take effect, and HSF selects an available IP address for the consumer to call the service from the Providers list stored in Config Server. When a method-based route is used, if the calculated address is empty, search for the service name in hsf.log. A log similar to the following exists. The next to last line, EmptyProtection trigger [true], indicates that empty protection is enabled.

      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 empty 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].
      							
  2. Check whether the routing rule is correct.

    Check whether the interface route, method route, and parameter route are correct.

  3. Address calculation priority

    If same-IDC address calculation rule is used, the addresses for the same IDC take precedence over the addresses for routing rules, and the addresses for routing rules are calculated in the address set of the rules for the same IDC.

    Routing rules are divided into interface routing rules, method routing rules, and parameter routing rules, with descending priority. If a routing rule at a certain level does not exist, the returned key is null or RoutingRuleMap does not contain the corresponding value, this level has no restrictions on the routing address, and all the addresses at the upper level are used.

    The overall calculation process is as follows:

    • The final address list of interface-level routing rules (regular expression) intersects with the list of the result addresses of the same IDC rule.
    • The final address list of method-level routing rules (regular expression) intersects with the address list of the interface-level routing rules.
    • The final address list of parameter-level routing rules (regular expression) intersects with the address list of the method-level routing rules.

5. Check whether the routing rule is actually called

If the problem persists after the preceding troubleshooting, check whether the service or method specified by the routing rule is actually called. If the corresponding method is not called, the call log cannot be found on the target instance.

You can print the log by using System.out.println() in the routing rule. Note that the returned content must be a closure. For example:

ovy_v200907@package hqm.test.groovy
public class RoutingRule {
    Map<String, List<String>> 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." ;
                }
            }
        }
    }
}