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字段來維護表之間的關系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM