目录
1 泳道的概念和特性
1.1 背景
微服务架构下服务个数多、调用链路长,其中一个服务出问题会影响到整条链路。但QA提测往往需要同时测试一条链路上的多个服务,甚至是同时测试一个服务的多个演进版本。
提供稳定的环境和多服务/多版本同时测试变成了主要矛盾,通过泳道“Swimlane”能够得到解决。
测试过程中会遇到的问题
- 一个服务的多个需求同时测试,这个服务的多个分支需要抢占测试环境。
- 一个服务被大量的调用方依赖,这个服务在新功能测试时会影响调用方的测试。
1.2 什么是泳道
对服务调用链按需求进行分组,并实现逻辑、物理隔离,使得不同分组的服务调用链运行在互相隔离的机器上,互不影响。每一条调用链就好像游泳池中间的泳道。
一个环境内会有一条骨干链路(该环境的默认链路)和多条泳道。如图所示,泳道隔离出了一条调用边界:处于[泳道-1]内的服务B要调用服务C,若在[泳道-1]内部署了C服务,则B只能调用泳道内的C服务,而不能调用骨干链路或其他泳道的C服务;若在[泳道-1]内没有部署C服务,则流量会调回骨干链路。
优势:
- 并行测试。(因此可以根据测试需要,部署不同分支的服务分组,多个泳道并行,多个服务/多个版本可同时提测)
- 提供稳定的骨干链路。(保证整个测试流程始终能正常运行)
- 错误隔离。(泳道内的服务发生异常,不会影响其他泳道)
1.3 泳道的特性
泳道相当于提供了多条“请求的跑道”,理解泳道主要在于理解“流量跑到哪去了”:
- 泳道内如果没有部署被调用服务,流量会fallback到骨干
– 比如上图[泳道-2]中的B服务节点 调用了 [骨干链路]中的C服务节点
- 泳道内若存在被调用节点,那么流量是一定不会fallback的 (包括不可用的和禁用的)
– 比如上图[泳道-2]中的A服务节点 只会调用 [泳道-2]中的B服务节点,即使[泳道-2]中的B不可用,也是不会fallback的
- 骨干环境是一定不会调用到泳道内的
– 比如上图中绝逼不会有 从[骨干链路]到[泳道-2]的调用
- 泳道之间是一定不会互相调用的
– 比如上图中绝逼不会有 [泳道-1]与[泳道-2]之间的调用
1.4 泳道的价值
本质上,要解决环境稳定及并行测试的问题,我们提供多套环境也可以解决。但多套环境会带来成本的急剧上升:
- 硬件成本:比如部署3套测试环境,我们就能提供一套稳定的测试环境+2套分支测试环境,支持一个服务的2个需求同时测试。这意味着需要有3套完整的测试环境。在泳道环境下,只有和被测需求相关的调用链上的服务才需要在泳道中额外部署,大部分服务不需要额外部署。而且需求测试完成后,泳道可以被回收。因而增加的成本较部署完整的测试环境要少的多。
- 运营成本:多套环境中运行的服务和依赖的数据是需要维护的。特别是数据,多套环境中的数据维护成本是巨大的。
站在研发人员的角度看:
1. 对于开发人员,在开发环境进行服务开发时
作为服务提供方,泳道可以保证服务的稳定,不受新版服务功能变更、功能出错及调试的影响;开发人员可以在自己的泳道中验证新版服务功能,任意暂停、调试代码而不会影响服务调用方。
作为服务调用方,泳道可以保证有稳定的服务提供方可用,不会受服务提供方经常发布变更导致服务不可用的影响。
2. 对于测试人员,在测试环境进行服务测试时
稳定的测试环境,主干部署的服务就是线上环境的版本,保证功能稳定可用。
并行测试的能力,多个需求可以并行测试,不需要抢占主干泳道,且多个并行测试的版本互不影响。
降低的沟通协调成本,当上下游服务一起联调时,需要协调整个调用链上的服务一起发布到测试环境,有了泳道,大家把互相依赖的服务都发布到同一个泳道即可,降低协调沟通成本。
3. 对于开发测试人员,在线上环境进行压测时
压测场景,线上压测时,为了保证压测效果且不影响线上服务,一般我们需要在线上环境的流量低峰期(一般是晚上10点到早上6点间)进行压测,有了泳道,借助泳道的隔离功能,我们就可以在白天进行压测,既保证服务间的隔离,能在工作时间进行压测,又能保证压测效果。
故障隔离场景,一些重要业务,对下游服务有依赖的,不希望下游服务受其他调用方的影响,这种场景下,可以为重要业务及其依赖的关键链路上的服务,进行泳道部署,隔离重要业务的调用链路不受其他业务影响。
2 feign的概念和简单使用
2.1 feign背景
在微服务背景下,多个服务之间是可以采用http通信,也就是restTemplate进行互相访问,但是这种方式对参数传递和使用都不是很方便,所以弃用此方式,采用feign进行服务之间的调用,可以简化调用流程,真正感觉到是在同一个项目中调用另一个类的方法的欢快感。
2.2 feign使用说明
Feign是Netflix开发的声明式、模板化的HTTP客户端,Feign可以帮助我们更快捷、优雅地调用HTTP API。
在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Spring Cloud Feign具备可插拔的注解支持,支持Feign注解、JAX-RS注解和Spring MVC的注解。
2.3 feign使用示例
(1)引入feign依赖支持(还需要其它的依赖,此处不列出)
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)创建一个Feign接口,并添加@FeignClient注解
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
}
(3)修改Controller代码,让其调用Feign接口
@RestController
public class MovieController {
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
return this.userFeignClient.findById(id);
}
}
(4)修改启动类,为其添加@EnableFeignClients注解
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerMovieApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieApplication.class, args);
}
}