Sentinel 控制台不显示应用问题定位过程

背景

        最近准备使用阿里的容灾组件Sentinel在项目中,做一些接口的监控和限流降级功能。

       本地改进Sentinel控制台,使用ZK做了持久化,调试没有问题后,准备测试并上线到生产环境。此时出现一个比较怪的问题。

问题现象

      本地启动客户端项目,Sentinel控制台可以正常显示监控信息,发布到Linux测试环境和 线上环境,控制台不显示应用。

 

定位问题

第一步,首先怀疑是网络问题,因为Linux 服务器部署的 控制台 和 客户端不在同一台机器上。

telnet ip port

结果:可以通

netstat 查看端口和网络情况,均正常。

第二步,网络是通的,此时怀疑是否是防火墙、权限等拦截了。

找运维沟通,确定测试环境是内网,没有类似的权限限制,检查了防火墙,也没有拦截相应的端口。

没办法,只能去github 查看Sentinel 的 wiki.

根据wiki的FAQ排查问题

其他配置既然本地可以,说明代码和配置没问题,看到wiki 说 fastjson 版本不一致,可能导致客户端 埋点数据上报 控制台不显示。

统一fastjson 为最新版1.2.62 后,重新编译发布测试环境,依然不可以。。。。

又检查了几遍测试配置的ip 和 hostname 映射,均没问题。

此时有些犯难了,能想到都已经检查过了,为什么本地和测试环境会有区别?

难道是 JDK版本不一致导致? 本地 jdk1.8.0_191, 测试环境jdk1.8.0_131。

没办法了,开始排除法,剔除一切不同的环境因素。统一 jdk版本后,发现依然存在该问题。。。。吐血

第三步,深入分析JVM线程和Sentinel 启动日志 和 埋点发送日志

查看了Sentinel 自身的record.log , 没有 任何error 日志。启动也没有报错。

最后只能通过profiling 手段来在线分析。

以下是我截取的本地和Linux环境 的 运行时 Threads.

Linux环境:

image

本地:

image

终于发现了一些问题,sentinel 相关的Threads, Linux 服务器比本地少了一些。

少的这些线程作用是啥? 为什么这些线程没有启动?

到了这里,没办法了,只能去看源码,了解Sentinel 源码运行情况

第四步, 阅读源码

查看源码发现这几个线程在 sentinel 客户端初始化的时候,就会启动,那说明Sentiel 没有初始化成功,可是不成功为什么没有报错信息呢?

 这里感觉有点坑。。。

初始化代码如下:

发现启动过程中有一些日志

去查找日志:

本地启动日志:

Linux上的日志:

image

锁定了问题,日志区别就是红框内部分。

CommandCenterInitFunc 和 HeartbeatSenderInitFunc 、SimpleHttpCommandCenter 没有打印,没有启动。

到这里,问题基本浮出水面了。

源码中可以看到,这里使用了 ServiceLoader 加载接口实现。 这里使用了SPI 技术。

ServiceLoader 加载SPI 接口实现类时,需要将接口实现配置到 META-INF/services/ 下,解压Linux服务器上的jar 包,进入该目录。发现 InitFunc 接口配置文件,只有 com.alibaba.csp.sentinel.metric.extension.MetricCallbackInit。

其他的SPI实现类均丢失了。

问题终于定位。。。。剩下的就是找出解决办法。

问题解决

参考:https://stackoverflow.com/questions/24484962/dependencies-of-dependency-are-not-included/27317054#27317054

https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ServicesResourceTransformer

查找资料,了解到maven编译问题,会导致编译SPI接口出现覆盖,使用shade 插件可以解决。

在 pom.xml 中增加以下:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

重新打包编译,解压jar 后查看META-INF/services/ 下的InitFunc 配置:

发现,其他几个类已经有了。

长呼一口气。。。。

发布到测试环境,启动后,展示正常:

总结

        该问题定位话费了不少时间,过后反思。

1. 本地为何可以?

因为本地 IDEA 启动是直接编译执行,不存在 SPI 丢包情况, 而Linux 其实是启动jar 包运行。

启动方式不一样,这里是个误区。

发布了14 篇原创文章 · 获赞 11 · 访问量 9325

猜你喜欢

转载自blog.csdn.net/qq_27641935/article/details/103196045