有多少人从未在生产环境中遇到系统崩溃或故障?当然,你们每个人迟早都会经历它。如果我们无法避免失败,那么解决方案似乎是将我们的系统维持在永久性故障状态。Chaos Monkey - 这个概念是Netflix发明的工具,用于测试其IT基础架构的弹性。几天前,我根据Netflix工具背后的想法找到了解决方案,该工具旨在测试Spring Boot应用程序。Codecentric已经实现了这样的库。到目前为止,我认为它们只是作为Spring Boot生态系统专用的其他有趣解决方案的作者 - Spring Boot Admin。我已经在之前的一篇文章中描述了这个库使用 Monitoring Microservices With Spring Boot Admin。 今天我将向您展示如何在Spring Boot应用程序中包含Codecentric的Chaos Monkey,然后在一些微服务示例系统中实现混沌工程。Chaos Monkey库可以与Spring Boot 2.0一起使用,它的当前发行版本是1.0.1。但是,我将使用2.0.0-SNAPSHOT版本实现示例,因为它具有此库的早期版本中不能用的一些新的有趣功能。为了能够下载Codecentric的Chaos Monkey库的SNAPSHOT版本,您必须记住包含Maven存储库https://oss.sonatype.org/content/repositories/snapshots到您的pom.xml存储库中。

1.为应用程序启用Chaos Monkey

为Spring Boot应用程序启用Chaos Monkey 有两个必需的步骤。首先,让我们将chaos-monkey-spring-boot库添加到项目的依赖项中。

   de.codecentric

   chaos-monkey-spring-boot

   2.0.0-SNAPSHOT

然后,我们应该在应用程序启动时激活chaos-monkey文件。

$ java -jar target/order-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

2.样本系统架构

我们的示例系统由三个微服务组成,每个微服务都在两个实例中启动,还有一个服务发现服务器。微服务将自己注册到发现服务器,并通过HTTP API相互通信。Chaos Monkey库包含在所有正在运行的微服务的每个实例中,但不包含在发现服务器中。下面是用于说明示例系统架构的图表。

样本应用程序的源代码可以在GitHub的仓库 sample-spring-chaosmonkey中找到。克隆此存储库并使用mvn clean install命令构建它之后,您应该首先运行discovery-service。然后通过-Dserver.port使用适当的数字设置属性,在不同端口上运行每个微服务的两个实例。下面是我的一组运行命令。

$ java -jar target/discovery-service-1.0-SNAPSHOT.jar

$ java -jar target/order-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

$ java -jar -Dserver.port=9091 target/order-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

$ java -jar target/product-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

$ java -jar -Dserver.port=9092 target/product-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

$ java -jar target/customer-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

$ java -jar -Dserver.port=9093 target/customer-service-1.0-SNAPSHOT.jar --spring.profiles.active=chaos-monkey

3.流程配置

在版本2.0.0-SNAPSHOT的chaos-monkey-spring-boot库中,Chaos Monkey默认启用它包含的应用程序。您可以使用chaos.monkey.enabled属性禁用它。但是,默认情况下启用的唯一攻击是延迟。这种类型的攻击会通过属性chaos.monkey.assaults.latencyRangeStart和chaos.monkey.assaults.latencyRangeEnd确定的范围为应用程序处理的请求添加随机延迟。受攻击请求的数量取决于属性chaos.monkey.assaults.level,其中1表示每个请求,10表示每第10个请求。我们还可以为我们的应用程序启用异常和appKiller攻击。为简单起见,我为所有微服务设置了配置。我们来看看application.yml文件中提供的设置。

chaos:

 monkey:

   assaults:

     level: 8

     latencyRangeStart: 1000

     latencyRangeEnd: 10000

     exceptionsActive: true

     killApplicationActive: true

   watcher:

     repository: true

     restController: true

理论上,上面显示的配置应该启用所有三种可用类型的攻击。但是,如果启用latency和exceptions,killApplication永远不会发生。此外,如果同时启用latency和exceptions,则无论使用chaos.monkey.assaults.level属性设置哪个级别,发送给应用程序的所有请求都将受到攻击。记住激活restController观察者很重要,默认情况下禁用观察者。

4.启用Spring Boot Actuator端点

Codecentric在其Chaos Monkey库的2.0版本中实现了一项新功能 - Spring Boot Actuator的端点。要为我们的应用程序启用它,我们必须按照执行程序约定激活它 - 通过将属性management.endpoint.chaosmonkey.enabled设置为true。此外,从Spring Boot 2.0版开始,我们必须公开该HTTP端点在应用程序启动后可用。

management:

 endpoint:

   chaosmonkey:

     enabled: true

 endpoints:

   web:

     exposure:

       include: health,info,chaosmonkey

chaos-monkey-spring-boot提供了几个端点,允许你查看和修改配置。你可以使用GET /chaosmonkey方法来获取库的整个配置。你也可以在启动应用程序后,通过调用/chaosmonkey/disable方法,禁用chaos monkey。此处列出了可用端点的完整列表:https://codecentric.github.io/chaos-monkey-spring-boot/2.0.0-SNAPSHOT/#endpoints。

