報錯資訊
使用Groovy指令碼佈建服務的路由規則未生效。
可能原因
上述報錯資訊表明調用沒有被路由到預期的機器上,可能原因是規則配置錯誤,例如路由規則填寫錯誤、路由規則裡的IP沒有提供服務等。路由規則的配置方式,請參見 Routing Rule Wiki。
解決方案
您可以通過以下步驟,排查路由規則是否生效。
步驟一:用戶端是否為本地調用、泛化調用
如果用戶端通過本地調用、泛化調用的方式消費服務,將不會使用路由規則邏輯,因此會出現路由規則不生效的情況。
- 本地調用:指一個進程既是一個服務的發行者,又是這個服務的消費者。此時,HSF預設優先使用本地調用,即進程內的Java調用,而非RPC調用。這種情況不使用路由規則的邏輯。
- 泛化調用:指不依賴服務的二方包,直接通過GenericService通過服務描述進行消費的情境。此時,HSF由於沒有服務的Class,無法執行路由規則裡調用業務類的邏輯,因此也不使用路由規則的邏輯。
HSFOPS上的服務測試功能使用的是泛化調用,因此路由規則也不會生效。
步驟二:用戶端是否收到路由規則
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<String>> routingRuleMap(){
return [
"G1":["100.69.161.201:*"]
]
}
String interfaceRoutingRule(){
return "G1";
}
}
- 路由規則的命名是否與服務名對應。具體資訊,請參見 Routing Rule Wiki。
- 路由規則配置在Diamond上的環境和用戶端所在的環境是否一致。
步驟三:路由規則是否正確解析
在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 ,檢查您的路由規則。
步驟四:路由規則的內容是否正確
收到路由規則且解析正確後,如果路由規則執行的效果仍與預期不同,請依次檢查以下內容。
- 確認路由的目標機器是否提供該服務。
請在對應環境的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 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].
- 確認路由規則是否正確。
檢查介面路由、方法路由、參數路由。
- 確認地址計算優先順序。
如果開啟了同機房規則,那麼同機房的地址優先於路由規則的地址,路由規則的地址在同機房規則結果的地址集合裡再計算。
路由規則分為介面級>方法級>參數級,若某一級的路由規則不存在,即其返回的key為null,或在
routingRuleMap中找不到相應值,則認為這一級對路由地址不做限制,地址取上一級的全部地址。總體的計算過程如下:- 介面級路由規則(正則式)最終地址清單會和同機房規則結果地址清單作交集。
- 方法級路由規則(正則式)最終地址清單會和介面級地址清單作交集。
- 參數級路由規則(正則式)最終地址清單會和方法級地址清單作交集。
步驟五:路由規則是否被調用
如果按照以上內容排查後均確認無誤,請再確認路由規則指定的服務或方法是否被調用。如果相應的方法沒有被調用,則在目標機器上肯定也搜不到調用日誌。
可以通過System.out.println()在路由規則中列印內容來確認,同時注意返回的內容必須為一個閉包。例如:
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.";
}
}
}
}
}