1. 负载均衡

​ 负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务。

1.1. dubbo

String loadbalance() default "";

dubbo的四种负载分别是:随机(权重)、轮询(权重)、最少活跃调用数、一致性Hash。

1.2. gateway

通过服务注册中心的服务名/接口实现负载均衡。实际上gateway的负载均衡基于的是ribbon

server:
  port: 8080
spring:
  application:
    name: gateway_server
  cloud:
    gateway:
      default-filters:
      routes:
        - id: my_route
          uri: lb://my-load-balanced-service
          predicates:
            - Path=/gateway/**
          filters:
            - StripPrefix=1
my-load-balanced-service:
  ribbon:
    listOfServers: localhost:1001, localhost:1002
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule**
    # 使用了轮询的负载均衡策略。
    # https://www.jianshu.com/p/cdf63185b0c3

1.3. Ribbon

  • 负载规则:从服务器列表中决定用哪个服务器
  • ping任务:后台运行的任务,用来验证服务器是否可用
  • 服务器列表:以是静态也可以是动态,如果是动态,那么就要有一个后台线程定时去刷新和过滤列表。我们微服务基于服务发现的情况,服务器列表肯定都是动态增减的
  • RoundRobinRule:轮询。默认超过10次获取到的server都不可用,会返回一个空的server
  • RandomRule:随机,如果随机到的server为null或者不可用的话,会while不停的循环选取
  • RetryRule:一定时限内循环重试。默认继承RoundRobinRule,也支持自定义注入,RetryRule会在每次选取之后,对选举的server进行判断,是否为null,是否alive,并且在500ms内会不停的选取判断。而RoundRobinRule失效的策略是超过10次,RandomRule是没有失效时间的概念,只要serverList没都挂。
  • BestAvailableRule:最小连接数。遍历serverList,选取出可用的且连接数最小的一个server。该算法里面有一个LoadBalancerStats的成员变量,会存储所有server的运行状况和连接数。如果选取到的server为null,那么会调用RoundRobinRule重新选取。
  • WeightedResponseTimeRule:最小响应时间。这个策略整合了随机算法和响应时间加权算法。会开启定时任务,每30秒计算一次所有Provider的响应时间,以响应时间作为权重,响应时间越短的服务器被选中的概率越大。比如Node1:node2:node3的平均响应时间为100ms:200ms:300ms,那么nodes的的权重值是300:500:600,每次以600为基础*随机值,那么落在 0–300的概率为50%,300–500的概率33%,100–600的概率为17%,也就是平均响应时间越短的节点,被选中的概率越大。

1.4. Nignx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FDMK8kFz-1596725381127)(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596721489063&di=66641b845f5efbd56566eff256dccf3e&imgtype=0&src=http%3A%2F%2Fstatic.jointforce.com%2Fjfperiodical%2Fattached%2Fimage%2F20160420%2F-1451750843.png)]

nginx负载均衡基本配置

http {
   upstream myapp1 {
       server ip:port;
       server ip:port;
       server ip:port;
   }
   server {
       listen 80;
       location / {
           proxy_pass http://xxx;
       }
   }
}

​ 目前Nginx的upstream模块支持6种方式的负载均衡策略(算法):轮询(默认方式)、weight(权重方式)、ip_hash(依据ip分配方式)、least_conn(最少连接方式)、fair(第三方提供的响应时间方式)、url_hash(第三方通过的依据URL分配方式)。

推荐文章:

2. 服务熔断

​ 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。

2.1. dubbo

String mock() default ""; //true(自动寻找mork实现类) fail(允许请求) default(和true一样) force(屏蔽请求)

2.2. Hystrix

circuitBreaker.enabled  是否开启熔断
circuitBreaker.requestVolumeThreshold  熔断最低触发请求数阈值
circuitBreaker.sleepWindowInMilliseconds  产生熔断后恢复窗口
circuitBreaker.errorThresholdPercentage  错误率阈值
circuitBreaker.forceOpen  强制打开熔断
circuitBreaker.forceClosed  强制关闭熔断
@Configuration
public class GatewayFallbackConfig {

    @Autowired
    private HystrixFallbackHandler hystrixFallbackHandler;

    @Bean
    public RouterFunction routerFunction() {
        return RouterFunctions.route(
                RequestPredicates.GET("/defaultfallback")
                        .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler);
    }
}

@Component
public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {

    @Override
    public Mono<ServerResponse> handle(ServerRequest serverRequest) {
    	
        serverRequest.attribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR)
            .ifPresent(originalUrls -> log.error("--------", originalUrls));
        return ServerResponse
            .status(HttpStatus.INTERNAL_SERVER_ERROR)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .body(BodyInserters.fromObject(ResultData.fail("HystrixFallbackHandler")));
    }
}

可以采用简单的注解配置

3. 服务降级

​ 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

服务降级这个问题,如果从整体来操作,

  1. 一定是先降级优先级地的接口,两权相害取其轻

  2. 如果服务链路整体没有性能特别差的点,比如就是外部流量突然激增,那么就从外到内开始降级

  3. 如果某个服务能检测到自身负载上升,那么可以从这个服务自身做降级

3.1. dubbo

  • 第一种方式:通过dubbo-admin实现

    mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

    还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

  • 第二种方式:@Reference实现

    @Reference(timeout = 1000) //设置超时时间
    
  • 第三种方式:mork

    String mock() default ""; //true(自动寻找mork实现类) fail(允许请求) default(和true一样) force(屏蔽请求)
    //xxxServiceMork要和接口在一个项目中,为的是方便找到Mork类
    

3.2. Hystrix

4. 服务限流

​ 为了防止某个消费者的QPS或是所有消费者的QPS总和突然飙升而导致的重要服务的失效,系统可以对访问流量进行控制,这种对集群的保护措施称为服务限流。

4.1. dubbo

Dubbo中能够实现服务限流的方式较多,可以划分为两类:直接限流间接限流

  • 直接限流:通过对连接数量直接进行限制来达到限流的目的。
  • 间接限流:通过一些非连接数量设置来达到限制流量的目的。

dubbo限流的方式:

  • 第一种方式:executes直接限流(提供者端使用)

    <dubbo:service interface="com.xxx.xxx" executes="10" /> <!--服务端并发:限制10个并发-->
    
    <dubbo:service interface="com.xxx.xxx">
        <dubbo:method name="xxxx" executes="10" /> <!--方法级别:限制10个并发-->
    </dubbo:service>
    
  • 第二种方式:accepts限流(提供者端使用)

    <dubbo:provider protocol="dubbo" accepts="10" /> <!--用于对指定协议的连接数量进行限制-->
    
    <dubbo:protocol name="dubbo" port="20880" accepts="10" /> <!--用于对指定协议的连接数量进行限制-->
    
  • 第三种方式:actives限流(两端)

    根据消费者与提供者间建立的连接类型的不同,其意义也不同

    • 长连接:表示当前长连接最多可以处理的请求个数。与长连接的数量没有关系
    • 短连接:表示当前服务可以同时处理的短连接数量
    <dubbo:service interface="com.xxx.xxx" actives="10" />
    
    <dubbo:reference interface="com.xxx.xxx">
        <dubbo:method name="xxxx" actives="10" />
    </dubbo:service>
    
    <dubbo:reference interface="com.xxx.xxx" actives="10" />
    
    <dubbo:reference interface="com.xxx.xxx">
        <dubbo:method name="xxxx" actives="10" />
    </dubbo:service>
    
  • 第四种方式:connections限流(两端)

    限定连接的个数。对于短连接,该属性效果与actives相同。但对于长连接,其限制的是长连接的个数。

    ​ 一般情况下,会使connectons与actives联用,让connections限制长连接个数,让actives限制一个长连接中可以处理的请求个数。联用前提:使用默认的Dubbo服务暴露协议

    <dubbo:service interface="com.xxx.xxx" ref="xxx" connections="10"></dubbo:service>
    
    <dubbo:service interface="com.xxx.xxx" ref="xxx">
    	<dubbo:method name="xxxx" connections="10"></dubbo:method>
    </dubbo:service>
    
    <dubbo:reference interface="com.xxx.xxx" id="xxx" connections="10"></dubbo:reference>
    
    <dubbo:reference interface="com.xxx.xxx" id="xxx">
    	<dubbo:method name="xxxx" connections="10"></dubbo:method>
    </dubbo:reference>
    
  • 第五种方式:延迟连接(间接限流)

    ​ 仅可设置在消费者端,且不能设置为方法级别。仅作用于Dubbo服务暴露协议。
    将长连接的建立推迟到消费者真正调用提供者时。可以减少长连接的数量。

    <!--设置当前消费者对接口中的每个方法发出链接采用延迟加载-->
    <dubbo:reference id="xxx"  lazy="true"
        interface="com.xxx.xxx.xxx"/>
    
  • 第六种方式:粘连连接(间接限流)

    ​ 仅能设置在消费者端,其可以设置为接口级别,也可以设置为方法级别。仅作用于Dubbo服务暴露协议,其会使客户端尽量向同一个提供者发起调用,除非该提供者挂了,其会连接另一台。只要启用了粘连连接,其就会自动启用延迟连接,其限制的是流向,而非流量。

    <dubbo:reference id="xxxx" sticky="true" interface="com.xxx.xxx.xxx"></dubbo:reference>
    
    <dubbo:reference id="xxxx" interface="com.xxx.xxx.xxx">
    	<dubbo:method name="xxxx" sticky="true"></dubbo:method>
    </dubbo:reference>
    
  • 第七种方式:负载均衡(间接限流)

    参考负载均衡中的dubbo

4.2. Hystrix

public class CommandReject extends HystrixCommand<String> {
  
  private String tag;
 
  public CommandReject(String tag) {
    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandReject"))
        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
            .withCoreSize(5)
            .withMaxQueueSize(2))
        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
            .withExecutionTimeoutInMilliseconds(3000)));
    this.tag = tag;
  }
 
  @Override
  protected String run() throws Exception {
    Thread.sleep(3000);
    return tag;
  }
 
  @Override
  protected String getFallback() {
    return "服务降级处理";
  }
}

5. 参考

Hystrix写的很少,往后学习会补充进去

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