文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringCloud—Spring Boot Admin微服务监控告警系统

2024-12-01 18:17

关注

业务系统正常运行的稳定性十分重要,作为SpringBoot的四大核心之一,Actuator让你时刻探知SpringBoot服务运行状态信息,是保障系统正常运行必不可少的组件。

spring-boot-starter-actuator提供的是一系列HTTP或者JMX监控端点,通过监控端点我们可以获取到系统的运行统计信息,同时,我们可以自己选择开启需要的监控端点,也可以自定义扩展监控端点。  

Actuator通过端点对外暴露的监控信息是JSON格式数据,我们需要使用界面来展示,目前使用比较多的就是Spring Boot Admin或者Prometheus + Grafana的方式:Spring Boot Admin实现起来相对比较简单,不存在数据库,不能存储和展示历史监控数据;Prometheus(时序数据库) + Grafana(界面)的方式相比较而言功能更丰富,提供历史记录存储,界面展示也比较美观。  

相比较而言,Prometheus + Grafana的方式更为流行一些,现在的微服务及Kubernetes基本是采用这种方式的。但是对于小的项目或者单体应用,Spring Boot Admin会更加方便快捷一些。具体采用哪种方式,可以根据自己的系统运维需求来取舍,这里我们把框架集成两种方式,在实际应用过程中自有选择。

本文主要介绍如何集成Spring Boot Admin以及通过SpringSecurity控制Actuator的端点权限。

1、在基础服务gitegg-platform中引入spring-boot-starter-actuator包。

无论是使用Spring Boot Admin还是使用Prometheus + Grafana的方式都需要spring-boot-starter-actuator来获取监控信息,这里将spring-boot-starter-actuator包添加到gitegg-platform-boot基础平台包中,这样所有的微服务都集成了此功能。

        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-actuatorartifactId>        dependency>

2、确定并引入工程使用的spring-boot-admin-starter-server和spring-boot-admin-starter-client依赖包。

spring-boot-admin-starter-server是Spring Boot Admin的服务端,我们需要新建一个SpringBoot工程来启动这个服务端,用来接收需要监控的服务注册,展示监控告警信息。spring-boot-admin-starter-client是客户端,需要被监控的服务需要引入这个依赖包。  

此处请注意: 看到网上很多文章里面写着添加spring-boot-admin-starter-client包,在SpringCloud微服务中是不需要引入的,spring-boot-admin-starter-client包仅仅是为了引入我们gitegg-platform平台工程的对应版本,在gitegg-boot框架中使用,在SpringCloud微服务框架中,不需要引入spring-boot-admin-starter-client,SpringBootAdmin会自动根据微服务注册信息查找服务端点,官方文档说明:spring-cloud-discovery-support 。  

在选择版本时,一定要找到对应SpringBoot版本的Spring Boot Admin,GitHub上有版本对应关系的说明:

我们在gitegg-platform-pom中来定义需要引入的spring-boot-admin-starter-server和spring-boot-admin-starter-client依赖包版本,然后在微服务业务开发中具体引入,这里不做统一引入,方便微服务切换监控方式。

......                <spring.boot.admin.version>2.3.1spring.boot.admin.version>......                                        de.codecentric                spring-boot-admin-starter-server                ${spring.boot.admin.version}                                                    de.codecentric                spring-boot-admin-starter-client                ${spring.boot.admin.version}            .......

3、在GitEgg-Cloud项目的gitegg-plugin工程下新建gitegg-admin-monitor工程,用于运行spring-boot-admin-starter-server。

pom.xml中引入需要的依赖包:

<dependencies>                <dependency>            <groupId>com.gitegg.platformgroupId>            <artifactId>gitegg-platform-bootartifactId>                        <exclusions>                <exclusion>                    <groupId>com.gitegg.platformgroupId>                    <artifactId>gitegg-platform-cacheartifactId>                exclusion>            exclusions>        dependency>                <dependency>            <groupId>com.gitegg.platformgroupId>            <artifactId>gitegg-platform-cloudartifactId>        dependency>                <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-securityartifactId>                        <exclusions>                <exclusion>                    <groupId>org.springframework.bootgroupId>                    <artifactId>spring-boot-starter-loggingartifactId>                exclusion>            exclusions>        dependency>        <dependency>            <groupId>de.codecentricgroupId>            <artifactId>spring-boot-admin-starter-serverartifactId>        dependency>    dependencies>

添加spring-boot-admin-starter-server启动类GitEggMonitorApplication.java,添加@EnableAdminServer注解即可。