5.运行应用程序

所有示例微服务都在MySQL中存储数据。因此,第一步是使用Docker镜像在本地运行MySQL数据库。下面显示的Docker命令还会创建具有密码的数据库和用户。

$ docker run -d --name mysql -e MYSQL_DATABASE=chaos -e MYSQL_USER=chaos -e MYSQL_PASSWORD=chaos123 -e MYSQL_ROOT_PASSWORD=123456 -p 33306:3306 mysql

在运行所有示例应用程序之后,所有微服务都在两个实例中使用不同端口,我们的环境如下图所示。

应用程序启动期间,您将在日志中看到以下信息。

我们可以通过调用以下执行器端点来检查每个运行的应用程序实例的Chaos Monkey配置设置。

6.测试系统

出于测试目的,我使用了流行的性能测试库--Gatling。它创建了20个并发线程,每个线程通过order-service 的API网关公开调用500次POST /orders和GET /order/{id}方法。

class ApiGatlingSimulationTest extends Simulation {

 val scn = scenario("AddAndFindOrders").repeat(500, "n") {

       exec(

         http("AddOrder-API")

           .post("http://localhost:8090/order-service/orders")

           .header("Content-Type", "application/json")

           .body(StringBody("""{"productId":""" + Random.nextInt(20) + ""","customerId":""" + Random.nextInt(20) + ""","productsCount":1,"price":1000,"status":"NEW"}"""))

           .check(status.is(200),  jsonPath("$.id").saveAs("orderId"))

       ).pause(Duration.apply(5, TimeUnit.MILLISECONDS))

       .

       exec(

         http("GetOrder-API")

           .get("http://localhost:8090/order-service/orders/${orderId}")

           .check(status.is(200))

       )

 }

 setUp(scn.inject(atOnceUsers(20))).maxDuration(FiniteDuration.apply(10, "minutes"))

}

POST端点在OrderController 的 add(...)方法内部实现。它调用由OpenFeign客户端公开的customer-service和product-service使用的查找方法。如果客户有足够的资金且库存中仍有产品,则它接受订单并使用PUT方法对客户和产品进行更改。下面是Gatling性能测试测试的两种方法的实现。

@RestController

@RequestMapping("/orders")

public class OrderController {

   @Autowired

   OrderRepository repository;

   @Autowired

   CustomerClient customerClient;

   @Autowired

   ProductClient productClient;

   @PostMapping

   public Order add(@RequestBody Order order) {

       Product product = productClient.findById(order.getProductId());

       Customer customer = customerClient.findById(order.getCustomerId());

       int totalPrice = order.getProductsCount() * product.getPrice();

       if (customer != null && customer.getAvailableFunds() >= totalPrice && product.getCount() >= order.getProductsCount()) {

           order.setPrice(totalPrice);

           order.setStatus(OrderStatus.ACCEPTED);

           product.setCount(product.getCount() - order.getProductsCount());

           productClient.update(product);

           customer.setAvailableFunds(customer.getAvailableFunds() - totalPrice);

           customerClient.update(customer);

       } else {

           order.setStatus(OrderStatus.REJECTED);

       }

       return repository.save(order);

   }

   @GetMapping("/{id}")

   public Order findById(@PathVariable("id") Integer id) {

       Optional order = repository.findById(id);

       if (order.isPresent()) {

           Order o = order.get();

           Product product = productClient.findById(o.getProductId());

           o.setProductName(product.getName());

           Customer customer = customerClient.findById(o.getCustomerId());

           o.setCustomerName(customer.getName());

           return o;

       } else {

           return null;

       }

   }

   // ...

}

Chaos Monkey将随机延迟设置在1000到10000毫秒之间(如步骤3所示)。 在开始测试之前更改Feign和Ribbon客户端的默认超时非常重要。我决定设置readTimeout为5000毫秒。这将导致一些延迟的请求超时,而一些将请求成功(约50%-50%)。下面是Feign客户端的超时配置。

feign:

 client:

   config:

     default:

       connectTimeout: 5000

       readTimeout: 5000

 hystrix:

   enabled: false

这是API网关的功能区客户端超时配置。我们还更改了Hystrix的设置以禁用Zuul的断路器。

ribbon:

 ConnectTimeout: 5000

 ReadTimeout: 5000

hystrix:

 command:

   default:

     execution:

       isolation:

         thread:

           timeoutInMilliseconds: 15000

     fallback:

       enabled: false

     circuitBreaker:

       enabled: false

要启动Gatling性能测试,请转到performance-test目录和运行gradle loadTest命令。这是针对设置延迟攻击生成的结果。当然,我们可以通过设置Chaos Monkey的延迟值或Ribbon和Feign超时值来更改此结果。

这是具有平均响应时间的Gatling图。结果看起来不太好。但是,我们应该记住从order-service的单个POST方法调用product-service的两个方法和customer-service的两个方法。

