微服务Spring Cloud Alibaba之我见
作者:Piotr Mińkowski,"Mastering Spring Cloud"一书作者
原文链接:
https://dzone.com/articles/microservices-with-spring-cloud-alibaba
如果你正在寻找一个Spring Cloud Netflix的替代方案,建议可以看下这篇和Spring Cloud Alibaba相关的文章。
前段时间,Spring Cloud在其官方博客宣布:阿里巴巴开源 Spring Cloud Alibaba,发布了首个预览版本0.2.0,并已和Spring Boot 2.0兼容,该项目支持基于阿里巴巴的开源组件和阿里云云产品,构建微服务体系。
这个项目看起来非常有趣,并且目前已成为SpringCloud孵化器仓库中最流行的项目之一。
Spring Cloud还支持另一个流行的阿里巴巴开源组件--Sentinel,他负责流量控制、并发、断路和负载保护。
我们的演示示例由三个微服务和API网关组成,非常类似于我之前写过的一篇文章《基于SpringBoot 2.0、Eureka和Spring Cloud搭建微服务的快速指南》中所描述的体系结构。
唯一的区别在于,用于配置管理和服务发现的工具。微服务调用服务暴露的接口,而department-service调用employee-service暴露的接口,使用OpenFeign客户端实现了服务间的通信。整个系统的复杂性隐藏在使用NetflixZuul实现的API网关之后。
"SpringCloud Alibaba是否可以替代SpringCloud Netflix?"
答案是肯定的,但不是全部。Spring Cloud Alibaba仍然与Ribbon集成,Ribbon是基于服务发现的负载平衡。在这种情况下,Netflix Eureka很有可能被Nacos替换掉。
Nacos(DynamicNaming and Configuration Service)是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台易于使用的平台,按照这个定义,您可以使用Nacos用于:
服务发现-可以注册您的微服务,并通过DNS或HTTP接口发现其他微服务。它还为注册服务提供实时健康检查。
分布式配置--Nacos提供的动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。事实上,您也可以使用它来替换Spring Cloud Config Server。
动态DNS--它支持加权路由,使得更容易实现中间层负载平衡、灵活的路由策略、流控制和简单的DNS解析服务。
Spring Cloud还支持另一个流行的阿里巴巴开源组件--Sentinel,他负责流量控制、并发、断路和负载保护。
我们的演示示例由三个微服务和API网关组成,非常类似于我之前写过的一篇文章《基于SpringBoot 2.0、Eureka和Spring Cloud搭建微服务的快速指南》中所描述的体系结构。唯一的区别在于,用于配置管理和服务发现的工具。
微服务调用服务暴露的接口,而department-service调用employee-service暴露的接口,使用OpenFeign客户端实现了服务间的通信。整个系统的复杂性隐藏在使用NetflixZuul实现的API网关之后。
1. 运行Nacos服务器
您可以在Windows和Linux系统上运行Nacos。首先,您应该下载GitHub上提供的最新稳定版本。解压缩之后,必须通过执行以下命令以单机模式运行它:
cmd nacos/bin/startup.cmd -m standalone
默认情况下,Nacos从端口8848开始。它提供/nacos/v1下的HTTP API,以及地址http://localhost:8848/nacos下的管理web控制台。如果查看日志,您会发现它只是一个使用SpringFramework编写的应用程序。
2. 依赖关系
正如我前面提到的,Spring Cloud Alibaba仍然处于孵化阶段,因此它不包含在SpringCloud Release Train中。这就是为什么我们需要在pom.xml的依赖关系管理部分中包括一个针对阿里巴巴的特殊BOM。我们还将使用Spring Cloud的最新稳定版本,即现在的Finchley.SR2。
org.springframework.cloud spring-cloud-dependencies Finchley.SR2 pom import org.springframework.cloud spring-cloud-alibaba-dependencies 0.2.0.RELEASE pom import
Spring Cloud Alibaba为当前支持的组件提供了三个启动器。这些是使用Nacos进行服务发现的spring-cloud-starter-alibaba-nacos-discovery、用于分布式配置的spring-cloud-starter-alibaba-nacos-config以及用于限流降级的spring-cloud-starter-alibaba-sentinel。
org.springframework.cloud spring-cloud-starter-alibaba-nacos- discovery org.springframework.cloud spring-cloud-starter-alibaba-nacos- config org.springframework.cloud spring-cloud-starter-alibaba-sentinel
3. 使用Nacos启用分布式配置
为了启用Nacos的配置管理,我们只需要引入一个starter,即spring-cloud-starter-alibaba-nacos-config。它不提供Nacos服务器的自动配置地址,因此我们需要为bootstrap.yml文件中的应用程序显式地设置它。
spring:application:name: employee-servicecloud:nacos: config: server-addr: localhost:8848
我们的应用程序尝试与Nacos连接,并获取在文件中提供的与属性spring.application.name的值同名的配置。目前,Spring Cloud Alibaba只支持.properties文件,因此我们需要在文件employee-service.properties内创建配置。
Nacos提供了创建和管理配置属性的优雅方式。我们可以使用网络管理控制台来做到这一点。下面图片中可见的字段Data ID实际上是配置文件的名称。配置属性列表应该放在Configuration Content字段中。
好消息是,它在修改了Nacos之后会动态刷新应用程序配置。在应用程序中,您唯一要做的就是注释应该用@RefreshScope或@ConfigurationProperties刷新的bean。
现在,让我们考虑以下情况。我们将稍微修改一下配置,以添加一些带有测试数据的属性,如下所示。
这是我们存储库bean的实现。它将带有前缀repository.employees的所有配置属性注入到employees列表中。
@Repository@ConfigurationProperties(prefix = "repository")public class EmployeeRepository {private List < Employee > employees = new ArrayList < > ();public List < Employee > getEmployees() {return employees;}public void setEmployees(List < Employee > employees) {this.employees = employees;}public Employee add(Employee employee) {employee.setId((long)(employees.size() + 1));employees.add(employee);return employee;}public Employee findById(Long id) {Optional < Employee > employee = employees.stream().filter(a - > a.getId().equals(id)).findFirst();if (employee.isPresent())return employee.get();elsereturn null;}public List < Employee > findAll() {return employees;}public List < Employee > findByDepartment(Long departmentId) {return employees.stream().filter(a -> a.getDepartmentId().equals(departmentId)).collect(Collectors.toList());}public List < Employee > findByOrganization(Long organizationId) {return employees.stream().filter(a -> a.getOrganizationId().equals(organizationId)).collect(Collectors.toList());}}
现在,您可以更改一些属性值,如下图所示。然后,如果调用在端口8090(http://localhost:8090)上可用的employee-service,您应该会看到具有修改值的雇员的完整列表。
对于我们另外两个微服务,部门服务和组织服务,应该创建相同的配置属性。假设您已经完成了,那么您应该在Nacos上具有以下配置条目。
4. 使用Nacos启用服务发现
要使用Nacos实现服务发现,首先需要包括starterspring-cloud-starter-alibaba-nacos-discovery。配置服务器也是如此;您还需要在bootstrap.yml文件中设置Nacos服务器的地址。
spring: application: name: employee-service cloud: nacos: discovery: server-addr: localhost:8848
最后一步是通过使用@EnableDiscoveryClient注释主类来为应用程序启用发现客户端。
@SpringBootApplication@EnableDiscoveryClient@EnableSwagger2public class EmployeeApplication {public static void main(String[] args) {SpringApplication.run(EmployeeApplication.class, args);}}
如果您为所有的微服务提供相同的实现并运行它们,您将在Nacos Web控制台中看到以下已注册的应用程序列表。
5. 服务间的通信
微服务之间的通信是使用标准Spring Cloud组件实现:RestTemplate或OpenFeign客户端。
默认情况下,负载平衡由Ribbon客户端实现。与Spring Cloud Netflix相比,唯一的区别之前的服务注册中心使用的是 SpringCloud Netflix。下面是负责与employee service公开的端点GET/department/{departmentId} 通信的 FeignClient 客户端在部门服务中集成的实现。
@FeignClient(name = "employee-service")public interface EmployeeClient {@GetMapping("/department/{departmentId}")List < Employee > findByDepartment(@PathVariable("departmentId") Long departmentId);}
不要忘记为Spring Boot应用程序启用Feign客户端。
@SpringBootApplication@EnableDiscoveryClient@EnableFeignClients@EnableSwagger2public class DepartmentApplication {public static void main(String[] args) {SpringApplication.run(DepartmentApplication.class, args);}}
我们还应该运行多个employee-service实例,以便在客户端测试负载均衡。在此之前,我们可以通过在Nacos上存储的配置中将属性server.port设置为0,来启用端口号的动态生成。
现在,我们可以使用相同的配置设置运行单个服务的许多实例,而不必担心单个微服务的端口号冲突。让我们扩大employee-service实例的数量。
如果希望测试服务间通信,可以调用以下方法,这些方法使用OpenFeign客户端调用其他微服务公开的端点:GET /organization/{organizationId}/with-employees
from department-service
, and GET /{id}/with-departments
, GET /{id}/with-departments-and-employees
, GET /{id}/with-employees
from organization-service
.
6. 运行API网关
现在是运行体系结构中最后一个组件--API网关。它建在Spring Cloud Netflix Zuul之上,同样使用Nacos作为发现和配置服务器。
org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.cloud spring-cloud-starter-alibaba-nacos-config org.springframework.cloud spring-cloud-starter-netflix-zuul
在包括所需的依赖项之后,我们需要为应用程序启用Zuul代理和发现客户端。
@SpringBootApplication@EnableDiscoveryClient@EnableZuulProxy@EnableSwagger2public class ProxyApplication {public static void main(String[] args) {SpringApplication.run(ProxyApplication.class, args);}}
以下是为我们的三个示例微服务定义的Zuul路由的配置:
zuul: routes: department: path: /department/** serviceId: department-serviceemployee: path: /employee/** serviceId: employee-serviceorganization: path: /organization/** serviceId: organization-service
在运行网关之后,它为所有定义的微服务公开的API公开了Swagger2规范。假设您已经在端口8080上运行了它,那么您可以在地址http://localhost:8080/swagger-ui.html下访问它。由于这个原因,您可以从一个单独的位置调用方法。
7. 结论
示例应用程序的源代码可以在GitHub上通过阿里巴巴分支中的sample-spring-microservices-new获得。
本文的主要目的是展示如何使用用于服务发现和配置管理的AlibabaNacos替换一些流行的SpringCloud组件。
SpringCloud Alibaba项目处于开发的早期阶段,所以我们可能在不久的将来期待一些新的有趣的特性。您也可以在此处Spring Cloud Alibaba GitHub站点上找到其他一些示例。