@EnableAdminServer@SpringBootApplication@RefreshScopepublic class GitEggMonitorApplication {        public static void main(String[] args)    {        SpringApplication.run(GitEggMonitorApplication.class, args);    }    }

这里主要配置登录页面、静态文件、登录、退出等的权限。请注意这里配置了publicUrl的前缀,当部署在微服务环境或Docker环境中需要经过gateway或者nginx转发时,在SpringBootAdmin配置中,需要配置publicUrl,否则SpringBootAdmin只会跳转到本机环境的地址和端口。publicUrl如果是80端口,那么这个端口不能省略,需要配置上。

@Configuration(proxyBeanMethods = false)public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {        private final AdminServerUiProperties adminUi;        private final AdminServerProperties adminServer;        private final SecurityProperties security;        public SecuritySecureConfig(AdminServerUiProperties adminUi, AdminServerProperties adminServer, SecurityProperties security) {        this.adminUi = adminUi;        this.adminServer = adminServer;        this.security = security;    }        @Override    protected void configure(HttpSecurity http) throws Exception {                // 当设置了publicUrl时,Gateway跳转到login或logout链接需要redirect到publicUrl        String publicUrl = this.adminUi.getPublicUrl() != null ? this.adminUi.getPublicUrl() : this.adminServer.getContextPath();        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();        successHandler.setTargetUrlParameter("redirectTo");        successHandler.setDefaultTargetUrl(publicUrl + "/");                http.authorizeRequests(                (authorizeRequests) -> authorizeRequests.antMatchers(this.adminServer.path("/assets    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.inMemoryAuthentication().withUser(security.getUser().getName())                .password("{noop}" + security.getUser().getPassword()).roles(security.getUser().getRoles().toArray(new String[0]));    }    }

4、在Nacos配置中心配置SpringBootAdmin的相关配置,在gitegg-admin-monitor工程中,也需要配置读取配置的相关yml文件,除了读取主配置之外,还需要读取SpringBootAdmin专属配置。

spring:  boot:    admin:      ui:        brand: <img src="https://www.528045.com/file/upload/202411/30/0i5nwaks2d5.png"><span>GitEgg微服务监控系统span>        title: GitEgg微服务监控系统        favicon: http://img.gitegg.com/cloud/docs/images/logo.png        public-url: http://127.0.0.1:80/gitegg-admin-monitor/monitor      context-path: /monitor
server:  port: 8009spring:  profiles:    active: '@spring.profiles.active@'  application:    name: '@artifactId@'  cloud:    inetutils:      ignored-interfaces: docker0    nacos:      discovery:        server-addr: ${spring.nacos.addr}        metadata:          # 启用SpringBootAdmin时 客户端端点信息的安全认证信息          user.name: ${spring.security.user.name}          user.password: ${spring.security.user.password}      config:        server-addr: ${spring.nacos.addr}        file-extension: yaml        extension-configs:          # 必须带文件扩展名,此时 file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响          - data-id: ${spring.nacos.config.prefix}.yaml            group: ${spring.nacos.config.group}            refresh: true          - data-id: ${spring.nacos.config.prefix}-admin-monitor.yaml            group: ${spring.nacos.config.group}            refresh: true

5、扩展gitegg-gateway的SpringSecurity配置,增加统一鉴权校验。因我们有多个微服务,且所有的微服务在生产环境部署时都不会暴露端口,所以所有的微服务鉴权都会在网关做。

SpringSecurity权限验证支持多过滤器配置,同时可配置验证顺序,我们这里需要改造之前的过滤器,这里新增Basic认证过滤器,通过securityMatcher设置,只有健康检查的请求走这个权限过滤器,其他请求继续走之前我们设置的OAuth2+JWT权限验证器。

@RequiredArgsConstructor(onConstructor_ = @Autowired)@Configuration@EnableWebFluxSecuritypublic class MultiWebSecurityConfig {        private final AuthorizationManager authorizationManager;        private final AuthServerAccessDeniedHandler authServerAccessDeniedHandler;        private final AuthServerAuthenticationEntryPoint authServerAuthenticationEntryPoint;        private final AuthUrlWhiteListProperties authUrlWhiteListProperties;        private final WhiteListRemoveJwtFilter whiteListRemoveJwtFilter;        private final SecurityProperties securityProperties;        @Value("${management.endpoints.web.base-path:}")    private String actuatorPath;            @Order(Ordered.HIGHEST_PRECEDENCE)    @Bean    @ConditionalOnProperty( value = {"management.security.enabled", "management.endpoints.enabled-by-default"}, havingValue = "true")    SecurityWebFilterChain webHttpSecurity(ServerHttpSecurity http) {        if (StringUtils.isEmpty(actuatorPath))        {            throw new BusinessException("当启用健康检查时,不允许健康检查的路径为空");        }        http                .cors()                .and()                .csrf().disable()                .formLogin().disable()                .securityMatcher(new OrServerWebExchangeMatcher(                        new PathPatternParserServerWebExchangeMatcher(actuatorPath + "    @Bean    @ConditionalOnProperty( value = {"management.security.enabled", "management.endpoints.enabled-by-default"}, havingValue = "true")    ReactiveUserDetailsService userDetailsService() {        return new MapReactiveUserDetailsService(User                .withUsername(securityProperties.getUser().getName())                .password(passwordEncoder().encode(securityProperties.getUser().getPassword()))                .roles(securityProperties.getUser().getRoles().toArray(new String[0]))                .build());    }            @Bean    @ConditionalOnProperty( value = {"management.security.enabled", "management.endpoints.enabled-by-default"}, havingValue = "true")    public static PasswordEncoder passwordEncoder() {        DelegatingPasswordEncoder delegatingPasswordEncoder =                (DelegatingPasswordEncoder) PasswordEncoderFactories.createDelegatingPasswordEncoder();        return  delegatingPasswordEncoder;    }            @Bean    SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) {                http.oauth2ResourceServer().jwt()                .jwtAuthenticationConverter(jwtAuthenticationConverter());            // 自定义处理JWT请求头过期或签名错误的结果        http.oauth2ResourceServer().authenticationEntryPoint(authServerAuthenticationEntryPoint);            // 对白名单路径,直接移除JWT请求头,不移除的话,后台会校验jwt        http.addFilterBefore(whiteListRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION);            // Basic认证直接放行        if (!CollectionUtils.isEmpty(authUrlWhiteListProperties.getTokenUrls()))        {            http.authorizeExchange().pathMatchers(ArrayUtil.toArray(authUrlWhiteListProperties.getTokenUrls(), String.class)).permitAll();        }            // 判断是否有静态文件        if (!CollectionUtils.isEmpty(authUrlWhiteListProperties.getStaticFiles()))        {            http.authorizeExchange().pathMatchers(ArrayUtil.toArray(authUrlWhiteListProperties.getStaticFiles(), String.class)).permitAll();        }            http.authorizeExchange()                .pathMatchers(ArrayUtil.toArray(authUrlWhiteListProperties.getWhiteUrls(), String.class)).permitAll()                .anyExchange().access(authorizationManager)                .and()                .exceptionHandling()                                .accessDeniedHandler(authServerAccessDeniedHandler)                                .authenticationEntryPoint(authServerAuthenticationEntryPoint)                .and()                .cors()                .and().csrf().disable();            return http.build();    }            @Bean    public Converter> jwtAuthenticationConverter() {        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX);        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME);                JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);    }}

6、在Nacos配置中心,统一配置所有微服务的健康检查端点地址,权限校验的用户名密码等。

spring:......  security:    # # 启用SpringBootAdmin时,健康检查权限校验,不使用SpringBootAdmin此处可省略    user:      name: user      password: password      roles: ACTUATOR_ADMIN......# 性能监控端点配置management:  security:    enabled: true    role: ACTUATOR_ADMIN  endpoint:    health:      show-details: always  endpoints:    enabled-by-default: true    web:      base-path: /actuator      exposure:        include: '*'  server:    servlet:      context-path: /actuator  health:    mail:      enabled: false......

7、设置网关Gateway配置,对gitegg-admin-monitor进行过路由和转发。

spring:    gateway:      discovery:        locator:          enabled: true      routes:......        - id: gitegg-admin-monitor          uri: lb://gitegg-admin-monitor          predicates:            - Path=/gitegg-admin-monitor/**          filters:            - StripPrefix=1        - id: monitor          uri: lb://gitegg-admin-monitor          predicates:            - Path=/monitor/**          filters:            - StripPrefix=0......

8、启动所有的微服务,并访问 http://127.0.0.1/gitegg-admin-monitor/monitor/login 进行健康检查微服务配置。

根据我们在Nacos中的配置,我们这里的登录用户名密码是:user / password。

以上为SpringBootAdmin在SpringCloud微服务中的搭建和配置步骤,相比较而言比较简单,但是一定要注意权限问题,不要因为健康检查而泄露了系统信息。我们这里是通过Gateway进行的统一鉴权,在生产环境部署时,一定要注意修改默认的Basic校验用户名密码,甚至需要修改健康检查端点。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