zoukankan      html  css  js  c++  java
  • SpringCloud应对高并发的思路

    一、Eureka的高可用性

      Eureka下面的服务实例默认每隔30秒会发送一个HTTP心跳给Eureka,来告诉Eureka服务还活着,每个服务实例每隔30秒也会通过HTTP请求向Eureka获取服务列表,这就相当于一个服务实例一分钟会与Eureka进行四次请求,当服务实例多了以后,就要考虑Eureka的压力,如果我们有1000个服务实例,一分钟就会有4000次请求,平均每秒70次请求,不过Eureka内部是通过内存建立一个HashMap来维护服务实例列表的,并且还做了读写分离,所以保证多个实例的心跳是没有问题的,要注意的是保证Eureka的高可用,生产环境中如果Eureka挂掉,相当于所有实例之间都没办法联系了,我们可以在多台机器上部署Eureka(尽量不要同时在一台机器上部署,因为出问题时,一般整个机器的资源都不能正常使用了),可以部署三个Eureka实例,然后将每个服务实例同时注册到三台Eureka上面,这样即使某个Eureka挂掉了,也不会影响整个系统的运行。

      配置的方式也很简单,部署好多台Eureka实例后,只需要将每个服务实例分别注册到每个Eureka上面即可

    eureka:
      client:
        serviceUrl:
          defaultZone: http://eureka1:80/eureka/, http://eureka2:80/eureka/

    二、服务熔断和服务降级

      微服务之间的调用两种情况,网关与服务之间的调用,服务与服务之间的调用,当某个服务的响应时间过长,调用链就会等待,当请求量多了,就会引起雪崩,所以就需要用到服务熔断组件hystrix,当调用超时时直接返回,并且设置服务降级策略,当发生熔断时的补救措施,比如监控告警,记录SQL日志后续进行数据恢复等

    1、服务降级配置

      当出现服务熔断时,我们需要配置服务熔断的处理策略,服务降级有两种情况,网关层面做降级和服务之间做降级

    (1)网关层面降级:只需要重写ZuulFallbackProvider的方法,即可定制返回值

    @Component
    public class GatewayFallback implements ZuulFallbackProvider
    {
        @Override
        public String getRoute()
        {
            // 这里配置服务降级是针对哪个服务实例的,可以填写服务id,如果返回null则是针对所有服务
            return null;
        }
        @Override
        public ClientHttpResponse fallbackResponse()
        {
            // 服务熔断后,返回的内容
            return new ClientHttpResponse()
            {
                @Override
                public InputStream getBody() throws IOException
                {
                    JSONObject result = new JSONObject();
                    result.put("error_code", -1);
                    result.put("error_info", "网络繁忙");
                    return new ByteArrayInputStream(result.toString().getBytes("UTF-8"));
                }
                @Override
                public HttpHeaders getHeaders()
                {
                    // 返回Json格式的数据
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    return headers;
                }
                @Override
                public HttpStatus getStatusCode() throws IOException
                {
                    // 返回的HTTP错误码
                    return HttpStatus.OK;
                }
                @Override
                public int getRawStatusCode() throws IOException
                {
                    return HttpStatus.OK.value();
                }
                @Override
                public String getStatusText() throws IOException
                {
                    return HttpStatus.OK.getReasonPhrase();
                }
                @Override
                public void close()
                {
                    // 进行一些自定义的处理,比如监控告警
                }
            };
        }
    }

    (2)服务之间降级:服务之间的调用一般是使用Feign组件,我们需要为Feign接口声明的每个方法编写处理的逻辑,通过注解的fallback属性来指定服务降级的实现类

    @FeignClient(value = "clientService", fallback = ClientServiceFallback.class)
    public interface ClientService
    {
        @RequestMapping(method = RequestMethod.POST, value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
        String queryClientById(@RequestParam("id") String id);
    }
    public class ClientServiceFallback implements ClientService
    {
        @Override
        public String queryClientById(String id)
        {
            // 进行一些自定义的处理
            return null;
        }
    }

    2、服务熔断配置

      服务熔断的参数配置非常重要,合理的参数配置才能更好地利用好机器资源,既不会浪费,也能合理对服务进行熔断防止雪崩

    (1)熔断超时时间设置:这个时间一定要根据情况合理选择,不能太高也不能太低,如果设置太高,当服务出现问题时,每个线程都要等待很久,所有线程卡死就会导致用户根本无法正常使用,如果太小,出现网络波动就会影响服务质量,合理的设置一般是比如你的接口处理时间是200ms,那你可以设置300ms,比正常的响应时间大一点点,防止网络波动出现熔断

    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 300

    (2)Hystrix线程池大小设置:首先评估你的服务压力,比如你的服务每秒需要处理100个请求,每个请求的处理时间是200ms,相当于1个线程1秒可以处理5个请求,100/5=20,可以算出20个线程就可以处理请求,我们设置就可以设置25个线程,多给5个线程用来留些后路,防止一些特点时间点有大量的请求

    hystrix.threadpool.default.coreSize: 25

    三、最后

      应对高并发,最重要还是先要保证业务逻辑的处理速度,才能从根本上优化,比如进行SQL查询时,尽量避免多表关联,SQL语句越简单越好,数据表加索引,不要使用外键,外键会在一定程度上影响性能,且不容易维护,我个人建议通过增加其他表的id字段来维护表之间的关系

  • 相关阅读:
    怎样用一个3升的杯子和一个5升的杯子装出4升水来(杯子没有刻度)?
    HttpModule和Http Handler (比较与区别)
    Entity Framework 6新特性:全局性地自定义Code First约定
    ASP.NET MVC下的四种验证编程方式
    Json.Net
    JSON 序列化和反序列化——JavaScriptSerializer实现
    XML 命名空间(XML Namespaces)
    使用SQL Server存储ASP.NET Session变量
    ISV 和SI 是什么
    HTML,XML中的转义字符
  • 原文地址:https://www.cnblogs.com/orange911/p/10696835.html
Copyright © 2011-2022 走看看