1.SpringBoot与SpringCloud
首先谈一下spring框架:springboot构建一切,springcloud连接一切。springcloud我认为主要是实现分布式,过个项目(服务)之间可以通过springcloud进行连接。
SpringBoot和SpringCloud之间的关系:
SpringBoot主要是构建项目,springboot的核心就是约定大于配置,专注于构建每个服务;
SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务,整合并管理起来;
SpringBoot可以离开SpringCloud单独使用,但是SpringCloud离不开SpringBoot。
2.微服务
谈到SpringCloud就离不开微服务。微服务主要是将一个项目中的各个功能或者模块抽象成一个服务,每个服务都可以单独的运行。之间的项目是all in one,所有的项目功能都在一个模块里面,只要有一个功能崩溃,那整个项目就崩溃,这种的耦合程度非常高;但是微服务达到了解耦的目的,各个服务抽象出来,一个服务崩溃,其他的服务还是可以运行。
那实现微服务就有以下几个问题:
- 这么多服务,客户端怎么访问
- 这么多服务,服务之间怎么通信
- 这么多服务,怎么治理服务
- 服务崩溃的问题
下面就是针对上面四个问题spring cloud netfix提出的解决方案
3. SpringCloud核心组件
3.1 路由网关GateWay
路由网关就是解决客户端访问服务的问题。SpringCloud当中是Zuul网关,主要是对客户端的请求进行路由和过滤。
- 概念:主要是对客户端请求的路由和过滤
- 有一个统一的访问地址,用gateway实现请求的路由(管理这些微服务)。
- 路由:将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,
- 过滤:负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。
举个例子:
原来访问一个服务是:http://localhost:8001/dept/get/1(地址)
加了zuul网关之后:http://www.study.com:9527/springcloud-provider-dept/dept/get/1
但是这里没有配置zuul所有暴露出了微服务的名字
根据配置zuul之后:http://www.study.com:9527/haust/mydept/dept/get/1(/haust是统一前缀,/mydept替代了前面的微服务的名字)
//路由相关配置
//原来访问路由 eg:http://www.study.com:9527/springcloud-provider-dept/dept/get/1
//zull路由配置后访问路由 eg:http://www.study.com:9527/haust/mydept/dept/get/1
routes:
mydept.serviceId: springcloud-provider-dept # eureka注册中心的服务提供方路由名称
mydept.path: /mydept/** # 将eureka注册中心的服务提供方路由名称 改为自定义路由名称
//不能再使用这个路径访问了,*: 忽略,隐藏全部的服务名称~
ignored-services:
"*"
//设置公共的前缀(这是统一的前缀)
prefix: /haust
3.2 Ribbon和Feign
Ribbon和Feign两者都是实现负载均衡(LoadBalancer)。那负载均衡是什么?其实就是分配访问服务器,当存在很多个客户端请求,负载均衡可以实现将请求分散给各个服务器,不让一个服务器承受压力。Ribbon是基于Restful风格,利用restTemplate进行处理;而feign是基于注解和接口编程,更加符合java编程的习惯。
Ribbon:
Step1:新建一个配置类:
@Configuration
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
Step2:在controller中利用微服务名字进行访问
@RestController
public class DeptConsumerController {
/***
* 消费者不需要service层
* RestTemplate模板我们直接调用
* (url,实体,responseType)
*/
@Autowired
private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法
private static final String REST_URL_PREFIX="http://localhost:8001";
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") int id){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get"+id,Dept.class);
}
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> getAll(){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}
}
Feign:
Step1:写一个接口DeptConsumerClient
// @FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public Dept queryAll();
@GetMapping("/dept/add")
public Dept addDept(Dept dept);
Step2:在controller层中直接调用
@RestController
public class DeptConsumerController {
@Autowired
private DeptClientService deptClientService;
/**
* 消费方添加部门信息
* @param dept
* @return
*/
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
return deptClientService.addDept(dept);
}
/**
* 消费方根据id查询部门信息
* @param id
* @return
*/
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return deptClientService.queryById(id);
}
/**
* 消费方查询部门信息列表
* @return
*/
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
return deptClientService.queryAll();
}
}
3.3 Euraka服务注册
Euraka主要是为了解决服务之间治理的问题。Euraka是一个服务注册中心,所有的服务都需要在Euraka中注册。
系统中的其他微服务:使用Euraka的客户端连接到EurakaServer并维持心跳连接,可以通过EurakaServer监控系统中的各个微服务是否正常运行。
两个组件:Eureka Server 和 Eureka Client.
Eureka Server: 提供服务注册,各个节点启动后,回在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会储存所有课用服务节点的信息,服务节点的信息可以在界面中直观的看到.
Eureka Client :一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳 (默认周期为30秒) 。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉 (默认周期为90s).
EureKa自我保护机制:
某时刻某一个微服务不可用,eureka不会立即清理,依旧会对该微服务的信息进行保存!(该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,保护机制就先不注销该服务)
对比Zookeeper:
CAP理论:一致性、可用性、分区容忍性
zookeeper:主要是保证CP原则(主要是保证了一致性)
eureka:主要是保证AP原则(主要是保证可用性)
3.4 Hystrix服务熔断
Hystrix主要是解决服务挂了的问题。主要就是服务崩溃或者访问有错后,客户不会有什么异常,就算后端在报错,但是前端不会报错,会出现相应的提示信息(比如为空等等)
- 服务雪崩:分布式系统中有多个服务器,出现服务器崩溃的现象(可能出现一个服务崩溃导致整个分布式系统都出现崩溃的情况)
- Hystrix保证一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障
- 作用:服务降级、服务熔断、服务限流、接近实时的监控
- Hystrix机制:与保险丝类似:当某个服务单元发生故障之后,通过断路器的故障监控 (类似熔断保险丝) ,向调用方返回一个服务预期的,可处理的备选响应 (FallBack) ,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。(调用备份)
- 一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:
@HystrixCommand
- 其中重要的部分是服务熔断和服务降级。
- 服务熔断:走备选方法:(在服务端写的) 某个服务超时或者异常
- 服务降级:把系统资源让给优先级高的服务,将其他服务关闭(比如双11的时候关闭查看历史订单、关闭退款功能)(在客户端写的) 从整体网站请求负载考虑,客户还是可以发请求,但是这个服务不走服务器