Alibaba Sentinel對接Spring Cloud Gateway關於不顯示API管理及請求鏈路的坑附帶解決方案


調試Sentinel對接Scg網關的時候,出現了一個比較坑的現象,就是網關菜單,不顯示請求鏈路和API管理的菜單項,這個問題主要是由於,Sentinel的dashboard前端sidebar.js的 代碼邏輯中,       /registry/machine查詢返回的數據,返回的appType = 0

AppService.getApps().success(
function (data) {
if (data.code === 0) {
let path = $location.path().split('/');
let initHashApp = path[path.length - 1];
$scope.apps = data.data;
$scope.apps = $scope.apps.map(function (item) {
if (item.app === initHashApp) {
item.active = true;
}
let healthyCount = 0;
for (let i in item.machines) {
if (item.machines[i].healthy) {
healthyCount++;
}
}
item.healthyCount = healthyCount;
// 對應后端接口 /registry/machine查詢數據,返回的appType = 0
item.isGateway = item.appType === 1 || item.appType === 11 || item.appType === 12;

if (item.shown) {
return item;
}
});
}
}
);
通過后端MachineRegistryController的receiveHeartBeat方法返回的數據 item的appType為0,這就使得菜單一直顯示普通的服務類型的菜單,而不顯示網關類型的菜單。

receiveHeartBeat方法實際是由連接dashboard的各個客戶端發送心跳數據,傳入的參數中含有appType, 而透過客戶端的代碼可以看到以,使用http方式傳輸為例,可以看一下客戶端SimpleHttpHeartbeatSender的源碼,這里的sendHeartbeat方法,就是對應dashboard的receiveHeartBeat來進行信息交互的,通過調試可以看出發送的心跳數據HeartbeatMessage中,appType就為0而不是為1,HeartbeatMessage類中app_type的值是來源於SentinelConfig.getAppType() 

public HeartbeatMessage() {
message.put("hostname", HostNameUtil.getHostName());
message.put("ip", TransportConfig.getHeartbeatClientIp());
message.put("app", AppNameUtil.getAppName());
// Put application type (since 1.6.0).
message.put("app_type", String.valueOf(SentinelConfig.getAppType()));
message.put("port", String.valueOf(TransportConfig.getPort()));
}
而SentinelConfig中 appType的默認值APP_TYPE_COMMON = 0,由於SentinelSCGAutoConfiguration自動配置的時候,init初始化方法未能在發送心跳前將appType的值進行變更,所以導致都是按默認值0來傳遞數據的,也就是說,SimpleHttpHeartbeatSender中的HeartbeatMessage在初始化的時候SentinelSCGAutoConfiguration里的initAppType方法還未未執行,SentinelSCGAutoConfiguration是在SimpleHttpHeartbeatSender讀取csp.sentinel.app.type之后執行的,所以SentinelSCGAutoConfiguration這里的自動配置csp.sentinel.app.type是無效的,這就使得dashboard一直按普通服務展示菜單。所以只能通過,SentinelConfigLoader 會從System.getProperty加載變量信息,並最終由SentinelConfig的loadProps方法加載到props的內存Map中,解決辦法是可以在服務的啟動命令中加上 -Dcsp.sentinel.app.type=1 或者 在服務的Application的main方法里加入System.setProperty("csp.sentinel.app.type", "1"); 這樣就可以使得機器的appType變為1

@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
System.setProperty("csp.sentinel.app.type", "1");
SpringApplication.run(Application.class, args);
}
}
這樣調整之后只是改變了一半的問題,你會發現即便改變完成,dashboard刷新后,菜單仍然不會刷新變為網關類型,這是什么原因呢,調試代碼發現,雖然客戶端心跳發送的machineInfo已經變更appType,但是dashboard查詢數據AppInfo里中的apptype依舊為0,

public class AppInfo {

private String app = "";

private Integer appType = 0;

private Set<MachineInfo> machines = ConcurrentHashMap.newKeySet(); 這里的appType已經變為1了

public AppInfo() {}
這又是什么原因呢?經過調試,最后發現,問題就出現在了,SimpleMachineDiscovery里的addMachine方法上了

@Component
public class SimpleMachineDiscovery implements MachineDiscovery {

private final ConcurrentMap<String, AppInfo> apps = new ConcurrentHashMap<>();

@Override
public long addMachine(MachineInfo machineInfo) {
AssertUtil.notNull(machineInfo, "machineInfo cannot be null");
AppInfo appInfo = apps.computeIfAbsent(machineInfo.getApp(), o -> new AppInfo(machineInfo.getApp(), machineInfo.getAppType()));
// 只有當apps里對象不存在的時候,才會放一個新的進去,才會發生變化
appInfo.addMachine(machineInfo);
return 1;
}
這是因為,apps里存儲了所有服務的服務信息,開始提到的,item.isGateway = item.appType === 1 || item.appType === 11 || item.appType 這個item對象實際對應的是appInfo對象,而appInfo對象里的appType值,是在第一次apps里對象不存在的時候,才會放一個新的進去,才會發生變化。所以當你不重啟dashboard的時候,apps里的服務列表中單個對象中的appType是不會變化的,即便是你網關服務已經變更appTpye=1並發送心跳過來。所以直到你重啟dashboard ,apps重新裝載數據的時候,apps里的服務列表中單個對象中的appType才會重新取到客戶端修改后的值並存進去。

AppInfo appInfo = apps.computeIfAbsent(machineInfo.getApp(), o -> new AppInfo(machineInfo.getApp(), machineInfo.getAppType()));

machineInfo.getAppType()變為1了
apps的中AppInfo的appType才會被machineInfo.getAppType值覆蓋掉
這個時候頁面中的菜單才會變為
————————————————
版權聲明:本文為CSDN博主「幕紫」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ankeway/article/details/107262986


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM