对于每个服务网格框架来说,处理服务间通信中的通信故障的能力是绝对必要的。它包括超时和HTTP错误代码的处理。在本文中,我将展示如何使用Istio配置重试和熔断机制。与之前Kubernetes上使用Istio Service Mesh的文章相同,我们将分析在Kubernetes上部署的两个简单Spring Boot应用程序之间的通信。但是,我们将讨论更高级的主题,而不是非常基本的示例。
示例为了演示Istio和Spring Boot的用法,我在GitHub上创建了带有两个示例应用程序的存储库:callme-service和caller-service。该存储库的地址为https://github.com/piomin/sample-istio-services.git。前言中已经提到与Istio有关服务网格的第一篇文章使用了相同的存储库。
架构我们的示例系统的体系结构与上一篇文章非常相似。但是,存在一些差异。我们不是在使用Istio组件注入故障或延迟,而是直接在源代码内部的应用程序上注入错误或延迟。为什么?现在,我们将能够直接按照为callme-service创建的规则进行处理,而不必像以前那样在客户端进行处理。另外,我们正在运行两个callme-service应用程序版本v2实例,以测试熔断器对相同服务(或相同Deployment)实例的作用如何。下图说明了当前描述的体系结构。
Spring Boot 应用我们从示例应用程序的实现开始。应用程序callme-service公开了两个端点,这些端点返回有关版本和实例ID的信息。端点GET /ping-with-random-error将HTTP 504错误代码设置为对约50%请求的响应。端点GET /ping-with-random-delay返回的响应具有0s和3s之间的随机延迟。这是callme-service端 @RestController的实现。
@RestController@RequestMapping("/callme")public class CallmeController { private static final Logger LOGGER = LoggerFactory.getLogger(CallmeController.class); private static final String INSTANCE_ID = UUID.randomUUID().toString(); private Random random = new Random(); @Autowired BuildProperties buildProperties; @Value("${VERSION}") private String version; @GetMapping("/ping-with-random-error") public ResponseEntity<String> pingWithRandomError() { int r = random.nextInt(100); if (r % 2 == 0) { LOGGER.info("Ping with random error: name={}, version={}, random={}, httpCode={}", buildProperties.getName(), version, r, HttpStatus.GATEWAY_TIMEOUT); return new ResponseEntity<>("Surprise " + INSTANCE_ID + " " + version, HttpStatus.GATEWAY_TIMEOUT); } else { LOGGER.info("Ping with random error: name={}, version={}, random={}, httpCode={}", buildProperties.getName(), version, r, HttpStatus.OK); return new ResponseEntity<>("I'm callme-service" + INSTANCE_ID + " " + version, HttpStatus.OK); } } @GetMapping("/ping-with-random-delay") public String pingWithRandomDelay() throws InterruptedException { int r = new Random().nextInt(3000); LOGGER.info("Ping with random delay: name={}, version={}, delay={}", buildProperties.getName(), version, r); Thread.sleep(r); return "I'm callme-service " + version; }}应用程序caller-service公开了两个GET端点。它使用RestTemplate来调用callme-service公开的相应GET端点。它还返回caller-service的版本,但是只有一个标有version = v1的应用程序的部署。
...