Spring Cloud 是一个基于Spring Boot实现的微服务框架,它包含了实现微服务框架所需的各种组件。
Spring Cloud简单理解就是简化Spring项目的搭建、配置、组合的框架。
服务化即为拆解的一种手段,服务、服务调用、注册中心、服务注册、服务发现即为一个服务化框架的最小组成元素,可通过这些基本的组成要素,实现一个简单的服务架构。
一、面向服务的架构和微服务架构
面向服务的架构(SOA)和微服务架构师目前两种主流的服务化架构,两者的区别如下:
微服务是去ESB(企业服务总线)的SOA。ESB借鉴了计算机组成原理中的通信模型–总线,所有需要和外部系统通信的系统,通过ESB进行标准化地转换从而消除协议、异构系统之间的差异,这样就可以利用现有的系统架构构建一个全新的松耦合的异构的分布式系统。微服务架构去掉ESB,本质上是一种去中心化的思想。
为了解决服务治理问题,Spring Cloud提供了Eureka、Zookeeper、Cloud Foundry、Consul等服务治理框架的集成。它们的工作模式是将所有的微服务注册到一个Server上,然后通过心跳进行服务健康监测。这样服务A调用服务B时,可以从注册中心拿到可用的服务B的地址、端口进行调用。
Spring Cloud提供了两种服务调用方式:一种是Ribbon + restTemplate, 另一种是Feign。
a、Ribbon是基于HTTP和TCP客户端的负载均衡器,restTemplate是Spring提供的Restful远程调用的模板,两者结合就可以达到远程调用的负载均衡。
b、Feign是一个更加声明式的HTTP客户端,开发者可以像调用本地方法一样调用它,完全感觉不到是远程调用,结合Ribbon也可以做负载均衡。
举例说明(包含了微服务中注册中心、服务提供者、服务消费者三个基本角色):
- 注册中心
注解@EnableEurekaServer表示该Spring Boot应用是一个注册中心。
@EnableEurekaServer
@SpringBootApplication
public class EurekaserverApplication {
public static void mian(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
}
eureka.client.registerWithEureka:flase 和fetchRegistry:false来表明自己是一个eureka server。
server:
port:8080
eureka:
Instance:
hostname:localhost
client
registerWithEurka:false
fetchRegistry:false
serviceUrl:
defaultZone:http://$(eureka.instance.hostname):$(server.port)/eureka/
- service-hello 服务
注解@EnableEurekaClient表示它是一个Eureka客户端,它会在注册中心注册自己。
注解@RestController表示这是一个控制器,@RequestMapping(“/hello”)表示匹配到请求‘/hello’时会调用该方法进行响应。
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHelloApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceHelloApplication.class, args);
}
}
@Value("$(server.port"))
String port;
@RequestMapping("/hello")
public String home(@RequestParam String name) {
return "hello" + name + ", i am from port:" + port;
}
注册中心的地址为:http://localhost:8080/eureka/。服务名为service-hello,将会被调用者调用。
eureka:
client:
serviceUrl:
defaultZone:http://localhost:8080/eureka/
server:
port:8081
spring:
application:
name:service-hello
- 服务消费者service-ribbon
假设service-ribbon端口为8082,当我们访问http://localhost:8080/hello时,HelloController接收到请求,并调用HelloService中的helloService方法,HelloService中通过定义的restTemplate去调用http://service-hello/hello。注解@LoadBalanced表示启动负载均衡。
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String helloService(String name) {
return restTemplate.getForObject("http://service-hello/hello?name=" + name, String.class);
}
}
@RestController
public class HelloController{
@AutoWired
HelloService helloService;
@RequestMapping(value = "/hello")
public String hello(@RequestParam String name) {
return helloService.helloService(name);
}
}
-
服务“雪崩”与断路器
由于网络等原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗殆尽,导致服务瘫痪。
由于服务与服务直接存在依赖,故障会在调用链路上传播,导致整个微服务系统崩溃,这就是服务故障的**“雪崩”效应**。
为了解决“雪崩”效应这个问题,Spring Cloud提供了对Hystrix断路器的继成,当服务调用失败的频次达到一定阈值,断路器将被开启,降低的策略可以开发者制定,一般是返回一个固定值。这样就能够避免连锁故障。
此外Spring Cloud还提供Hystrix Dashboard和Hystrix Turbine,帮助我们进行监控和聚合监控。
-
服务暴露与路由网关
微服务中的服务很多,直接暴露给用户一是不安全,二是对用户不友好。因此在微服务和面向微服务的架构中,通常会有一个路由网关的角色,来负责路由转发和过滤。对应到Spring Cloud中有Zuul和Gateway两个组件可用。
路由网关接收了所有的用户请求,有着很高的负载,因此它通常是一个集群。用户的请求会先经过一层负载均衡被发到路由网关。
-
服务配置与配置中心
在微服务应用中,服务数量巨多,而每个服务不同环境都有着不同的配置,为了方便服务配置文件统一管理,实时更新,所有需要分布式配置中心组件。
Spring Cloud提供了Spring Cloud Config组件,它支持配置服务房子配置服务的内存中(即本地),也支持放在远程Git仓库中,帮助我们管理服务的配置信息。
-
信息同步与消息总线
Spring Cloud提供了Spring Cloud Bus组件,它通过轻量消息代理连接各个分布的节点。当配置信息更新的时候,我们只要更新一个节点的配置,这个更新就会被广播到这个分布式系统中。
-
问题定位与链路追踪
在微服务系统中,服务之间可以相互调用,因此我们一个请求可能会一条调用链,而整个系统会存在一张调用网,其中任意一个服务调用失败或网络超时都可能导致整个请求失败。因调用关系复杂,给问题定位造成了极大的困难,这也是必须提供服务链路追踪的原因。