javascript
springboot jar服务器运行后无法请求_Spring Boot微服务中Chaos Monkey的应用
有多少人從未在生產環境中遇到系統崩潰或故障?當然,你們每個人遲早都會經歷它。如果我們無法避免失敗,那么解決方案似乎是將我們的系統維持在永久性故障狀態。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的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公文字体字号标准2020_党政机关公文格
- 下一篇: wpf 动画_WPF中监视动画进度