Spring Cloud

怎么保证Eureka注册中心高可用?

可以部署多个注册中心,注册中心相互注册

Ribbon实现负载均衡的原理?

RestTemplate上添加了@LoadBalanced注解后,就会使用LoadBalancerClient来配置RestTemplate,自动配置LoadBalancerAutoConfiguration在满足@ConditionalOnBean(LoadBalancerClient.class)后就会实现自动配置,在RestTemplateCustomizer中添加了拦截器LoadBalancerInterceptorLoadBalancerInterceptor拦截器会拦截所有的请求,通过ServiceId获取服务器真实地址列表,获取服务器列表后使用负载均衡算法选出一台服务器进行调用

Ribbon有哪些负载均衡算法?

轮询、随机、权重

轮询的算法:使用线程安全的数值类型来存储请求的次数,如:AtomicLong,然后用请求次数 模与服务的个数 如:count是请求次数,size的服务的个数,count%size=index。通过这个index就可以从服务列表中获取到某个服务,因为使用了取模的操作,这个index永远在服务列表size的范围内。

Hystrix的作用是什么

Hystrix主要用来解决雪崩问题,采用服务降级策略。

服务降级有2中解决方案: 1、线程隔离、2、服务熔断。

可以为某个方法单独编写服务降级逻辑fallback方法,然后在这个方法上使用@HystrixCommand(fallbackMethod = “getProducterInfoFallBack”)注解,并制定fallback方法名字,这种方式需要 原方法和降价方法的参数和返回值保持一致

也可以编写一个统一降级逻辑方法,并在类上使用@DefaultProperties(defaultFallback = “defaultFallBack”),指定统一降级逻辑,这种方式降级方法可以没有参数,但要求类中的所有方法的返回值都和降级逻辑的返回值一致

Hystix如何解决雪崩问题?

Hystrix为每个依赖服务调用分配一个小的独立线程池,用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满调用将被立即拒绝,否则使用线程来处理请求。

可以在主线程中设置超时时间,超过这个时间如果子线程还没有执行完成任务或者子线程执行出现异常,则会进行服务降级。

用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息) 。
服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。

Hystix如何进行服务熔断?

Hystix的熔断状态:

  • Closed:关闭状态(断路器关闭),所有请求都正常访问。
  • Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
  • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时。

SpringCloud是如何进行服务间调用的

服务间的调用使用Feign组件。

创建客户端,一般叫XXXClient是个interface。需要引入依赖spring-cloud-openfeign-core。在接口使用@FeignClient(“serviceId”) 里面填写这个接口对应的serviceId。在接口中编写方法,方法的url、参数、返回值要和Api的url、参数、返回值保持一致,方法名字可一修改。

在需要进行远程调用的工程中引入spring-cloud-starter-openfeign,引入feign客户端接口所在的包。在启动类上添加注解@EnableFeignClients,在需要使用的地方注入接口即可使用。

Feign是如何进行服务降级的

Feign默认也有对Hystix的集成,默认情况下是关闭的。我们需要通过下面的参数来开启:

feign:
  hystrix:
    enabled: true

但是Feign中的Fallback配置不像Hystrix中那样简单了。

需要要定义一个类,实现feign的接口,作为feign接口的fallback处理类,在类中实现每一个接口中的方法,这些实现方法都是fallback处理方法 ,如:

@Component
public class HelloClientFallback implements HelloClient {
    @Override
    public String hello() {
        return "服务太忙了,请稍后重试。" + System.currentTimeMillis();
    }

    @Override
    public String postParam(String name) {
        return "服务太忙了,请稍后重试。" + System.currentTimeMillis();
    }

    @Override
    public String postBody(User user) {
        return "服务太忙了,请稍后重试。" + System.currentTimeMillis();
    }
}

然后在接口Client中的@FeignClient注解中的fallback属性,指定编写的实现类 ,如:

// 添加FeignClient注解,指定服务ID,指定降级处理类
@FeignClient(value = "hello-service",fallback = HelloClientFallback.class)
public interface HelloClient {
    // 需要指定具体的调用方法
    @GetMapping("/hello")
    String hello();

    // 需要注意使用@RequestParam要指定传入的Key
    @PostMapping("/hello/postParam")
    String postParam(@RequestParam("name") String name);

    @PostMapping("/hello/postBody")
    String postBody(@RequestBody User user);
}

是否用到了网关

项目中使用了网关zuul。zuul的主要作用的 过滤、路由、负载均衡

Zuul需要独立搭建服务部署。依赖是spring-cloud-starter-netflix-zuul,启动类上添加@EnableZuulProxy,在application.yml中添加zuul.routes 路由映射的配置。

Zuul面向服务的路由和负载均衡需要依赖Eureka,需要引入 eureka的client依赖。

Zuul内部都是过滤器,有4中类型:pre、routing、error、post。

zuul的过滤器都继承了一个等级类ZuulFilter。如果想要自己实现一个自定义过滤器,就需要继承ZuulFilter。并实现4个方法,分别是:

abstract public String filterType();  //过滤器类型
    abstract public int filterOrder(); //当前过滤器执行顺序
    boolean shouldFilter();     //是否过滤
    Object run() throws ZuulException;  //当前过滤器的业务

结合自定义过滤器,我们可以实现某些自定义功能,如

请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了

异常处理:一般会在error类型和post类型过滤器中结合来处理。

服务调用时长统计:pre和post结合使用。

SpringCloudConfig作用

统一配置组件,统一管理配置文件。可以把配置文件放在 Git、Svn、本地文件存储。

config的结构包含server端和client。

server端需要独立部署,引入spring-cloud-config-server依赖和spring-boot-starter-actuator依赖,在启动类上添加注解@EnableConfigServer,并在自己的配置文件中配置git地址,如

spring:
  application:
    name: config-demo
  cloud:
    config:
      server:
        git:
          uri: https://gitee/fwis/fwis.git
server:
  port: 12000

client需要在微服务中集成,引入spring-cloud-starter-config,在配置文件中,配置server的路径、当前应用配置文件的名字、配置文件对应的环境、git上的分支名字,如:

spring:
  cloud:
    config:
      name: user
      profile: dev
      label: master
      uri: http://127.0.0.1:12000

应用服务中就不需要出现application.yml。每次启动的时候先去统一配置server获取最新的配置文件,拉取到本地后再启动。

统一配置server从git拉取后,会现在本地按照版本信息缓存一份配置文件。

SpringCloudBus的作用

SpringCloudBus实现配置的自动更新。

基于RabbitMQ消息中间件实现。需要在server端引入依赖spring-cloud-starter-bus-amqp,然后在配置文件配置RabbitMQ的ip、虚拟主机、用户名、密码,并配置可以调用的总线地址,如:

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    virtual-host: /fwis
    username: fwis
    password: fwis
management: #暴露触发消息总线的地址
  endpoints:
    web:
      exposure:
        include: bus-refresh

在微服务中引入spring-cloud-starter-bus-amqp,也配置RabbitMQ的ip、虚拟主机、用户名、密码,并配置可以调用的总线地址。

最后如果在git上的配置文件有了修改,可以post请求访问 http://127.0.0.1:12000/actuator/bus-refresh这个地址,bus组件就会帮助实现自动更新

更多推荐

Spring Cloud五大组件及SpringCloudBus、 SpringCloudConfig实际作用