在调试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 = 0item.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<>();@Overridepublic 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值覆盖掉

这个时候页面中的菜单才会变为

Alibaba Sentinel对接Spring Cloud Gateway关于不显示API管理及请求链路的坑附带解决方案相关推荐

  1. Spring Cloud Gateway — 网关基本功能API暴露

    API网关 API网关是一种设计模式,一种在微服务体系下的经典构件.要了解最新API网关模式可以参考敖小剑写的<Service Mesh和Api Gateway关系深度探讨> 早期SOA阶 ...

  2. 当Spring Cloud Alibaba Sentinel碰上Spring Cloud Sleuth会擦出怎样的火花

    前言 今年主要会做一个比较完整的微服务项目开源出来.目前已经开始了,刚兴趣的先Star一个吧. 项目:https://github.com/yinjihuan/kitty-cloud 基础框架:htt ...

  3. Spring Cloud入门教程 - Zuul实现API网关和请求过滤

    简介 Zuul是Spring Cloud提供的api网关和过滤组件,它提供如下功能: 认证 过滤 压力测试 Canary测试 动态路由 服务迁移 负载均衡 安全 静态请求处理 动态流量管理 在本教程中 ...

  4. 实战 Spring Cloud Gateway 之限流篇

    来源:https://www.aneasystone.com/archives/2020/08/spring-cloud-gateway-current-limiting.html 话说在 Sprin ...

  5. 这可能是全网Spring Cloud Gateway限流最完整的方案了!

        作者:aneasystone     https://www.aneasystone.com/ 话说在 Spring Cloud Gateway 问世之前,Spring Cloud 的微服务世 ...

  6. Spring Cloud Gateway 入门

    认识 Spring Cloud Gateway Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API ...

  7. 有什么办法动态更改yml的值吗_基于Redis实现Spring Cloud Gateway的动态管理

    转载本文需注明出处:微信公众号EAWorld,违者必究. 引言: Spring Cloud Gateway是当前使用非常广泛的一种API网关.它本身能力并不能完全满足企业对网关的期望,人们希望它可以提 ...

  8. Spring Cloud Gateway (七)处理流程解析

    Spring Cloud Gateway (七)处理流程解析 简介     初步梳理 Spring Cloud Gateway 的处理流程 过程记录 主要请求流程     在前面的分析中,我们知道在 ...

  9. springcloud(十一):服务网关 Spring Cloud GateWay 入门

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

最新文章

  1. php 内容自动生成word文档,php生成word文档的例子
  2. 在openshift上自定义node.js的版本
  3. redis的hash操作在集中式session中的应用
  4. php js 比较大小写,JavaScript中如何实现大小写转换
  5. 去火星的票和背后的故事!
  6. day-17 包与模块
  7. mysql使用技巧_MySQL使用不得不看的几个小技巧
  8. C# 控制台 打印输出
  9. C#用链式方法表达循环嵌套
  10. jenkins相关下载链接
  11. 快速获取知网,万方,维普等永久性免费下载权限
  12. Raspberry Pi Zero W 安装配置
  13. Windows 10正式版官方原版ISO镜像下载汇总!!!
  14. YOLO ZOO:YOU ONLY LOOK ONCE ZOO
  15. AHP层析分析法初步讲解
  16. 中国电子竞技市场:外国玩家的机遇与挑战
  17. 为什么别人总是把你往“坏处想”?浅谈如何更好地与项目团队中的“网友”更好地交流
  18. PHP实现小程序微信支付V2获取prepay_id
  19. 中国各大IT公司创始人学历统计
  20. c# 小票机打印二维条码_C# winform 使用rdlc打印小票其中包含动态显示多条形码的解决方法...

热门文章

  1. 正确使用小程序中的globalData
  2. vue高仿网易云音乐踩到的坑:根据登陆状态显示头像
  3. html图标右上角添加小图标,图片右上角增加删除图标(css布局示例)
  4. 危险派对 - 王以太/刘至佳
  5. 【Qt】解决QScrollBar调用setValue()方法会自动发送valueChanged问题
  6. 我带你去哪里 VII
  7. steam课程 机器人
  8. Android APP转成launcher
  9. Python爬虫爬取肯德基餐厅信息案例实现(含源码及详细解释)
  10. maysql 按月建立分表