版权声明:本文为博主原创文章,版权归烟台华东数据科技有限公司与博主本人共同所有。烟台华东数据科技有限公司及其下属机构毋须博主授权即可在任意用途下转载、使用!
目录
Environment
- Intellij Idea version : 2019.1.2
- JavaSDK version : 1.8
- Maven version : 3.6.1
- Spring Cloud version : Finchley.SR4
- SpringBoot version : 2.0.9.RELEASE
- Spring Boot Admin 2.0.6
Spring Boot Admin简介
Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册(通过HTTP)或使用SpringCloud注册中心(例如Eureka,Consul)发现。 UI是的AngularJs应用程序,展示Spring Boot Admin Client的Actuator端点上的一些监控。常见的功能或者监控如下:
- 显示健康状况
- 显示详细信息,例如
- JVM和内存指标
- micrometer.io指标
- 数据源指标
- 缓存指标
- 显示构建信息编号
- 关注并下载日志文件
- 查看jvm系统和环境属性
- 查看Spring Boot配置属性
- 支持Spring Cloud的postable / env-和/ refresh-endpoint
- 轻松的日志级管理
- 与JMX-beans交互
- 查看线程转储
- 查看http跟踪
- 查看auditevents
- 查看http-endpoints
- 查看计划任务
- 查看和删除活动会话(使用spring-session)
- 查看Flyway / Liquibase数据库迁移
- 下载heapdump
- 状态变更通知(通过电子邮件,Slack,Hipchat,......)
- 状态更改的事件日志(非持久性)
详细的学习与配置,本文不再介绍,可以参考以下博客:
Spring Boot Admin 详解(Spring Boot 2.0,基于 Eureka 的实现)
本文只把项目中需要注意的问题列明如下:
启动类:
package net.huadong;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableDiscoveryClient
@EnableAdminServer
@SpringBootApplication
public class HddSpringAdminApplication {
public static void main(String[] args) {
SpringApplication.run(HddSpringAdminApplication.class, args);
}
}
安全登录配置类:
package net.huadong;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
/**
* @author yangzj
* @desc Security配置类,用于配置admin server的安全控制
* @create 2019-06-30 15:16
**/
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 登录成功处理类
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeRequests()
//静态文件允许访问
.antMatchers(adminContextPath + "/assets/**").permitAll()
//登录页面允许访问
.antMatchers(adminContextPath + "/login").permitAll()
//其他所有请求需要登录
.anyRequest().authenticated()
.and()
//登录页面配置,用于替换security默认页面
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
//登出页面配置,用于替换security默认页面
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(
"/instances",
"/actuator/**"
);
}
}
bootstrap.yml 在这里配置的账号密码,详细说明解释请查看上面推荐的博客或者文档
spring: application: name: springAdmin cloud: config: enabled: true discovery: enabled: true service-id: config #1 security: user: name: 'hdd' password: 'ok' eureka: instance: non-secure-port: ${server.port:8110} health-check-url-path: /actuator/health metadata-map: instanceId: ${spring.application.name}:${random.value} #4 user.name: ${spring.security.user.name} user.password: ${spring.security.user.password} client: service-url: defaultZone: http://${eureka.host:localhost}:${eureka.port:8101}/eureka/
pom文件:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
但是照这样开启后,会发现并不能正常监控,原因是从Spring Boot 2.0开始 Actuator 只暴露了 /health、/info 两个端口(为了安全考虑),所以要配置 management.endpoints.web.exposure.include 的属性,下面的配置文件中直接暴露了所有的端点,详细的端点介绍配置,可以查看官方文档。
或者可以参考此博文:一起来学SpringBoot | 第十四篇:强大的 actuator 服务监控与管理
此处我们给上一篇博文提到的RedisService暴露端口
HDD_REDIS_SERVICE中的application.yml文件:
server: port: 8889 logging: config: classpath:logback.xml level: org.springframework: error debug: false #actuator 启用所有的监控端点 “*”号代表启用所有的监控端点,可以单独启用,例如,health,info,metrics # spring boot 升为 2.0 后,为了安全,默认 Actuator 只暴露了2个端点,heath 和 info,继续 # 访问 http://localhost:8889/actuator/metrics management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS
演示效果
访问http://localhost:8110 会自动跳转到登录界面
登录后,显示各个已经注册的微服务模块:
选择一个微服务模块后进去,会有详细的描述界面
在Web——HTTP Traces中有详细的访问描述
Hystrix简介与使用、Turbine集群监控
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。
有关Hystrix的介绍网上面有很多,此处不再赘述,Hystrix的简介、原理、实现的目的可以参考如下资料:
详细的熔断使用开发介绍
Hystrix注意事项
经过上面的资料介绍,Hystrix的熔断有两种配置模式:
- 直接配置在Controller方法中,并且针对每一个需要实现熔断处理的方法实现一个对应的熔断处理方法
- 针对提供Service服务的Feign进行熔断监控
而我们项目里面是两种模式都有可能使用,网上面很多资料都没有详细描述这两种模式的区别,我在这里分开描述一下各自的用法和说明
1、单个方法配置Hystrix
如在HDD_REDIS_SERVICE的Controller中
@ApiOperation(value = "设置redis缓存值", notes = "设置redis缓存值")
@RequestMapping(value = "/setRedis", method = RequestMethod.POST)
@HystrixCommand(fallbackMethod = "setRedisFall")
void setRedis(@RequestBody Map<String, Object> map) {
String key = (String) map.get("key");
Object obj = map.get("value");
redisService.set(key, obj);
}
void setRedisFall(Map<String, Object> map) {
logger.error("RedisService setRedis Failed!");
}
很简单的设置,这种一般是正针对于微服务内部的错误,比如底层的数据库出问题了或者SpringMVC中的redisService层报错了,从而进行的熔断处理。
2、对Feign进行熔断配置
在HDD_REDIS_SERVICE_INTERFACE中
RedisService
package net.huadong.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@FeignClient(name = "redisService", fallbackFactory = RedisServiceFallback.class)
@Component
public interface RedisService {
/**
* 根据传入的map(key,value)值设置redis
*
* @param map
* @return
*/
@RequestMapping(value = "/Redis/setRedis", method = RequestMethod.POST)
void set(@RequestBody Map<String, Object> map);
/**
* 传入key获取对应的redis 值
*
* @return obj
*/
@RequestMapping(value = "/Redis/getRedis", method = RequestMethod.POST)
@ResponseBody
Object get(@RequestParam("key") String key);
}
RedisServiceFallback
package net.huadong.service;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author yangzj
* @desc 熔断降级方法
* @create 2019-06-30 17:12
**/
@Component
public class RedisServiceFallback implements FallbackFactory<RedisService> {
@Override
public RedisService create(Throwable throwable) {
throwable.printStackTrace();
return new RedisService() {
@Override
public void set(Map<String, Object> map) {
System.out.println(throwable.getMessage());
}
@Override
public Object get(String key) {
return throwable.getMessage();
}
};
}
}
这个与方法1最大的区别是,这个是在调用方进行熔断控制,比如其他项目A使用这个INTERFACE接口调用Redis的微服务,出现了问题,可能是网络问题、接口不可访问等,熔断的控制其实是在项目A中进行的。而方法1中的熔断控制是直接在微服务中控制的。
当然网络上有的人其实是把这两个混在一起了,Redis的微服务既是单独的服务实例,同时提供对外的Feign连接,或者不提供Feign,直接需要其他项目使用Rest的方式进行访问。个人觉得远不及使用Feign方便,直接隐藏了下一层的网络处理代码。
pom文件:
方法1中需要引用:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
方法2中不需要额外引用,只要引用了Feign即可,如下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
题外话
Hystrix已经于2018年年末官方正式宣布不再开发,但是还是会持续维护一段时间。当前还是可以继续使用的。
替代品官方推荐使用Resilience4J
或者使用Alibaba Sentinel
集成Turbine集群监控
上面提到的Hystrix只是针对单个方法的情况或者单个Service,而在实际的生成环境中,都是大范围的集群。
Turbine是聚合服务器发送事件流数据的一个工具,Hystrix的监控中,只能监控单个节点,实际生产中都为集群,因此可以通过Turbine来监控集群下Hystrix的metrics情况。
例如,我们在上一篇说的HDD_REDIS_SERVICE增加集群监控示例
pom引用
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-turbine</artifactId> </dependency>
启动类:
package net.huadong;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@EnableEurekaClient
@SpringBootApplication
@EnableCircuitBreaker
@EnableHystrixDashboard
@EnableTurbine
public class HddRedisServiceApplication {
public static void main(String[] args) {
SpringApplication.run(HddRedisServiceApplication.class, args);
}
}
最后关键的一步:application.yml
server: port: 8889 logging: config: classpath:logback.xml level: org.springframework: error debug: false eureka: client: healthcheck: enabled: true feign: hystrix: enabled: true hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 30000 #actuator 启用所有的监控端点 “*”号代表启用所有的监控端点,可以单独启用,例如,health,info,metrics # spring boot 升为 2.0 后,为了安全,默认 Actuator 只暴露了2个端点,heath 和 info,继续 # 访问 http://localhost:8889/actuator/metrics management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS
一定要在配置中开启Hystrix的控制。
综合以上,要实现Turbine集群监控,第一步就是微服务中要实现了Hystrix,然后启动类上增加了相应注解,然后在application.yml配置文件中进行了相应配置。
Turbine集群监控微服务
启动类
package net.huadong;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
/**
* 断路器监控
*/
@SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard
@EnableTurbine
public class HddBreakMonitorApplication {
public static void main(String[] args) {
SpringApplication.run(HddBreakMonitorApplication.class, args);
}
}
bootstrap.yml
spring: application: name: monitor eureka: instance: nonSecurePort: ${server.port:8989} lease-renewal-interval-in-seconds: 20 lease-expiration-duration-in-seconds: 30 client: serviceUrl: defaultZone: http://${eureka.host:localhost}:${eureka.port:8101}/eureka/ turbine: combine-host-port: true app-config: redisService cluster-name-expression: new String("default") aggregator: cluster-config: default #更改turbine连接的默认uri ,默认为actuator/hystrix.stream instanceUrlSuffix: actuator/hystrix.stream
其中有一个关键的turbine.app-config配置,这里配置的就是需要监控哪一个Service
pom文件
<parent>
<artifactId>HDD_SHJJHY_PLATFORM</artifactId>
<groupId>net.huadong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>HDD_BREAK_MONITOR</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>HDD_BREAK_MONITOR</name>
<description>EUREKA的熔断器和监控器</description>
<properties>
<start-class>net.huadong.HddBreakMonitorApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
</dependencies>
演示效果
启动监控微服务后,进入地址:http://localhost:8989/hystrix
在这里输入监控地址:http://localhost:8989/turbine.stream
进入后,刚开始很多人也许会显示Loading...
出现Loading的原因很多,我初步总结如下:
- app-config中设置的Service并没有使用方法1或者方法2的Hystrix
- 没有暴露端口
- 需要监控的微服务中没有加上相应的注解或者相关引用
- 启动后,需要有数据流转起来才能监控,一般是项目刚启动后,没有对相关配置了熔断的方法进行了调用
- 参考资料:https://www.cnblogs.com/houzheng/p/9906800.html
成功后的效果如下:
一个监控的方法就会出现一个监控,相关数据项目的解释说明请查看以下博文资料:
下一章,如何让其他非Spring Cloud项目使用微服务