下面是另一个Gatling结果图 - 这次它说明了时间轴上的错误和成功响应。Gatling在性能测试期间生成的所有HTML报告都可以在performance-test/build/gatling-results目录下找到

原文链接:https://piotrminkowski.wordpress.com/2018/05/23/chaos-monkey-for-spring-boot-microservices/

作者:Piotr Mińkowski

译者:xuli

推荐: SpringBoot WebFlux 入门案例

上一篇:Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

关注公众号

点击原文

springboot jar服务器运行后无法请求_Spring Boot微服务中Chaos Monkey的应用相关推荐

  1. springboot jar服务器运行后无法请求_Spring boot、微服务、OAuth、OpenID的爱恨情仇!...

    在本文中,我们学习如何使用Spring boot轻松配置和部署微服务,然后使用OAuth和OpenID保护它们. 在微服务体系架构中,其中较大的应用程序由多个较小的服务组成,每个服务都有自己的目标,它 ...

  2. springboot 添加拦截器之后中文乱码_spring boot 2.x 添加拦截器配置未生效的问题

    背景: 今天有一个需求需要拦截除登录相关请求以外的所有请求,并查看request 中是否包含指定的信息,而自然就想到了使用拦截器就可以轻松实现 编写拦截器,获取请求头信息中的test,并打印出来 @C ...

  3. 「问题解决」java web项目打成jar包运行后工具类无法读取模板文件的解决方法

    介绍语 本号主要是Java常用关键技术点,通用工具类的分享:以及springboot+springcloud+Mybatisplus+druid+mysql+redis+swagger+maven+d ...

  4. xjar 对Spring-Boot JAR 包加密运行工具

    Xjar 介绍 Spring Boot JAR 安全加密运行工具,同时支持的原生JAR. 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码 ...

  5. jar容器部署成功无法访问_Spring Boot 应用程序五种部署方式

    翻译自 Deploying Spring Boot Applications[1] 原作者 Murat Artim[2] 可以使用各种方法将 Spring Boot 应用程序部署到生产系统中.在本文中 ...

  6. springboot netty给特定客户端推送_Spring Boot 又升级了?2.0 你搞懂了吗?!

    [小宅按]作为知名互联网公司都在用的技术,Spring Boot 2.0 的更新引起了很大的关注,本文将分为三部分解读 2.0 的更新: 第一类,基础环境升级: 第二类,默认软件替换和优化: 第三类, ...

  7. springboot @datetimeformat 标注在参数上无效_Spring Boot 中必须掌握的 45 个注解

    点关注,不迷路:持续更新Java架构相关技术及资讯热文!!! 一.SpringBoot/spring @SpringBootApplication: 包含@Configuration.@EnableA ...

  8. java option请求_Spring boot处理OPTIONS请求

    一.现象 从fetch说起,用fetch构造一个POST请求. 1 fetch('http://127.0.0.1:8000/api/login', {2 method: "POST&quo ...

  9. hystrix 单独使用_Spring cloud微服务架构-Hystrix工作原理(微服务故障熔断)

    流程图 下图显示了通过Hystrix向服务依赖项请求时发生的情况: 以下各节将更详细地说明此流程: 1.构造一个HystrixCommand或HystrixObservableCommand对象 第一 ...

最新文章

  1. [vijos1234]口袋的天空最小生成树
  2. 期望dp ---- E. Vasya and Magic Matrix(二维转一维+前缀和优化的期望dp)
  3. Windows 安装 pytorch3d
  4. 如何使用悲观锁定修复乐观锁定竞争条件
  5. Python 数据分析三剑客之 Pandas(七):合并数据集
  6. 《开源思索集》一Source Code + X
  7. 视频编解码(五):解码器驱动代码理解
  8. Java中简单Http请求
  9. mysql gitd 数据结构同步失败_mysql 5.7 gtid主从同步错误修复
  10. kindle mysql_MySQL(二) MySQL基本操作
  11. switch 大气层双系统 进入破解系统 及安装nsp nsz 格式教程
  12. 解决GUT GUI中文乱码问题
  13. 微信设置文字大小影响网页布局
  14. 基于STM32的RGB调色器——STM32程序和Qt上位机全开源
  15. overleaf使用指南以及最基本LaTeX语法回顾
  16. Apache虚拟主机配置详解
  17. 苹果cmsv10好看的七色中文二开视频免费模板
  18. IndexedDB 实践
  19. LVS(DR)+Keepalive高可用+Zabbix监控脑裂
  20. 被问麻了,Spring 如何处理循环依赖?

热门文章

  1. 最新动态,电信屏蔽Godaddy部分DNS服务
  2. 缺乏管理思想的管理软件是没有灵魂的
  3. MySQL binlog日志
  4. mpls企业组网怎么样?
  5. 找不到网卡eth0的解决方法
  6. 部署了OpenStack就拥有了云平台?还差很远呢
  7. 大数据与智能算法(三-集疏运应用)-SMU在线学习笔记
  8. PostgreSQL非交互式键入密码
  9. 优化数据库大幅度提高Oracle的性能
  10. 【Django】安装及配置