概述
Spring Cloud中文文档:https://www.springcloud.cc/spring-reference.html;需要注意的是,Spring Cloud的版本号是以伦敦地铁站名字命名,版本号按字母排序,标记GA的版本为稳定版。
什么是微服务?
- 简单说就是把应用程序细分成一个个的独立服务
- 服务被模块化,单一化,每一个服务都可以独立启动或销毁
- 可以根据各个服务的需求选择最适合自己的开发语言和环境。
- 让开发更高效,每一个微服务一个小团队就可以开发
- 更安全,每一个微服务放在不同的环境里,且有备用环境。
微服务有哪些难题?
- 用户如何访问我们的微服务?(网关API解决如zuul)
- 服务之间如何通信?(如Apache的Dubbo)
- 怎么管理这些服务?(Zookeeper等)
- 怎么制止雪崩,熔断机制?(Hystrix等)
现在的解决方案
-
Spring Cloud NetFlix 一站式解决方案(已经停更)
- zuul API网关
- feign http通信方式,同步,阻塞
- Eureka 服务注册发现
- Hystrix 熔断机制
Spring Cloud20年已经开始移除相关的Netflix OSS组件
-
Apache Dubbo Zookeeper 半自动的,只能解决通信和注册中心的问题,其他两个问题需要求助别的技术(Dubbo停更5年重启)
- zuul等 API网关
- Dubbo 最成熟的通信解决方案
- Zookeeper 服务注册发现
- Hystrix等 熔断机制
-
Spring Cloud Alibaba 最新的一站式解决方案,简单易用,19年第三季度才推出的。
什么是Spring Cloud?
- 为了解决微服务问题所形成的生态环境,提供微服务的全家桶
- 整合了各个经得住考验的,稳定的解决方案,将其整合为SpringBoot风格,易使用,易维护。
- 依赖于SpringBoot,SpringBoot专注于开发单个微服务,SpringCloud关注协调管理这些微服务。
- 主要提供配置管理,熔断器,路由,服务发现,微代理,事件总线,全局锁,分布式会话等服务
微服务调用流程
所有的组件服务一般都需要向注册中心(Eureka)进行服务注册;微服务的配置一般都统一由配置中心(config)进行管理。
常见的服务调用流程:
1、外部或者内部的非Spring Cloud项目都统一通过API网关(Zuul)来访问内部服务.
2、网关(Zuul)接收到请求后,从注册中心(Eureka)获取可用服务;
3、可用服务列表经由Ribbon进行均衡负载后,分发到后端的具体服务器;
4、微服务之间通过Feign进行通信处理业务、微服务的统一配置由config server管理;
5、Hystrix负责处理服务调用超时熔断;
6、Turbine监控服务间的调用和熔断相关指标。
使用
Spring Cloud Netflix
[Spring Cloud Netflix] (https://www.springcloud.cc/spring-cloud-greenwich.html#_spring_cloud_netflix)
使用一些简单的批注,您可以快速启用和配置应用程序内部的通用模式,并使用经过测试的Netflix组件构建大型分布式系统。提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)。
Eureka
如何运行Eureka服务器?
要将Eureka服务器包含在您的项目中,请使用启动器,其组ID为org.springframework.cloud
,工件ID为spring-cloud-starter-netflix-eureka-server
。以下示例显示了最小的Eureka服务器:
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
如果您的项目已经使用Thymeleaf作为模板引擎,则Eureka服务器的Freemarker模板可能无法正确加载。在这种情况下,必须手动配置模板加载器:application.yml。
spring:
freemarker:
template-loader-path: classpath:/templates/
prefer-file-system-access: false
向Eureka注册
当客户端向Eureka注册时,它会提供有关其自身的元数据-例如主机,端口,运行状况指示器URL,主页和其他详细信息。Eureka从属于服务的每个实例接收心跳消息。如果心跳在可配置的时间表上进行故障转移,则通常会将实例从注册表中删除。
以下示例显示了最小的Eureka客户端应用程序:
@SpringBootApplication
EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
请注意,前面的示例显示了普通的Spring Boot应用程序。通过在类路径上使用spring-cloud-starter-netflix-eureka-client
,您的应用程序将自动在Eureka服务器中注册。如下例所示,需要进行配置才能找到Eureka服务器:
application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
Zuul
路由是微服务架构不可或缺的一部分。例如,/
可能被映射到您的web应用程序,/api/users
被映射到用户服务,/api/shop
被映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载平衡器。Spring Cloud Greenwich 中文文档 参考手册 中文版
**包含它:**请使用组ID为org.springframework.cloud
和工件ID为spring-cloud-starter-netflix-zuul
的启动程序。
**启动它:**用@EnableZuulProxy
注释Spring Boot主类。这样做会导致将本地呼叫转发到适当的服务。按照约定,ID为users
的服务从位于/users
的代理接收请求(前缀被去除)。代理使用Ribbon来定位要通过发现转发到的实例。所有请求均在hystrix命令中执行,因此失败以Hystrix指标显示。一旦电路断开,代理就不会尝试与服务联系。
**适用它:**要增加或更改代理路由,可以添加外部配置,如下所示:
application.yml。
zuul:
routes:
users: /myusers/**
前面的示例意味着对/myusers
的HTTP调用被转发到users
服务(例如,/myusers/101
被转发到/101
)。
要对路由进行更细粒度的控制,可以分别指定路径和serviceId,如下所示:
application.yml。
zuul:
routes:
users:
path: /myusers/**
serviceId: users_service
前面的示例意味着对/myusers
的HTTP调用将转发到users_service
服务。路由必须具有可以指定为蚂蚁样式模式的path
,因此/myusers/*
仅匹配一个级别,而/myusers/**
则分层匹配。
Feign
Feign是声明性的web服务客户端。它使编写web服务客户端更加容易。要使用Feign,请创建一个接口并对其进行注释。它具有可插入的注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。
**包含它:**要将Feign包含在您的项目中,请将启动器与组org.springframework.cloud
和工件ID spring-cloud-starter-openfeign
一起使用。
启动它:
示例spring boot应用
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
使用它:
StoreClient.java。
@FeignClient("stores")
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
在@FeignClient
批注中,字符串值(上面的“ stores”)是一个任意的客户端名称,用于创建Ribbon负载均衡器(请参见下面的Ribbon support的详细信息)。您还可以使用url
属性(绝对值或仅是主机名)来指定URL。在应用程序上下文中,bean的名称是接口的标准名称。要指定自己的别名值,可以使用@FeignClient
批注的qualifier
值。
Ribbon
Ribbon是一种客户端负载平衡器,可让您对HTTP和TCP客户端的行为进行大量控制。Feign已使用Ribbon,因此,如果使用@FeignClient
,则本节也适用。
Ribbon中的中心概念是指定客户的概念。每个负载均衡器都是组件的一部分,这些组件可以一起工作以按需联系远程服务器,并且该组件具有您作为应用程序开发人员提供的名称(例如,使用@FeignClient
批注)。根据需要,Spring Cloud通过使用RibbonClientConfiguration
为每个命名的客户端创建一个新的集合作为ApplicationContext
。其中包含ILoadBalancer
,RestClient
和ServerListFilter
。
**包含它:**要将Ribbon包含在您的项目中,请使用起始者,其组ID为org.springframework.cloud
,工件ID为spring-cloud-starter-netflix-ribbon
。
自定义Ribbon客户端
您可以使用<client>.ribbon.*
中的外部属性来配置Ribbon客户端的某些位,这与本地使用Netflix API相似,不同之处在于可以使用Spring Boot配置文件。可以将本机选项检查为CommonClientConfigKey
(功能区核心的一部分)中的静态字段。
Spring Cloud还允许您通过使用@RibbonClient
声明其他配置(在RibbonClientConfiguration
之上)来完全控制客户端,如以下示例所示:
@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}
在这种情况下,客户端由RibbonClientConfiguration
中已有的组件以及CustomConfiguration
中的任何组件组成(其中后者通常会覆盖前者)。
Hystrix
Netflix创建了一个名为Hystrix的库,该库实现了断路器模式。在微服务架构中,通常有多个服务调用层,如以下示例所示:
图 Hystrix后备可防止级联故障
较低级别的服务中的服务故障可能会导致级联故障,直至用户。在metrics.rollingStats.timeInMilliseconds
定义的滚动窗口中,当对特定服务的调用超过circuitBreaker.requestVolumeThreshold
(默认:20个请求)并且失败百分比大于circuitBreaker.errorThresholdPercentage
(默认:> 50%)时(默认:10秒) ),则电路断开并且无法进行呼叫。在错误和断路的情况下,开发人员可以提供备用功能。
开路可停止级联故障,并让不堪重负的服务时间得以恢复。后备可以是另一个受Hystrix保护的呼叫,静态数据或合理的空值。可以将回退链接在一起,以便第一个回退进行其他业务调用,然后回退到静态数据。
**包含它:**要将Hystrix包含在您的项目中,请使用起始者,其组ID为org.springframework.cloud
,工件ID为spring-cloud-starter-netflix-hystrix
以下示例显示了具有Hystrix断路器的最小Eureka服务器:
@SpringBootApplication
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
@Component
public class StoreIntegration {
@HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
}
public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}
@HystrixCommand
由一个名为“ javanica ”的Netflix contrib库提供。Spring Cloud将带有注释的Spring beans自动包装在与Hystrix断路器连接的代理中。断路器计算何时断开和闭合电路,以及在发生故障时应采取的措施。
要配置@HystrixCommand
,可以将commandProperties
属性与@HystrixProperty
批注一起使用。有关 更多详细信息,请参见 此处。有关 可用属性的详细信息,请参见Hystrix Wiki。
Hystrix超时和Ribbon客户
当使用包裹Ribbon客户端的Hystrix命令时,您要确保Hystrix超时配置为比配置的Ribbon超时更长,包括可能进行的任何重试。例如,如果您的Ribbon连接超时是一秒钟,并且Ribbon客户端可能重试了3次请求,则Hystrix超时应该稍微超过3秒。
Config
Spring Cloud Config为分布式系统中的外部化配置提供服务器端和客户端支持。使用Config Server,您可以在中心位置管理所有环境中应用程序的外部属性。客户端和服务器上的概念都与Spring Environment
和PropertySource
抽象映射相同,因此它们非常适合Spring应用程序,但可以与以任何语言运行的任何应用程序一起使用。在应用程序从开发人员到测试人员再到生产人员的整个部署过程中,您可以管理这些环境之间的配置,并确保应用程序具有它们迁移时所需的一切。服务器存储后端的默认实现使用git,因此它轻松支持带标签的配置环境版本,并且可以通过各种工具来访问这些内容来管理内容。添加替代实现并将其插入Spring配置很容易。
Config服务器
Spring Cloud Config服务器为外部配置(名称/值对或等效的YAML内容)提供了一个基于HTTP资源的API。通过使用@EnableConfigServer
批注,服务器可嵌入到Spring Boot应用程序中。因此,以下应用程序是配置服务器:
ConfigServer.java。
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
像所有Spring Boot应用程序一样,它默认在端口8080上运行,但是您可以通过各种方式将其切换到更传统的端口8888。最简单的方法也是设置默认配置存储库,方法是使用spring.config.name=configserver
(在Config Server jar中有configserver.yml
)启动它。另一种方法是使用您自己的application.properties
,如以下示例所示:
application.properties。
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
其中${user.home}/config-repo
是包含YAML和属性文件的git存储库。
客户端使用
要在应用程序中使用这些功能,您可以将其构建为依赖于spring-cloud-config-client的Spring Boot应用程序(例如,请参阅config-client或示例应用程序的测试用例)。添加依赖项最方便的方法是使用Spring Boot启动器org.springframework.cloud:spring-cloud-starter-config
。还有一个Maven用户的父pom和BOM(spring-cloud-starter-parent
),以及一个Gradle和Spring CLI用户的Spring IO版本管理属性文件。以下示例显示了典型的Maven配置:
pom.xml。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>{spring-boot-docs-version}</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>{spring-cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- repositories also needed for snapshots and milestones -->
现在,您可以创建一个标准的Spring Boot应用程序,例如以下HTTP服务器:
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
当此HTTP服务器运行时,它将从端口8888上的默认本地配置服务器(如果正在运行)中获取外部配置。要修改启动行为,可以使用bootstrap.properties
(类似于application.properties
,但用于应用程序上下文的引导阶段),如以下示例所示:
spring.cloud.config.uri: http://myconfigserver.com
默认情况下,如果未设置应用程序名称,将使用application
。要修改名称,可以将以下属性添加到bootstrap.properties
文件中:
spring.application.name: myapp
设置属性${spring.application.name}
时,请勿在您的应用名称前加上保留字application-
,以防止解析正确的属性源时出现问题。
引导程序属性在/env
端点中显示为高优先级属性源,如以下示例所示。
$ curl localhost:8080/env
{
"profiles":[],
"configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
"servletContextInitParams":{},
"systemProperties":{...},
...
}
名为```configService:/的属性源包含值为
bar的
foo`属性,并且优先级最高。