一. 问题描述

笔者在用SpringBoot 2.1.4.RELEASE + SpringCloud Greenwich.SR5学习Hystrix时,在Hystrix Dashboard页面出现了一个常见错误:hystrix dashboard Unable to connect to Command Metric Stream,截图如下:

springboot slf4j 默认几天 springboot401_spring boot


而我直接在浏览器中输入hystrix.stream地址:http://localhost:20081/actuator/hystrix.stream 是能访问到接口内容的

springboot slf4j 默认几天 springboot401_spring_02

二. 原因分析

1. SpringBoot2.0版本问题排查

首先审查了下,项目需要的security及hystrix相关依赖都已添加:

<!-- spring security依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
   
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!-- dashboard可视化面板 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

一开始我以为是SpringBoot2.0以上版本出现的:url增加/actuator、需要配置Servlet映射问题(参见此博客)。

@Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

但发现此配置没有用,依然会报错。思考到我之前就可以通过直接输入地址:http://localhost:20081/actuator/hystrix.stream 访问到接口内容,那应该不会是SpringBoot2.0的问题,换其他思路

2. 看后台服务报错

回看到后台服务的日志信息,发现后台服务报错与上文博客中的情况不同,为Http 401错误,日志如下

2021-11-13 20:36:30.002  WARN 22544 --- [io-20081-exec-7] ashboardConfiguration$ProxyStreamServlet : Failed opening connection to http://localhost:20081/actuator/hystrix.stream : 401 : HTTP/1.1 401 
2021-11-13 20:36:30.007  WARN 22544 --- [o-20081-exec-10] ashboardConfiguration$ProxyStreamServlet : Failed opening connection to http://localhost:20081/actuator/hystrix.stream : 401 : HTTP/1.1 401 
2021-11-13 20:36:45.476  INFO 22544 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration

HTTP 401错误是指用户权限认证出现问题。这提醒了我,本次实验项目pom中的Security模块是很早之前练习Eureka时就已经引入的包,当时还做了一些自定义配置。
会不会是当时的自定义配置影响了接口的调用?查到相关代码如下:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有的请求,都需要经过HTTP Basic认证
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }
}

这里就看到了问题原因所在:Security设置的项目接口都需要HTTPBasic输入用户名和密码进行登录认证。但Dashboard页面框架是作为get参数来加载hystrix.stream后台接口,此时后台系统无法认证相关接口用户登录态问题,则报错401

三. 解决办法

因为需要Dashboard自己轮询http://localhost:20081/actuator/hystrix.stream 这个接口,所以需要让后台服务将此接口进行登录态放行,修改此方法:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有的请求,都需要经过HTTP Basic认证
        http.authorizeRequests()
                .antMatchers("/actuator/hystrix.stream").permitAll()        //放行/actuator/hystrix.stream
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }

只增加了一行代码.antMatchers("/actuator/hystrix.stream").permitAll()。完成后重启,发现Dashboard成功出现监控数据

springboot slf4j 默认几天 springboot401_spring cloud_03

四. 总结

遇到问题需要对症下药,查到原因才能更好的解决

PS:

最开始测试时,我在打开浏览器访问本项目其他接口时,也做过用户认证,cookie中记下了我的登录态。因此后来直接用浏览器打开http://localhost:20081/actuator/hystrix.stream 接口时没有弹出登录接口,以至于疏忽了Security安全认证的配置

springboot slf4j 默认几天 springboot401_HTTP_04