Spring Cloud 微服务架构介绍
Spring Cloud 的目标是为 Spring 开发人员提供一套易于使用的工具来构建分布式系统. 它主要通过包装其他实现堆栈, 从 Netflix OSS 堆栈开始. 然后, 这些堆栈将通过基于注释的配置, Java 配置和基于模板的编程的熟悉工具进行消耗. 我们来看几个 Spring Cloud 的组件.
Spring Cloud 配置服务器
Spring Cloud Config Server(配置服务器)提供了可水平扩展的集中式配置服务. 它使用可插拔存储库层作为其数据存储, 当前支持本地存储, Git 和 Subversion. 通过利用版本控制系统作为配置存储, 开发人员可以轻松地对配置更改进行版本化和审核.
配置表示为 Java 属性或 YAML 文件. Config Server 将这些文件合并到环境对象中, 将对 Spring 属性和配置文件的理解模型呈现为 REST API. 这个 REST API 可以直接由任何应用程序查询来获取配置数据, 但可以将智能客户端绑定添加到 Spring Boot 应用程序中, 这些应用程序将自动协调任何本地配置与配置服务器接收的配置.
Spring Cloud 总线
Spring Cloud Config Server 是一种强大的机制, 用于在一组应用程序实例中一致地分发配置. 然而, 就目前而言, 我们目前仅限于在应用程序启动时更新此类配置. 将属性的新值推送到 Git 后, 我们需要手动重新启动每个应用程序流程以获取新值. 我们想要的是在不重新启动的情况下刷新应用程序配置的功能.
Spring Cloud Bus 为您的应用程序实例添加一个管理背板. 它目前被实现为客户端绑定到一组 AMQP 交换和队列, 但这个后端也被设计为可插拔. Cloud Bus 为您的应用程序添加了更多的管理端点. 在图中, 我们看到上 POST 到 App A 的 / bus/refresh 端点的一个请求, 由此获得 Git 的 greeting 属性新值. 此请求触发三个事件:
1. App A 从配置服务器请求最新的配置. 使用 @RefreshScope 注释的任何 Spring Bean 将重新初始化到新配置.
2. 应用程序 A 向 AMQP 交换机发送消息, 指示它已经接收到刷新事件.
3. 通过聆听适当的 AMQP 队列参与 Cloud Bus 的应用程序 B 和 C 以与 App A 相同的方式接收消息并更新其配置. 现在我们可以刷新应用程序的配置而无需重新启动.
Spring Cloud Netflix
Spring Cloud Netflix 提供了几个 Netflix 组件的封装: Eureka,Ribbon,Hystrix 和 Zuul. 下面依次讨论这些.
Eureka 是一个有弹性的服务注册表实现. 服务注册表是用于服务发现的一种机制
Spring Cloud Netflix 通过简单地将 spring-cloud-starter-eureka-server 依赖关系添加到 Spring Boot 应用程序, 然后用 @EnableEurekaServer 来标注该应用程序的配置类.
应用程序可以通过添加 spring-cloud-starter-eureka 依赖关系并注释 @EnableDiscoveryClient 其配置类来参与服务发现. 此注释提供了将 DiscoveryClient 正确配置的实例注入任何 Spring Bean 的功能. DiscoveryClient 是服务发现的抽象, 在这种情况下恰好是通过 Eureka 实现的, 但也可以提供与其他候选技术栈 (如 Consul) 的集成. DiscoveryClient 能够提供位置信息(例如网络地址), 并提供根据服务逻辑标识符在 Eureka 注册服务实例的其它元数据.
Eureka 提供的负载平衡算法只限于轮循. Ribbon 提供了一个复杂的客户端 IPC 库, 具有可配置的负载平衡和容错能力. 可以从 Eureka 服务器获取的动态服务器列表导出轮询列表. Spring Cloud Netflix 通过向 Spring Boot 添加 spring-cloud-starter-ribbonSpring 添加依赖关系来提供轮询 Ribbon 的集成. 这个额外的库也提供了将 LoadBalancerClient 正确配置的实例注入任何 Spring Bean 的能力, 这将使客户端获得负载平衡(图 4).
除了其他任务之外, 使用 Ribbon 还可以实现额外的负载平衡算法, 例如可用性过滤, 加权响应时间和可用性区域密切关系.
Spring Cloud Netflix 将通过自动创建一个 RestTemplate 的可以注入到任何 Spring Bean 中的 Ribbon 增强实例进一步增强 Spring 开发人员对 Ribbon 的使用. 开发人员可以简单地将提供 URL 中的逻辑服务名称传递给 RestTemplate:
- @Autowired
- @LoadBalanced
- private RestTemplate restTemplate;
- @RequestMapping("/")
- public String consume() {
- ProducerResponse response = restTemplate.getForObject("http://producer", ProducerResponse.class);
- return String.format("{"value": %s}", response.getValue());
- }
Hystrix 为分布式系统提供了常见的容错模式的实现(如断路器 和隔板). 断路器通常被实现为状态机, 其示例在图 5 中找到.
断路器可以放置在服务和其远程依赖之间. 如果电路关闭, 则对依赖关系的调用正常通过. 如果呼叫失败, 则计算该失败. 如果故障次数在可配置的时间段内达到阈值, 则电路跳闸以打开. 在打开状态下, 调用不再发送到依赖项, 并且生成的行为是可自定义的(抛出异常, 返回伪数据, 调用不同的依赖关系等).
定期地, 状态机将转换到 "半开" 状态, 以确定依赖关系是否再次健康. 在这种状态下, 请求再次通过. 如果请求成功, 机器将返回到关闭状态. 如果请求失败, 机器将转回到打开状态.
Spring Cloud 应用程序可以通过添加 spring-cloud-starter-hystrix 依赖关系并注释 @EnableCircuitBreaker 其配置类来利用 Hystrix. 然后, 您可以通过以下方式对任何 Spring Bean 方法用 @HystrixCommand 添加断路器:
- @HystrixCommand(fallbackMethod = "getProducerFallback")
- public ProducerResponse getValue() {
- return restTemplate.getForObject("http://producer", ProducerResponse.class);
- }
此示例指定一个名为 getProducerFallback 的后备方法. 当断路器处于断开状态时, 这种方法将被用来代替 getValue:
- private ProducerResponse getProducerFallback() {
- return new ProducerResponse(42);
- }
除了提供状态机行为外, Hystrix 还会从每个断路器发出一个指标流, 提供重要的遥测, 如请求测量, 响应时间直方图以及成功, 失败和短路请求的数量(图 6).
Zuul 处理 Netflix 边缘服务的所有传入请求. 它与其他 Netflix 组件 (如 Ribbon 和 Hystrix) 结合使用, 为 Netflix 服务提供灵活而有弹性的路由选择层.
Netflix 使用动态加载到 Zuul 中的过滤器执行以下功能:
1. 身份验证和安全性: 识别每个资源的身份验证要求, 并拒绝不满足他们的请求.
2. 洞察和监控: 跟踪边缘的有意义的数据和统计数据, 以便我们准确地了解生产情况.
3. 动态路由: 根据需要将请求动态路由到不同的后端集群.
4. 压力测试: 逐渐增加到集群的流量, 以衡量性能.
5. 卸载: 为每种类型的请求分配容量并删除超过限制的请求.
6. 静态响应处理: 直接在边缘构建一些响应, 而不是将它们转发到内部集群.
7. 多区域弹性: 跨 AWS 地区的路由请求, 以使我们的 ELB 使用多样化, 并使我们的边缘更接近我们的成员.
此外, Netflix 利用 Zuul 的功能, 通过 canary 版本执行外部路由和压力测试.
对于一个 UI 应用程序想要代理对一个或多个后端服务的呼叫等非常常见的用例, Spring Cloud 已经创建了一个嵌入式的 Zuul 代理, 以简化开发. 该功能便于用户前端对其所需的后端服务进行代理, 避免了对所有后端单独管理 CORS(跨原始资源共享)和身份验证问题的需求. Zuul 代理是 API 网关模式的一个重要应用(图 7)
Spring Cloud 增强了嵌入式 Zuul 代理, 提供文件上传的自动处理功能, 并且通过添加 Spring Cloud Security 可以轻松提供 OAuth2 SSO, 以及向下游服务提供令牌继承. Zuul 使用 Ribbon 作为其客户端和所有出站请求的负载均衡器. Ribbon 的动态服务器列表通常由 Eureka 导入, 但 Spring Cloud 能够从其他来源导入.
进入微服务世界使我们直接进入分布式系统的世界, 分布式系统并不总是 "正常工作", 所以我们必须假设我们系统的组件的行为和位置往往会是以不可预知的方式不断变化.
来源: http://www.jianshu.com/p/dbe6f23790b3