Spring Cloud核心组件及其作用

Eureka

服务注册与发现
注册:每个服务都向Eureka登记自己提供服务的数据,包括服务的ip地址、端口号、版本号、通信协议等。Eureka将各个服务维护在了一个服务清单中(双层Map,第一层map的key是服务名,第二层map的key是实例名,value是服务地址加端口)。同时对服务维持心跳,剔除不可用的服务,Eureka集群各节点相互注册的每个实例中都有一样的服务清单。
发现:Eureka注册的服务之间调用不需要制定服务地址,而是通过服务名向注册中心咨询,并获取所有服务实例清单(缓存到本地),然后实现服务的请求访问。

Ribbon

服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台(被调用方的服务地址有多个),Ribbon也是通过发起http请求来进行调用,只不过是通过调用服务名的地址来实现的。虽说Ribbon不用去具体请求服务实例的ip地址或域名了,但是每调用一个接口都还要手动去发起http请求

1
2
3
4
5
6
7
8
9
10
@RestController
public class ConsumerController{
@Autowired
RestTemplate restTemplate;
@GetMapping("/ribbon-consumer")
public String helloConsumer(){
//每调用一次实例都要写这么一行代码来发起http请求,非常的麻烦,由此引出feign
return restTemplate.getForEntity("http://exampleservice/index",String.class).getBody();
}
}

Feign

基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求,简化服务见得调用,在Ribbon的基础上进行了进一步的封装。单独抽出了一个组件,就是Spring Cloud Feign,在引入Spring Cloud Feign后,我么只需要创建一个接口,并用注解的方式来配置它,即可完成对服务提供方的接口绑定。
调用远程服务就像调用本地服务一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RestController
public class UserController(){
@GetMapping("/getUser")
public String getUser(){
List<String> list = new ArrayList<>();
list.add("张三");
return SON.toJSONString(list);;
}
}

//name是服务在Eureka上注册的服务名
@FeignClient(name = "user")
public interface UserClient{
@GetMapping("/getUser")
String getUser();
}

public class TestController{
@Resource
UserClient userClient;
@RequestMapping("/test")
public String test(){
return userClient.getUser();
}
}

Hystrix

发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,通过统计接口超时次数返回的默认值,来实现服务的熔断和降级。
例如存在这么一条调用链: A > B > C,A服务的并发量很高,A服务是会垮掉的,在这条链路中,A服务会把并发量向下传导,即传给B节点和C节点,导致每个节点的并发量升高,极有可能因为A服务而导致这条调用链垮掉,而Hystrix就是起到断路器的作用,将A与B之间的调用切断,从而保护下级链路。

Zuul

如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务,通过与Eureka进行整合,将自身注册为Eureka下的应用,从Eureka下获取所有服务的实例,来进行服务的路由。Zuul还提供了一套过滤器机制,开发者可以自己指定那些规则的请求需要执行校验罗技,只有通过校验逻辑的请求才会被路由到具体服务实例上,否则返回错误提示。

Spring Cloud和Dubbo有什么区别?

Spring Cloud是一个微服务框架,提供了微服务领域中很多的功能组件,Dubbo一开始是一个RPC调用框架,核心是解决服务调用间的问题,Spring Cloud是一个大而全的框架,Dubbo更侧重于服务调用,所以Dubbo所提供的功能没有Spring Cloud全面,但是Dubbo的服务调用性能比Spring Cloud高,不过两者并不是对立的,可以整合起来一起使用。

什么是服务降级?什么是服务熔断?区别是什么?

服务降级是指:当发现系统压力过载时,可以通过关闭某个服务,或限流某个服务来减轻系统压力。
服务熔断是指:当服务A调用的某个服务B不可用时,上游服务A为了保证自身不受影响,从而不在调用服务B,直接返回一个结果,减轻服务A和服务B的压力,知道服务B恢复。
相同点:

  1. 都是为了防止系统崩溃
  2. 都让用户感受到某些功能暂时不可用

不同点:

  1. 熔断是下游服务故障而触发的
  2. 降级是为了降低系统负载

什么是服务雪崩?什么是服务限流?

  1. 当服务A调用服务B,服务B调用服务C,此时大量请求突然请求服务A,假如服务A本身能够扛得住这些请求,但是服务C扛不住,就会导致服务C请求堆积,从而服务B请求堆积,最终导致服务A不可用,这就是服务雪崩,解决方式就是服务降级和服务熔断。
  2. 服务限流是指高并发请求下,为了保护系统,可以对访问服务的请求进行数量上的限制,从而防止系统不被大量请求压垮,在秒杀中,服务限流是非常重要的。

谈谈你对微服务的理解,微服务有哪些优缺点?

微服务是由Martin Fowler大师提出的。微服务是一种架构风格,通过将大型的单体应用划分为比较小的服务单元,从而降低整个系统的复杂度。
优点:

  1. 服务部署更灵活:每个应用都可以是一个独立的项目,可以独立部署,不依赖于其他服务,耦合性降低。
  2. 技术更新灵活:在大型单体应用中,技术要进行更新,往往是非常困难的。而微服务可以根据业务特点,灵活选择技术栈。
  3. 应用的性能得到提升:在大型单体应用中,启动往往就会成为一个很大的难关,而采用微服务之后,整个系统的性能是能够提升的。
  4. 更容易组建专门的团队:在单体应用中,团队成员往往需要对系统的各个部分要有深入的了解,门槛相对较高,而采用微服务之后,可以给每个微服务组建专门的团队。
  5. 代码复用:很多底层服务可以以RESTAPI的方式对外提供统一的服务,所有基础服务可以在整个微服务系统中通用。

缺点:

  1. 服务调用的复杂度提高了:网络问题、容错问题、负载问题、高并发问题……
  2. 分布式事务:使用难度高,难处理。
  3. 测试的难度提升:是自己的服务出问题了,还是外部的接口出问题了,测试要有足够的覆盖
  4. 运维难度提升:单体架构只要维护一个环境,而微服务是很多个环境,比如nacos服务,mq服务,运维方式还都不一样。对部署、监控、告警等要求就会变得非常困难。

Nacos注册中心的核心功能原理是什么?

服务注册:当服务一启动,通过Rest请求的方式向Nacos Server注册自己的服务。
服务心跳:Nacos Client会维护一个定时心跳持续通知Nacos Server,表示服务处于一个可用的状态,默认5s发送一次,如果Nacos Client 超过了15s没有接收到心跳,会将服务健康状态设置为false(拉取的时候会忽略),如果Nacos Client超过了30秒没有接收到心跳,就会剔除掉服务。
服务发现:Nacos Client会有一个定时任务,实时去Nacos Server拉取健康服务
服务停止:Nacos Client会主动通过Rest请求Nacos Server发送一个注销的请求。