国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

這篇具有很好參考價(jià)值的文章主要介紹了微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

微服務(wù)03 分布式搜索引擎 elasticsearch ELK kibana RestAPI 索引庫 DSL查詢 RestClient 黑馬旅游

分布式搜索引擎03

1.數(shù)據(jù)聚合

聚合(aggregations)可以讓我們極其方便的實(shí)現(xiàn)對數(shù)據(jù)的統(tǒng)計(jì)、分析、運(yùn)算。例如:

  • 什么品牌的手機(jī)最受歡迎?

  • 這些手機(jī)的平均價(jià)格、最高價(jià)格、最低價(jià)格?

  • 這些手機(jī)每月的銷售情況如何?

實(shí)現(xiàn)這些統(tǒng)計(jì)功能的比數(shù)據(jù)庫的sql要方便的多,而且查詢速度非???/strong>,可以實(shí)現(xiàn)近實(shí)時(shí)搜索效果。

1.1.聚合的種類

聚合常見的有三類:

  • 桶(Bucket)聚合:用來對文檔做分組

  • TermAggregation:按照文檔字段值分組,例如按照品牌值分組、按照國家分組

  • Date Histogram:按照日期階梯分組,例如一周為一組,或者一月為一組

  • 度量(Metric)聚合:用以計(jì)算一些值,比如:最大值、最小值、平均值等

  • Avg:求平均

  • Max:求最

  • Min:求最

  • Stats:同時(shí)求max、min、avg、sum

  • 管道(pipeline)聚合:其它聚合的結(jié)果為基礎(chǔ)做聚合

注意: 參加聚合的字段必須是keyword、日期、數(shù)值、布爾類型( 不分詞

1.2.DSL實(shí)現(xiàn)聚合

現(xiàn)在,我們要統(tǒng)計(jì)所有數(shù)據(jù)中的酒店品牌有幾種,其實(shí)就是按照品牌對數(shù)據(jù)分組。此時(shí)可以根據(jù)酒店品牌的名稱做聚合,也就是Bucket聚合。

1.2.1.Bucket聚合語法

語法如下:

GET /hotel/_search
{
  "size": 0,  // 設(shè)置size為0,結(jié)果中不包含文檔,只包含聚合結(jié)果
  "aggs": { // 定義聚合
    "brandAgg": { //給聚合起個(gè)名字
      "terms": { // 聚合的類型,按照品牌值聚合,所以選擇term
        "field": "brand", // 參與聚合的字段
        "size": 20 // 希望獲取的聚合結(jié)果數(shù)量
      }
    }
  }
}

結(jié)果如圖:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.2.2.聚合結(jié)果排序

默認(rèn)情況下,Bucket聚合會(huì)統(tǒng)計(jì)Bucket內(nèi)的文檔數(shù)量,記為_count,并且按照_count降序排序。

我們可以指定order屬性,自定義聚合的排序方式:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "order": {
          "_count": "asc" // 按照_count升序排列
        },
        "size": 20
      }
    }
  }
}

1.2.3.限定聚合范圍

默認(rèn)情況下,Bucket聚合是對索引庫的所有文檔做聚合,但真實(shí)場景下,用戶會(huì)輸入搜索條件,因此聚合必須是對搜索結(jié)果聚合。那么聚合必須添加限定條件。

我們可以限定要聚合的文檔范圍,只要添加query條件即可:

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 200 // 只對200元以下的文檔聚合
      }
    }
  }, 
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

這次,聚合得到的品牌明顯變少了:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.2.4.Metric聚合語法

上節(jié)課,我們對酒店按照品牌分組,形成了一個(gè)個(gè)桶?,F(xiàn)在我們需要對桶內(nèi)的酒店做運(yùn)算,獲取每個(gè)品牌的用戶評分的min、max、avg等值。

這就要用到Metric聚合了,例如stat聚合:就可以獲取min、max、avg等結(jié)果。

語法如下:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": { 
      "terms": { 
        "field": "brand", 
        "size": 20
      },
      "aggs": { // 是brands聚合的子聚合,也就是分組后對每組分別計(jì)算
        "score_stats": { // 聚合名稱
          "stats": { // 聚合類型,這里stats可以計(jì)算min、max、avg等
            "field": "score" // 聚合字段,這里是score
          }
        }
      }
    }
  }
}

這次的score_stats聚合是在brandAgg的聚合內(nèi)部嵌套的子聚合。因?yàn)槲覀冃枰?span style="color:#c21c13;">在每個(gè)桶分別計(jì)算

另外,我們還可以給聚合結(jié)果做個(gè)排序,例如按照每個(gè)桶的酒店平均分做排序:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

這里面order可以寫多個(gè)條件 寫在后面的先執(zhí)行 不信可以試一下

1.2.5.小結(jié)

aggs代表聚合,與query同級,此時(shí)query的作用是?

  • 限定聚合的的文檔范圍

聚合必須的三要素

  • 聚合名稱

  • 聚合類型

  • 聚合字段

聚合可配置屬性有:

  • size:指定聚合結(jié)果數(shù)量

  • order:指定聚合結(jié)果排序方式

  • field:指定聚合字段

1.3.RestAPI實(shí)現(xiàn)聚合

1.3.1.API語法

聚合條件與query條件同級別,因此需要使用request.source()來指定聚合條件。

聚合條件的語法:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

聚合的結(jié)果也與查詢結(jié)果不同,API也比較特殊。不過同樣是JSON逐層解析:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.3.2.業(yè)務(wù)需求

需求:搜索頁面的品牌、城市等信息不應(yīng)該是在頁面寫死,而是通過聚合索引庫中的酒店數(shù)據(jù)得來的:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

分析:

目前,頁面的城市列表、星級列表、品牌列表都是寫死的,并不會(huì)隨著搜索結(jié)果的變化而變化。但是用戶搜索條件改變時(shí),搜索結(jié)果會(huì)跟著變化。

例如:用戶搜索“東方明珠”,那搜索的酒店肯定是在上海東方明珠附近,因此,城市只能是上海,此時(shí)城市列表中就不應(yīng)該顯示北京、深圳、杭州這些信息了。

也就是說,搜索結(jié)果中包含哪些城市,頁面就應(yīng)該列出哪些城市;搜索結(jié)果中包含哪些品牌,頁面就應(yīng)該列出哪些品牌。

如何得知搜索結(jié)果中包含哪些品牌?如何得知搜索結(jié)果中包含哪些城市?

使用聚合功能,利用Bucket聚合,對搜索結(jié)果中的文檔基于品牌分組、基于城市分組,就能得知包含哪些品牌、哪些城市了。

因?yàn)槭菍λ阉鹘Y(jié)果聚合,因此聚合是限定范圍的聚合,也就是說聚合的限定條件跟搜索文檔的條件一致。

查看瀏覽器可以發(fā)現(xiàn),前端其實(shí)已經(jīng)發(fā)出了這樣的一個(gè)請求

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

請求參數(shù)與搜索文檔的參數(shù)完全一致。

返回值類型就是頁面要展示的最終結(jié)果:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

結(jié)果是一個(gè)Map結(jié)構(gòu)

  • key是字符串,城市、星級、品牌、價(jià)格

  • value是集合,例如多個(gè)城市的名稱

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.3.3.業(yè)務(wù)實(shí)現(xiàn)

在cn.itcast.hotel.web包的HotelController中添加一個(gè)方法,遵循下面的要求:

  • 請求方式:POST

  • 請求路徑:/hotel/filters

  • 請求參數(shù):RequestParams,與搜索文檔的參數(shù)一致

  • 返回值類型:Map<String, List<String>>

代碼:


    @PostMapping("filters")
    public Map<String, List<String>> getFilters(@RequestBody RequestParams params){
        return hotelService.getFilters(params);
    }

這里調(diào)用了IHotelService中的getFilters方法,尚未實(shí)現(xiàn)。

在cn.itcast.hotel.service.IHotelService中定義新方法:

124集有坑 , map的key要put定義成為英文brand...的 和定義的字段對應(yīng)


Map<String, List<String>> filters(RequestParams params);

在cn.itcast.hotel.service.impl.HotelService中實(shí)現(xiàn)該方法:


@Override
public Map<String, List<String>> filters(RequestParams params) {
    try {
        // 1.準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        // 2.準(zhǔn)備DSL
        // 2.1.query
        buildBasicQuery(params, request);
        // 2.2.設(shè)置size
        request.source().size(0);
        // 2.3.聚合
        buildAggregation(request);
        // 3.發(fā)出請求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.解析結(jié)果
        Map<String, List<String>> result = new HashMap<>();
        Aggregations aggregations = response.getAggregations();
        // 4.1.根據(jù)品牌名稱,獲取品牌結(jié)果
        List<String> brandList = getAggByName(aggregations, "brandAgg");
        result.put("品牌", brandList);
        // 4.2.根據(jù)品牌名稱,獲取品牌結(jié)果
        List<String> cityList = getAggByName(aggregations, "cityAgg");
        result.put("城市", cityList);
        // 4.3.根據(jù)品牌名稱,獲取品牌結(jié)果
        List<String> starList = getAggByName(aggregations, "starAgg");
        result.put("星級", starList);

        return result;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private void buildAggregation(SearchRequest request) {
    request.source().aggregation(AggregationBuilders
                                 .terms("brandAgg")
                                 .field("brand")
                                 .size(100)
                                );
    request.source().aggregation(AggregationBuilders
                                 .terms("cityAgg")
                                 .field("city")
                                 .size(100)
                                );
    request.source().aggregation(AggregationBuilders
                                 .terms("starAgg")
                                 .field("starName")
                                 .size(100)
                                );
}

private List<String> getAggByName(Aggregations aggregations, String aggName) {
    // 4.1.根據(jù)聚合名稱獲取聚合結(jié)果
    Terms brandTerms = aggregations.get(aggName);
    // 4.2.獲取buckets
    List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
    // 4.3.遍歷
    List<String> brandList = new ArrayList<>();
    for (Terms.Bucket bucket : buckets) {
        // 4.4.獲取key
        String key = bucket.getKeyAsString();
        brandList.add(key);
    }
    return brandList;
}

2.自動(dòng)補(bǔ)全

當(dāng)用戶在搜索框輸入字符時(shí),我們應(yīng)該提示出與該字符有關(guān)的搜索項(xiàng),如圖:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

這種根據(jù)用戶輸入的字母,提示完整詞條的功能,就是自動(dòng)補(bǔ)全了。

因?yàn)樾枰鶕?jù)拼音字母來推斷,因此要用到拼音分詞功能。

2.1.拼音分詞器

要實(shí)現(xiàn)根據(jù)字母做補(bǔ)全,就必須對文檔按照拼音分詞。在GitHub上恰好有elasticsearch的拼音分詞插件。地址:GitHub - medcl/elasticsearch-analysis-pinyin: This Pinyin Analysis plugin is used to do conversion between Chinese characters and Pinyin.

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

課前資料中也提供了拼音分詞器的安裝包:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

安裝方式與IK分詞器一樣,分三步:

①解壓

上傳到虛擬機(jī)中,elasticsearch的plugin目錄

③重啟elasticsearch

④測試

詳細(xì)安裝步驟可以參考IK分詞器的安裝過程。

測試用法如下:

POST /_analyze
{
  "text": "如家酒店還不錯(cuò)",
  "analyzer": "pinyin"
}

結(jié)果:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2.2.自定義分詞器

默認(rèn)的拼音分詞器會(huì)將每個(gè)漢字單獨(dú)分為拼音,而我們希望的是每個(gè)詞條形成一組拼音,需要對拼音分詞器做個(gè)性化定制,形成自定義分詞器。

elasticsearch中分詞器(analyzer)的組成包含三部分:

  • character filters:在tokenizer之前對文本進(jìn)行處理。例如刪除字符、替換字符

  • tokenizer:

  • 將文本按照一定的規(guī)則切割成詞條(term)。例如keyword,就是不分詞;還有ik_smart

  • tokenizer filter:

  • tokenizer輸出的詞條做進(jìn)一步處理。例如大小寫轉(zhuǎn)換、同義詞處理、拼音處理等

文檔分詞時(shí)會(huì)依次由這三部分來處理文檔:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

聲明自定義分詞器的語法如下:

我們可以在創(chuàng)建索引庫時(shí),通過settings來配置自定義的analyzer (分詞器)

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": { // 自定義分詞器
        "my_analyzer": {  // 分詞器名稱
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": { // 自定義tokenizer filter
        "py": { // 過濾器名稱
          "type": "pinyin", // 過濾器類型,這里是pinyin
		  "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

測試:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

總結(jié):

如何使用拼音分詞器

  • ①下載pinyin分詞器

  • ②解壓并放到elasticsearch的plugin目錄

  • ③重啟即可

如何自定義分詞器?

  • ①創(chuàng)建索引庫時(shí),在settings中配置,可以包含三部分

  • ②character filter

  • ③tokenizer

  • ④filter

拼音分詞器注意事項(xiàng)?

  • 為了避免搜索到同音字,搜索時(shí)不要使用拼音分詞器

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

DELETE /test

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": { 
        "my_analyzer": { 
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": {
        "py": { 
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name":{
      "type":"text",
      "analyzer":"my_analyzer",
      "search_analyzer":"ik_smart"
      }
      }
  }
}

POST /test/_doc/1
{
  "id": 1,
  "name": "獅子"
}
POST /test/_doc/2
{
  "id": 2,
  "name": "虱子"
}

GET /test/_search
{
  "query": {
    "match": {
      "name": "掉入獅子籠咋辦"
    }
  }
}

"search_analyzer":"ik_smart" :這樣搜“掉入獅子籠咋辦”的時(shí)候就不會(huì)出來虱子

2.3.自動(dòng)補(bǔ)全查詢

elasticsearch提供了Completion Suggester查詢來實(shí)現(xiàn)自動(dòng)補(bǔ)全功能。這個(gè)查詢會(huì)匹配以用戶輸入內(nèi)容開頭的詞條并返回。為了提高補(bǔ)全查詢的效率,對于文檔中字段的類型有一些約束:

  • 參與補(bǔ)全查詢的字段必須是completion類型。

  • 字段的內(nèi)容一般是用來補(bǔ)全的多個(gè)詞條形成的數(shù)組。

比如,一個(gè)這樣的索引庫:

// 創(chuàng)建索引庫
PUT test
{
  "mappings": {
    "properties": {
      "title":{
        "type": "completion"
      }
    }
  }
}

然后插入下面的數(shù)據(jù):

// 示例數(shù)據(jù)
POST test/_doc
{
  "title": ["Sony", "WH-1000XM3"]
}
POST test/_doc
{
  "title": ["SK-II", "PITERA"]
}
POST test/_doc
{
  "title": ["Nintendo", "switch"]
}

查詢的DSL語句如下:

// 自動(dòng)補(bǔ)全查詢
GET /test/_search
{
  "suggest": {
    "title_suggest": {
      "text": "s", // 關(guān)鍵字
      "completion": {
        "field": "title", // 補(bǔ)全查詢的字段
        "skip_duplicates": true, // 跳過重復(fù)的
        "size": 10 // 獲取前10條結(jié)果
      }
    }
  }
}

2.4.實(shí)現(xiàn)酒店搜索框自動(dòng)補(bǔ)全

現(xiàn)在,我們的hotel索引庫還沒有設(shè)置拼音分詞器,需要修改索引庫中的配置。但是我們知道索引庫是無法修改的,只能刪除然后重新創(chuàng)建

另外,我們需要添加一個(gè)字段,用來做自動(dòng)補(bǔ)全,將brand、suggestion、city等都放進(jìn)去,作為自動(dòng)補(bǔ)全的提示。

因此,總結(jié)一下,我們需要做的事情包括:

  1. 修改hotel索引庫結(jié)構(gòu),設(shè)置自定義拼音分詞器

  1. 修改索引庫的name、all字段,使用自定義分詞器

  1. 索引庫添加一個(gè)新字段suggestion,類型為completion類型,使用自定義的分詞器

  1. 給HotelDoc類添加suggestion字段,內(nèi)容包含brand、business

  1. 重新導(dǎo)入數(shù)據(jù)到hotel庫

2.4.1.修改酒店映射結(jié)構(gòu)

代碼如下:

// 酒店數(shù)據(jù)索引庫
PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_anlyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword", //詞條 不分詞
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart",
        "copy_to": "all"
      },
      "address":{
        "type": "keyword",
        "index": false
      },
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      "brand":{
        "type": "keyword",
        "copy_to": "all"
      },
      "city":{
        "type": "keyword"
      },
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword",
        "copy_to": "all"
      },
      "location":{
        "type": "geo_point"
      },
      "pic":{
        "type": "keyword",
        "index": false
      },
      "all":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart"
      },
      "suggestion":{
          "type": "completion",
          "analyzer": "completion_analyzer"
      }
    }
  }
}

2.4.2.修改HotelDoc實(shí)體

HotelDoc中要添加一個(gè)字段,用來做自動(dòng)補(bǔ)全,內(nèi)容可以是酒店品牌、城市、商圈等信息。按照自動(dòng)補(bǔ)全字段的要求,最好是這些字段的數(shù)組。

因此我們在HotelDoc中添加一個(gè)suggestion字段,類型為List<String>,然后將brand、city、business等信息放到里面。

代碼如下:


package cn.itcast.hotel.pojo;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private Object distance;
    private Boolean isAD;
    private List<String> suggestion;

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
        // 組裝suggestion
        if(this.business.contains("/")){
            // business有多個(gè)值,需要切割
            String[] arr = this.business.split("/");
            // 添加元素
            this.suggestion = new ArrayList<>();
            this.suggestion.add(this.brand);
            Collections.addAll(this.suggestion, arr);
        }else {
            this.suggestion = Arrays.asList(this.brand, this.business);
        }
    }
}

2.4.3.重新導(dǎo)入

重新執(zhí)行之前編寫的導(dǎo)入數(shù)據(jù)功能,可以看到新的酒店數(shù)據(jù)中包含了suggestion:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2.4.4.自動(dòng)補(bǔ)全查詢的JavaAPI

之前我們學(xué)習(xí)了自動(dòng)補(bǔ)全查詢的DSL,而沒有學(xué)習(xí)對應(yīng)的JavaAPI,這里給出一個(gè)示例:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

自動(dòng)補(bǔ)全的結(jié)果也比較特殊,解析的代碼如下:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2.4.5.實(shí)現(xiàn)搜索框自動(dòng)補(bǔ)全

查看前端頁面,可以發(fā)現(xiàn)當(dāng)我們在輸入框鍵入時(shí),前端會(huì)發(fā)起ajax請求:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

返回值是補(bǔ)全詞條的集合,類型為List<String>

1)在cn.itcast.hotel.web包下的HotelController中添加新接口,接收新的請求


@GetMapping("suggestion")
public List<String> getSuggestions(@RequestParam("key") String prefix) {
    return hotelService.getSuggestions(prefix);
}

2)在cn.itcast.hotel.service包下的IhotelService中添加方法


List<String> getSuggestions(String prefix);

3)在cn.itcast.hotel.service.impl.HotelService中實(shí)現(xiàn)該方法:


@Override
public List<String> getSuggestions(String prefix) {
    try {
        // 1.準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        // 2.準(zhǔn)備DSL
        request.source().suggest(new SuggestBuilder().addSuggestion(
            "suggestions",
? ? ? ? ? ? ? ?//要補(bǔ)全的字段"suggestion"
            SuggestBuilders.completionSuggestion("suggestion")
            .prefix(prefix)//關(guān)鍵字
            .skipDuplicates(true)
            .size(10)//獲取前10條
        ));
        // 3.發(fā)起請求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.解析結(jié)果
        Suggest suggest = response.getSuggest();
        // 4.1.根據(jù)補(bǔ)全查詢名稱,獲取補(bǔ)全結(jié)果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        // 4.2.獲取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        // 4.3.遍歷
        List<String> list = new ArrayList<>(options.size());
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            list.add(text);
        }
        return list;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

3.數(shù)據(jù)同步

elasticsearch中的酒店數(shù)據(jù)來自于mysql數(shù)據(jù)庫,因此mysql數(shù)據(jù)發(fā)生改變時(shí),elasticsearch也必須跟著改變,這個(gè)就是elasticsearch與mysql之間的數(shù)據(jù)同步。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

3.1.思路分析

常見的數(shù)據(jù)同步方案有三種:

  • 同步調(diào)用

  • 異步通知

  • 監(jiān)聽binlog

3.1.1.同步調(diào)用

方案一:同步調(diào)用

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

基本步驟如下:

  • hotel-demo對外提供接口,用來修改elasticsearch中的數(shù)據(jù)

  • 酒店管理服務(wù)在完成數(shù)據(jù)庫操作后,直接調(diào)用hotel-demo提供的接口,

3.1.2.異步通知

方案二:異步通知

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

流程如下:

  • hotel-admin對mysql數(shù)據(jù)庫數(shù)據(jù)完成增、刪、改后,發(fā)送MQ消息

  • hotel-demo監(jiān)聽MQ,接收到消息后完成elasticsearch數(shù)據(jù)修改

3.1.3.監(jiān)聽binlog

方案三:監(jiān)聽binlog

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

流程如下:

  • 給mysql開啟binlog功能

  • mysql完成增、刪、改操作都會(huì)記錄在binlog

  • hotel-demo基于canal監(jiān)聽binlog變化,實(shí)時(shí)更新elasticsearch中的內(nèi)容

3.1.4.選擇

方式一:同步調(diào)用

  • 優(yōu)點(diǎn):實(shí)現(xiàn)簡單,粗暴

  • 缺點(diǎn):業(yè)務(wù)耦合度高

方式二:異步通知

  • 優(yōu)點(diǎn):低耦合,實(shí)現(xiàn)難度一般

  • 缺點(diǎn):依賴mq的可靠

方式三:監(jiān)聽binlog

  • 優(yōu)點(diǎn):完全解除服務(wù)間耦合

  • 缺點(diǎn):開啟binlog增加數(shù)據(jù)庫負(fù)擔(dān)、實(shí)現(xiàn)復(fù)雜度高

3.2.實(shí)現(xiàn)數(shù)據(jù)同步

3.2.1.思路

利用課前資料提供的hotel-admin項(xiàng)目作為酒店管理的微服務(wù)。

當(dāng)酒店數(shù)據(jù)發(fā)生增、刪、改時(shí),要求對elasticsearch中數(shù)據(jù)也要完成相同操作。

步驟:

  • 導(dǎo)入課前資料提供的hotel-admin項(xiàng)目,啟動(dòng)并測試酒店數(shù)據(jù)的CRUD

  • 聲明exchange、queue、RoutingKey

  • 在hotel-admin中的增、刪、改業(yè)務(wù)中完成消息發(fā)送

  • 在hotel-demo中完成消息監(jiān)聽,并更新elasticsearch中數(shù)據(jù)

  • 啟動(dòng)并測試數(shù)據(jù)同步功能

3.2.2.導(dǎo)入demo

導(dǎo)入課前資料提供的hotel-admin項(xiàng)目:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

運(yùn)行后,訪問 http://localhost:8099

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

其中包含了酒店的CRUD功能:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

3.2.3.聲明交換機(jī)、隊(duì)列

MQ結(jié)構(gòu)如圖:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
1)引入依賴

在hotel-admin、hotel-demo中引入rabbitmq的依賴:

<!--amqp-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2)聲明隊(duì)列交換機(jī)名稱

在hotel-admin和hotel-demo中的cn.itcast.hotel.constatnts包下新建一個(gè)類MqConstants:


package cn.itcast.hotel.constatnts;

    public class MqConstants {
    /**
     * 交換機(jī)
     */
    public final static String HOTEL_EXCHANGE = "hotel.topic";
    /**
     * 監(jiān)聽新增和修改的隊(duì)列
     */
    public final static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";
    /**
     * 監(jiān)聽刪除的隊(duì)列
     */
    public final static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";
    /**
     * 新增或修改的RoutingKey
     */
    public final static String HOTEL_INSERT_KEY = "hotel.insert";
    /**
     * 刪除的RoutingKey
     */
    public final static String HOTEL_DELETE_KEY = "hotel.delete";
}
3)聲明隊(duì)列交換機(jī)

在hotel-demo中,定義配置類,聲明隊(duì)列、交換機(jī)


package cn.itcast.hotel.config;

import cn.itcast.hotel.constants.MqConstants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqConfig {
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);
    }

    @Bean
    public Queue insertQueue(){
        return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);
    }

    @Bean
    public Queue deleteQueue(){
        return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);
    }

    @Bean
    public Binding insertQueueBinding(){
        return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);
    }

    @Bean
    public Binding deleteQueueBinding(){
        return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);
    }
}

3.2.4.發(fā)送MQ消息

在hotel-admin中的增、刪、改業(yè)務(wù)中分別發(fā)送MQ消息:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

3.2.5.接收MQ消息

hotel-demo接收到MQ消息要做的事情包括:

  • 新增消息:根據(jù)傳遞的hotel的id查詢hotel信息,然后新增一條數(shù)據(jù)到索引庫

  • 刪除消息:根據(jù)傳遞的hotel的id刪除索引庫中的一條數(shù)據(jù)

1)首先在hotel-demo的cn.itcast.hotel.service包下的IHotelService中新增新增、刪除業(yè)務(wù)


void deleteById(Long id);

void insertById(Long id);

2)給hotel-demo中的cn.itcast.hotel.service.impl包下的HotelService中實(shí)現(xiàn)業(yè)務(wù):


@Override
public void deleteById(Long id) {
    try {
        // 1.準(zhǔn)備Request
        DeleteRequest request = new DeleteRequest("hotel", id.toString());
        // 2.發(fā)送請求
        client.delete(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

@Override
public void insertById(Long id) {
    try {
        // 0.根據(jù)id查詢酒店數(shù)據(jù)
        Hotel hotel = getById(id);
        // 轉(zhuǎn)換為文檔類型
        HotelDoc hotelDoc = new HotelDoc(hotel);

        // 1.準(zhǔn)備Request對象
        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        // 2.準(zhǔn)備Json文檔
        request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        // 3.發(fā)送請求
        client.index(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

3)編寫監(jiān)聽器

在hotel-demo中的cn.itcast.hotel.mq包新增一個(gè)類:


package cn.itcast.hotel.mq;

import cn.itcast.hotel.constants.MqConstants;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class HotelListener {

    @Autowired
    private IHotelService hotelService;

    /**
     * 監(jiān)聽酒店新增或修改的業(yè)務(wù)
     * @param id 酒店id
     */
    @RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)
    public void listenHotelInsertOrUpdate(Long id){
        hotelService.insertById(id);
    }

    /**
     * 監(jiān)聽酒店刪除的業(yè)務(wù)
     * @param id 酒店id
     */
    @RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)
    public void listenHotelDelete(Long id){
        hotelService.deleteById(id);
    }
}

4.集群

單機(jī)的elasticsearch做數(shù)據(jù)存儲(chǔ),必然面臨兩個(gè)問題:海量數(shù)據(jù)存儲(chǔ)問題、單點(diǎn)故障問題。

  • 海量數(shù)據(jù)存儲(chǔ)問題:將索引庫從邏輯上拆分為N個(gè)分片(shard),存儲(chǔ)到多個(gè)節(jié)點(diǎn)

  • 單點(diǎn)故障問題:將分片數(shù)據(jù)在不同節(jié)點(diǎn)備份(replica )

ES集群相關(guān)概念:

  • 集群(cluster):一組擁有共同的 cluster name 的 節(jié)點(diǎn)。

  • 節(jié)點(diǎn)(node) :集群中的一個(gè) Elasticearch 實(shí)例

  • 分片(shard) :索引可以被拆分為不同的部分進(jìn)行存儲(chǔ),稱為分片。

  • 在集群環(huán)境下,一個(gè)索引的不同分片可以拆分到不同的節(jié)點(diǎn)

解決問題:數(shù)據(jù)量太大,單點(diǎn)存儲(chǔ)量有限的問題。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
此處,我們把數(shù)據(jù)分成3片:shard0、shard1、shard2
  • 主分片(Primary shard):相對于副本分片的定義

  • 副本分片(Replica shard)每個(gè)主分片可以有一個(gè)或者多個(gè)副本,數(shù)據(jù)和主分片一樣。

數(shù)據(jù)備份可以保證高可用,但是每個(gè)分片備份一份,所需要的節(jié)點(diǎn)數(shù)量就會(huì)翻一倍,成本實(shí)在是太高了!

為了在高可用和成本間尋求平衡,我們可以這樣做:

  • 首先對數(shù)據(jù)分片,存儲(chǔ)到不同節(jié)點(diǎn)

  • 然后對每個(gè)分片進(jìn)行備份,放到對方節(jié)點(diǎn),完成互相備份

這樣可以大大減少所需要的服務(wù)節(jié)點(diǎn)數(shù)量,如圖,我們以3分片,每個(gè)分片備份一份為例:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

現(xiàn)在,每個(gè)分片都有1個(gè)備份,存儲(chǔ)在3個(gè)節(jié)點(diǎn)

  • node0:保存了分片0和1

  • node1:保存了分片0和2

  • node2:保存了分片1和2

4.1.搭建ES集群

參考課前資料的文檔:

需要虛擬機(jī)內(nèi)存>4G;我的虛擬機(jī)2G 就沒做

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

其中的第四章節(jié):

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

4.2.集群腦裂問題

4.2.1.集群職責(zé)劃分

elasticsearch中集群節(jié)點(diǎn)有不同的職責(zé)劃分:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

默認(rèn)情況下,集群中的任何一個(gè)節(jié)點(diǎn)都同時(shí)具備上述四種角色。

但是真實(shí)的集群一定要將集群職責(zé)分離

  • master節(jié)點(diǎn):對CPU要求高,但是內(nèi)存要求不特別高

  • data節(jié)點(diǎn):對CPU和內(nèi)存要求都高

  • coordinating節(jié)點(diǎn):對網(wǎng)絡(luò)帶寬、CPU要求高

職責(zé)分離可以讓我們根據(jù)不同節(jié)點(diǎn)的需求分配不同的硬件去部署。而且避免業(yè)務(wù)之間的互相干擾。

一個(gè)典型的es集群職責(zé)劃分如圖:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

4.2.2.腦裂問題

腦裂是因?yàn)榧褐械墓?jié)點(diǎn)失聯(lián)導(dǎo)致的。

例如一個(gè)集群中,主節(jié)點(diǎn)與其它節(jié)點(diǎn)失聯(lián):

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

此時(shí),node2和node3認(rèn)為node1宕機(jī),就會(huì)重新選主

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

當(dāng)node3當(dāng)選后,集群繼續(xù)對外提供服務(wù),node2和node3自成集群,node1自成集群,兩個(gè)集群數(shù)據(jù)不同步,出現(xiàn)數(shù)據(jù)差異。

當(dāng)網(wǎng)絡(luò)恢復(fù)后,因?yàn)榧褐?span style="background-color:#e6d6f0;">有兩個(gè)master節(jié)點(diǎn),集群狀態(tài)的不一致,出現(xiàn)腦裂的情況:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

解決腦裂的方案是,要求選票超過 ( eligible節(jié)點(diǎn)數(shù)量 + 1 )/ 2 才能當(dāng)選為主,因此eligible節(jié)點(diǎn)數(shù)量最好是奇數(shù)。對應(yīng)配置項(xiàng)是discovery.zen.minimum_master_nodes,在es7.0以后,已經(jīng)成為默認(rèn)配置,因此一般不會(huì)發(fā)生腦裂問題

例如:3個(gè)節(jié)點(diǎn)形成的集群,選票必須超過 (3 + 1) / 2 ,也就是2票。node3得到node2和node3的選票,當(dāng)選為主。node1只有自己1票,沒有當(dāng)選。集群中依然只有1個(gè)主節(jié)點(diǎn),沒有出現(xiàn)腦裂。

4.2.3.小結(jié)

master eligible節(jié)點(diǎn)的作用是什么?

  • 參與集群選主

  • 主節(jié)點(diǎn)可以管理集群狀態(tài)、管理分片信息、處理創(chuàng)建和刪除索引庫的請求

data節(jié)點(diǎn)的作用是什么?

  • 數(shù)據(jù)的CRUD

coordinator節(jié)點(diǎn)的作用是什么?

  • 路由請求到其它節(jié)點(diǎn)

  • 合并查詢到的結(jié)果,返回給用戶

4.3.集群分布式存儲(chǔ)

當(dāng)新增文檔時(shí),應(yīng)該保存到不同分片,保證數(shù)據(jù)均衡,那么coordinating node如何確定數(shù)據(jù)該存儲(chǔ)到哪個(gè)分片呢?

4.3.1.分片存儲(chǔ)測試

插入三條數(shù)據(jù):

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

測試可以看到,三條數(shù)據(jù)分別在不同分片

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

結(jié)果:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

4.3.2.分片存儲(chǔ)原理

elasticsearch會(huì)通過hash算法來計(jì)算文檔應(yīng)該存儲(chǔ)到哪個(gè)分片

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

說明:

  • _routing默認(rèn)是文檔的id

  • 算法與分片數(shù)量(number_of_shards)有關(guān),因此索引庫一旦創(chuàng)建,分片數(shù)量不能修改!

新增文檔的流程如下:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

解讀:

  • 1)新增一個(gè)id=1的文檔

  • 2)對id做hash運(yùn)算,假如得到的是2,則應(yīng)該存儲(chǔ)到shard-2

  • 3)shard-2的主分片在node3節(jié)點(diǎn),將數(shù)據(jù)路由到node3

  • 4)保存文檔

  • 5)同步給shard-2的副本replica-2,在node2節(jié)點(diǎn)

  • 6)返回結(jié)果給coordinating-node節(jié)點(diǎn)

4.4.集群分布式查詢

elasticsearch的查詢分成兩個(gè)階段:

  • scatter phase:分散階段,coordinating node會(huì)把請求分發(fā)到每一個(gè)分片

  • gather phase:聚集階段,coordinating node匯總data node的搜索結(jié)果,并處理為最終結(jié)果集返回給用戶

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

4.5.集群故障轉(zhuǎn)移

集群的master節(jié)點(diǎn)會(huì)監(jiān)控集群中的節(jié)點(diǎn)狀態(tài),如果發(fā)現(xiàn)有節(jié)點(diǎn)宕機(jī),會(huì)立即將宕機(jī)節(jié)點(diǎn)的分片數(shù)據(jù)遷移到其它節(jié)點(diǎn),確保數(shù)據(jù)安全,這個(gè)叫做故障轉(zhuǎn)移。

1)例如一個(gè)集群結(jié)構(gòu)如圖:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

現(xiàn)在,node1是主節(jié)點(diǎn),其它兩個(gè)節(jié)點(diǎn)是從節(jié)點(diǎn)。

2)突然,node1發(fā)生了故障

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

宕機(jī)后的第一件事,需要重新選主,例如選中了node2:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

node2成為主節(jié)點(diǎn)后,會(huì)檢測集群監(jiān)控狀態(tài),發(fā)現(xiàn):shard-1、shard-0沒有副本節(jié)點(diǎn)。因此需要將node1上的數(shù)據(jù)遷移到node2、node3

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

微服務(wù)保護(hù)

1.初識Sentinel

1.1.雪崩問題及解決方案

1.1.1.雪崩問題

微服務(wù)中,服務(wù)間調(diào)用關(guān)系錯(cuò)綜復(fù)雜,一個(gè)微服務(wù)往往依賴于多個(gè)其它微服務(wù)。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

如圖,如果服務(wù)提供者I發(fā)生了故障,當(dāng)前的應(yīng)用的部分業(yè)務(wù)因?yàn)橐蕾囉诜?wù)I,因此也會(huì)被阻塞。此時(shí),其它不依賴于服務(wù)I的業(yè)務(wù)似乎不受影響。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

但是,依賴服務(wù)I的業(yè)務(wù)請求被阻塞,用戶不會(huì)得到響應(yīng),則tomcat的這個(gè)線程不會(huì)釋放,于是越來越多的用戶請求到來,越來越多的線程會(huì)阻塞

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

服務(wù)器支持的線程和并發(fā)數(shù)有限,請求一直阻塞,會(huì)導(dǎo)致服務(wù)器資源耗盡,從而導(dǎo)致所有其它服務(wù)都不可用,那么當(dāng)前服務(wù)也就不可用了。

那么,依賴于當(dāng)前服務(wù)的其它服務(wù)隨著時(shí)間的推移,最終也都會(huì)變的不可用,形成級聯(lián)失敗,雪崩就發(fā)生了:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.1.2.超時(shí)處理

解決雪崩問題的常見方式有四種:

?超時(shí)處理:設(shè)定超時(shí)時(shí)間,請求超過一定時(shí)間沒有響應(yīng)就返回錯(cuò)誤信息,不會(huì)無休止等待

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.1.3.倉壁模式

方案2:倉壁模式

倉壁模式來源于船艙的設(shè)計(jì),

船艙都會(huì)被隔板分離為多個(gè)獨(dú)立空間,當(dāng)船體破損時(shí),只會(huì)導(dǎo)致部分空間進(jìn)入,將故障控制在一定范圍內(nèi),避免整個(gè)船體都被淹沒

于此類似,我們可以限定每個(gè)業(yè)務(wù)能使用的線程數(shù),避免耗盡整個(gè)tomcat的資源,因此也叫線程隔離。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

缺點(diǎn):資源浪費(fèi),明明知道服務(wù)C掛了,請求來了還要嘗試訪問服務(wù)C占用線程;

1.1.4.斷路器

斷路器模式:

斷路器統(tǒng)計(jì)業(yè)務(wù)執(zhí)行的異常比例,如果超出閾值則會(huì)熔斷該業(yè)務(wù),攔截訪問該業(yè)務(wù)的一切請求。

斷路器會(huì)統(tǒng)計(jì)訪問某個(gè)服務(wù)的請求數(shù)量,異常比例

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

當(dāng)發(fā)現(xiàn)訪問服務(wù)D的請求異常比例過高時(shí),認(rèn)為服務(wù)D有導(dǎo)致雪崩的風(fēng)險(xiǎn),會(huì)攔截訪問服務(wù)D的一切請求,形成熔斷

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.1.5.限流

流量控制限制業(yè)務(wù)訪問的QPS(每秒處理請求的數(shù)量),避免服務(wù)因流量的突增而故障

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.1.6.總結(jié)

什么是雪崩問題?

  • 微服務(wù)之間相互調(diào)用,因?yàn)?span style="color:#116af0;">調(diào)用鏈中的一個(gè)服務(wù)故障,引起整個(gè)鏈路都無法訪問的情況。

可以認(rèn)為:

限流對服務(wù)的保護(hù),避免因瞬間高并發(fā)流量而導(dǎo)致服務(wù)故障,進(jìn)而避免雪崩。是一種預(yù)防措施。

超時(shí)處理、線程隔離、降級熔斷是在部分服務(wù)故障時(shí),將故障控制在一定范圍,避免雪崩。是一種補(bǔ)救措施。

1.2.服務(wù)保護(hù)技術(shù)對比

在SpringCloud當(dāng)中支持多種服務(wù)保護(hù)技術(shù):

  • Netfix Hystrix

  • Sentinel

  • Resilience4J

早期比較流行的是Hystrix框架(已經(jīng)停止升級與維護(hù)),但目前國內(nèi)實(shí)用最廣泛的還是阿里巴巴的Sentinel框架,這里我們做下對比:

Sentinel

Hystrix

隔離策略

信號量隔離

線程池隔離/信號量隔離

熔斷降級策略

基于慢調(diào)用比例或異常比例

基于失敗比率

實(shí)時(shí)指標(biāo)實(shí)現(xiàn)

滑動(dòng)窗口

滑動(dòng)窗口(基于 RxJava)

規(guī)則配置

支持多種數(shù)據(jù)源

支持多種數(shù)據(jù)源

擴(kuò)展性

多個(gè)擴(kuò)展點(diǎn)

插件的形式

基于注解的支持

支持

支持

限流

基于 QPS,支持基于調(diào)用關(guān)系的限流

有限的支持

流量整形

支持慢啟動(dòng)、勻速排隊(duì)模式

不支持

系統(tǒng)自適應(yīng)保護(hù)

支持

不支持

控制臺(tái)

開箱即用,可配置規(guī)則、查看秒級監(jiān)控、機(jī)器發(fā)現(xiàn)等

不完善

常見框架的適配

Servlet、Spring Cloud、Dubbo、gRPC 等

Servlet、Spring Cloud Netflix

1.3.Sentinel介紹和安裝

1.3.1.初識Sentinel

Sentinel是阿里巴巴開源的一款微服務(wù)流量控制組件。

官網(wǎng)地址:home | Sentinel

Sentinel 具有以下特征:

?豐富的應(yīng)用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、集群流量控制、實(shí)時(shí)熔斷下游不可用應(yīng)用等。

?完備的實(shí)時(shí)監(jiān)控:Sentinel 同時(shí)提供實(shí)時(shí)的監(jiān)控功能。您可以在控制臺(tái)中看到接入應(yīng)用的單臺(tái)機(jī)器秒級數(shù)據(jù),甚至 500 臺(tái)以下規(guī)模的集群的匯總運(yùn)行情況。

?廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 SpringCloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速地接入 Sentinel。

?完善的 SPI 擴(kuò)展點(diǎn):Sentinel 提供簡單易用、完善的 SPI 擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯。例如定制規(guī)則管理、適配動(dòng)態(tài)數(shù)據(jù)源等。

1.3.2.安裝Sentinel

1)下載

sentinel官方提供了UI控制臺(tái),方便我們對系統(tǒng)做限流設(shè)置。大家可以在GitHub下載。

課前資料也提供了下載好的jar包:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2)運(yùn)行

將jar包放到任意非中文目錄,執(zhí)行命令:


java -jar sentinel-dashboard-1.8.1.jar

如果要修改Sentinel的默認(rèn)端口、賬戶、密碼,可以通過下列配置:

配置項(xiàng)

默認(rèn)值

說明

server.port

8080

服務(wù)端口

sentinel.dashboard.auth.username

sentinel

默認(rèn)用戶名

sentinel.dashboard.auth.password

sentinel

默認(rèn)密碼

例如,修改端口:

報(bào)錯(cuò)的要,配置jdk8的環(huán)境變量;set Path=D:\ItheimaJava\jdk1.8.0_361\bin

報(bào)錯(cuò)的在控制臺(tái)先指定jdk版本。set Path=你的jdk里jre位置\bin

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

java -Dserver.port=8090 -jar sentinel-dashboard-1.8.1.jar

3)訪問

訪問http://localhost:8080頁面,就可以看到sentinel的控制臺(tái)了:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

需要輸入賬號和密碼,默認(rèn)都是:sentinel

登錄后,發(fā)現(xiàn)一片空白,什么都沒有:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

這是因?yàn)槲覀冞€沒有與微服務(wù)整合。

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

修改的話 就-Dserver.port=8090;或者

在jar包目錄寫一個(gè)配置文件就可以了;在包下寫個(gè)yml 配個(gè)server port 就會(huì)覆蓋了

jar包同級的同名配置文件,優(yōu)先級比 classpath要高的呀,可以在jar包同級目錄里創(chuàng)建配置文件的

更詳細(xì)的修改配置

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

1.4.微服務(wù)整合Sentinel

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel
微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

先停一下,前面的項(xiàng)目沒跑,得跑一下,要不直接做黑馬點(diǎn)評吧,感這種“假”微服務(wù)沒意義

我們在order-service中整合sentinel,并連接sentinel的控制臺(tái),步驟如下:

1)引入sentinel依賴

<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId> 
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2)配置控制臺(tái)

修改application.yaml文件,添加下面內(nèi)容:

server:
  port: 8088
spring:
  cloud: 
    sentinel:
      transport:
        dashboard: localhost:8080

3)訪問order-service的任意端點(diǎn)

打開瀏覽器,訪問http://localhost:8088/order/101,這樣才能觸發(fā)sentinel的監(jiān)控。

然后再訪問sentinel的控制臺(tái),查看效果:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2.流量控制

雪崩問題雖然有四種方案,但是限流是避免服務(wù)因突發(fā)的流量而發(fā)生故障,是對微服務(wù)雪崩問題的預(yù)防。我們先學(xué)習(xí)這種模式。

2.1.簇點(diǎn)鏈路

當(dāng)請求進(jìn)入微服務(wù)時(shí),首先會(huì)訪問DispatcherServlet,然后進(jìn)入Controller、Service、Mapper,這樣的一個(gè)調(diào)用鏈就叫做簇點(diǎn)鏈路。簇點(diǎn)鏈路中被監(jiān)控的每一個(gè)接口就是一個(gè)資源

默認(rèn)情況下sentinel會(huì)監(jiān)控SpringMVC的每一個(gè)端點(diǎn)(Endpoint,也就是controller中的方法),因此SpringMVC的每一個(gè)端點(diǎn)(Endpoint)就是調(diào)用鏈路中的一個(gè)資源。

例如,我們剛才訪問的order-service中的OrderController中的端點(diǎn):/order/{orderId}

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

流控、熔斷等都是針對簇點(diǎn)鏈路中的資源來設(shè)置的,因此我們可以點(diǎn)擊對應(yīng)資源后面的按鈕來設(shè)置規(guī)則:

  • 流控:流量控制

  • 降級:降級熔斷

  • 熱點(diǎn):熱點(diǎn)參數(shù)限流,是限流的一種

  • 授權(quán):請求的權(quán)限控制

2.1.快速入門

2.1.1.示例

點(diǎn)擊資源/order/{orderId}后面的流控按鈕,就可以彈出表單。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

表單中可以填寫限流規(guī)則,如下:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

其含義是限制 /order/{orderId}這個(gè)資源的單機(jī)QPS為1,即每秒只允許1次請求,超出的請求會(huì)被攔截并報(bào)錯(cuò)。

2.1.2.練習(xí):

需求:給 /order/{orderId}這個(gè)資源設(shè)置流控規(guī)則,QPS不能超過 5,然后測試。

1)首先在sentinel控制臺(tái)添加限流規(guī)則微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)利用jmeter測試

如果沒有用過jmeter,可以參考課前資料提供的文檔《Jmeter快速入門.md》

課前資料提供了編寫好的Jmeter測試樣例:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

打開jmeter,導(dǎo)入課前資料提供的測試樣例:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

選擇:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

20個(gè)用戶,2秒內(nèi)運(yùn)行完,QPS是10,超過了5.

選中流控入門,QPS<5右鍵運(yùn)行:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

注意,不要點(diǎn)擊菜單中的執(zhí)行按鈕來運(yùn)行。

結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

可以看到,成功的請求每次只有5個(gè)

2.2.流控模式

在添加限流規(guī)則時(shí),點(diǎn)擊高級選項(xiàng),可以選擇三種流控模式

  • 直接:統(tǒng)計(jì)當(dāng)前資源的請求,觸發(fā)閾值時(shí)對當(dāng)前資源直接限流,也是默認(rèn)的模式

  • 關(guān)聯(lián):統(tǒng)計(jì)與當(dāng)前資源相關(guān)的另一個(gè)資源,觸發(fā)閾值時(shí),對當(dāng)前資源限流

  • 鏈路:統(tǒng)計(jì)從指定鏈路訪問到本資源的請求,觸發(fā)閾值時(shí),對指定鏈路限流

快速入門測試的就是直接模式。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2.2.1.關(guān)聯(lián)模式

關(guān)聯(lián)模式:統(tǒng)計(jì)與當(dāng)前資源相關(guān)的另一個(gè)資源,觸發(fā)閾值時(shí),對當(dāng)前資源限流

配置規(guī)則微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

語法說明:當(dāng)/write資源訪問量觸發(fā)閾值時(shí),就會(huì)對/read資源限流,避免影響/write資源。

使用場景:比如用戶支付時(shí)需要修改訂單狀態(tài),同時(shí)用戶要查詢訂單。查詢和修改操作會(huì)爭搶數(shù)據(jù)庫鎖,產(chǎn)生競爭。業(yè)務(wù)需求是優(yōu)先支付和更新訂單的業(yè)務(wù),因此當(dāng)修改訂單業(yè)務(wù)觸發(fā)閾值時(shí),需要對查詢訂單業(yè)務(wù)限流。

需求說明

  • 在OrderController新建兩個(gè)端點(diǎn):/order/query和/order/update,無需實(shí)現(xiàn)業(yè)務(wù)

  • 配置流控規(guī)則,當(dāng)/order/ update資源被訪問的QPS超過5時(shí),對/order/query請求限流

1)定義/order/query端點(diǎn),模擬訂單查詢


@GetMapping("/query")
public String queryOrder() {
    return "查詢訂單成功";
}

2)定義/order/update端點(diǎn),模擬訂單更新


@GetMapping("/update")
public String updateOrder() {
    return "更新訂單成功";
}

重啟服務(wù),查看sentinel控制臺(tái)的簇點(diǎn)鏈路:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

3)配置流控規(guī)則

對哪個(gè)端點(diǎn)限流,就點(diǎn)擊哪個(gè)端點(diǎn)后面的按鈕。我們是對訂單查詢/order/query限流,因此點(diǎn)擊它后面的按鈕:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

在表單中填寫流控規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

4)在Jmeter測試

選擇《流控模式-關(guān)聯(lián)》:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

可以看到1000個(gè)用戶,100秒,因此QPS為10,超過了我們設(shè)定的閾值:5

查看http請求:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

請求的目標(biāo)是/order/update,這樣這個(gè)斷點(diǎn)就會(huì)觸發(fā)閾值。

但限流的目標(biāo)是/order/query,我們在瀏覽器訪問,可以發(fā)現(xiàn):微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

確實(shí)被限流了。

5)總結(jié)微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2.2.2.鏈路模式

鏈路模式:只針對從指定鏈路訪問到本資源的請求做統(tǒng)計(jì),判斷是否超過閾值。

配置示例

例如有兩條請求鏈路:

  • /test1 --> /common

  • /test2 --> /common

如果只希望統(tǒng)計(jì)從/test2進(jìn)入到/common的請求,則可以這樣配置:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

實(shí)戰(zhàn)案例

需求:有查詢訂單和創(chuàng)建訂單業(yè)務(wù),兩者都需要查詢商品。針對從查詢訂單進(jìn)入到查詢商品的請求統(tǒng)計(jì),并設(shè)置限流。

步驟:

  1. 在OrderService中添加一個(gè)queryGoods方法,不用實(shí)現(xiàn)業(yè)務(wù)

  2. 在OrderController中,改造/order/query端點(diǎn),調(diào)用OrderService中的queryGoods方法

  3. 在OrderController中添加一個(gè)/order/save的端點(diǎn),調(diào)用OrderService的queryGoods方法

  4. 給queryGoods設(shè)置限流規(guī)則,從/order/query進(jìn)入queryGoods的方法限制QPS必須小于2

實(shí)現(xiàn):

1)添加查詢商品方法

在order-service服務(wù)中,給OrderService類添加一個(gè)queryGoods方法:


public void queryGoods(){
    System.err.println("查詢商品");
}
2)查詢訂單時(shí),查詢商品

在order-service的OrderController中,修改/order/query端點(diǎn)的業(yè)務(wù)邏輯:


@GetMapping("/query")
public String queryOrder() {
    // 查詢商品
    orderService.queryGoods();
    // 查詢訂單
    System.out.println("查詢訂單");
    return "查詢訂單成功";
}
3)新增訂單,查詢商品

在order-service的OrderController中,修改/order/save端點(diǎn),模擬新增訂單:


@GetMapping("/save")
public String saveOrder() {
    // 查詢商品
    orderService.queryGoods();
    // 查詢訂單
    System.err.println("新增訂單");
    return "新增訂單成功";
}
4)給查詢商品添加資源標(biāo)記

默認(rèn)情況下,OrderService中的方法是不被Sentinel監(jiān)控的,需要我們自己通過注解來標(biāo)記要監(jiān)控的方法。

給OrderService的queryGoods方法添加@SentinelResource注解:


@SentinelResource("goods")
public void queryGoods(){
    System.err.println("查詢商品");
}

鏈路模式中,是對不同來源的兩個(gè)鏈路做監(jiān)控。但是sentinel默認(rèn)會(huì)給進(jìn)入SpringMVC的所有請求設(shè)置同一個(gè)root資源,會(huì)導(dǎo)致鏈路模式失效。

我們需要關(guān)閉這種對SpringMVC的資源聚合,修改order-service服務(wù)的application.yml文件:

spring:
  cloud:
    sentinel:
      web-context-unify: false # 關(guān)閉context整合

重啟服務(wù),訪問/order/query和/order/save,可以查看到sentinel的簇點(diǎn)鏈路規(guī)則中,出現(xiàn)了新的資源:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

5)添加流控規(guī)則

點(diǎn)擊goods資源后面的流控按鈕,在彈出的表單中填寫下面信息:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

只統(tǒng)計(jì)從/order/query進(jìn)入/goods的資源,QPS閾值為2,超出則被限流。

6)Jmeter測試

選擇《流控模式-鏈路》:

?微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

可以看到這里200個(gè)用戶,50秒內(nèi)發(fā)完,QPS為4,超過了我們設(shè)定的閾值2

一個(gè)http請求是訪問/order/save:

?微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

運(yùn)行的結(jié)果:

?微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

完全不受影響。

另一個(gè)是訪問/order/query:

?微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

運(yùn)行結(jié)果:

?微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

每次只有2個(gè)通過。

2.2.3.總結(jié)

流控模式有哪些?

?直接:對當(dāng)前資源限流

?關(guān)聯(lián):高優(yōu)先級資源觸發(fā)閾值,對低優(yōu)先級資源限流。

?鏈路:閾值統(tǒng)計(jì)時(shí),只統(tǒng)計(jì)從指定資源進(jìn)入當(dāng)前資源的請求,是對請求來源的限流

2.3.流控效果

在流控的高級選項(xiàng)中,還有一個(gè)流控效果選項(xiàng):微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

流控效果是指請求達(dá)到流控閾值時(shí)應(yīng)該采取的措施,包括三種:

  • 快速失?。哼_(dá)到閾值后,新的請求會(huì)被立即拒絕并拋出FlowException異常。是默認(rèn)的處理方式。

  • warm up:預(yù)熱模式,對超出閾值的請求同樣是拒絕并拋出異常。但這種模式閾值會(huì)動(dòng)態(tài)變化,從一個(gè)較小值逐漸增加到最大閾值。

  • 排隊(duì)等待:讓所有的請求按照先后次序排隊(duì)執(zhí)行,兩個(gè)請求的間隔不能小于指定時(shí)長

2.3.1.warm up

閾值一般是一個(gè)微服務(wù)能承擔(dān)的最大QPS,但是一個(gè)服務(wù)剛剛啟動(dòng)時(shí),一切資源尚未初始化(冷啟動(dòng)),如果直接將QPS跑到最大值,可能導(dǎo)致服務(wù)瞬間宕機(jī)。

warm up也叫預(yù)熱模式,是應(yīng)對服務(wù)冷啟動(dòng)的一種方案。請求閾值初始值是 maxThreshold / coldFactor,持續(xù)指定時(shí)長后,逐漸提高到maxThreshold值。而coldFactor的默認(rèn)值是3.

例如,我設(shè)置QPS的maxThreshold為10,預(yù)熱時(shí)間為5秒,那么初始閾值就是 10 / 3 ,也就是3,然后在5秒后逐漸增長到10.微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

案例

需求:給/order/{orderId}這個(gè)資源設(shè)置限流,最大QPS為10,利用warm up效果,預(yù)熱時(shí)長為5秒

1)配置流控規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)Jmeter測試

選擇《流控效果,warm up》:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

QPS為10.

剛剛啟動(dòng)時(shí),大部分請求失敗,成功的只有3個(gè),說明QPS被限定在3:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

隨著時(shí)間推移,成功比例越來越高:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

到Sentinel控制臺(tái)查看實(shí)時(shí)監(jiān)控:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel?

?

一段時(shí)間后:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

2.3.2.排隊(duì)等待

當(dāng)請求超過QPS閾值時(shí),快速失敗和warm up 會(huì)拒絕新的請求并拋出異常。

而排隊(duì)等待則是讓所有請求進(jìn)入一個(gè)隊(duì)列中,然后按照閾值允許的時(shí)間間隔依次執(zhí)行。后來的請求必須等待前面執(zhí)行完成,如果請求預(yù)期的等待時(shí)間超出最大時(shí)長,則會(huì)被拒絕。

工作原理

例如:QPS = 5,意味著每200ms處理一個(gè)隊(duì)列中的請求;timeout = 2000,意味著預(yù)期等待時(shí)長超過2000ms的請求會(huì)被拒絕并拋出異常。

那什么叫做預(yù)期等待時(shí)長呢?

比如現(xiàn)在一下子來了12 個(gè)請求,因?yàn)槊?00ms執(zhí)行一個(gè)請求,那么:

  • 第6個(gè)請求的預(yù)期等待時(shí)長 = 200 * (6 - 1) = 1000ms

  • 第12個(gè)請求的預(yù)期等待時(shí)長 = 200 * (12-1) = 2200ms

現(xiàn)在,第1秒同時(shí)接收到10個(gè)請求,但第2秒只有1個(gè)請求,此時(shí)QPS的曲線這樣的:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

如果使用隊(duì)列模式做流控,所有進(jìn)入的請求都要排隊(duì),以固定的200ms的間隔執(zhí)行,QPS會(huì)變的很平滑:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

平滑的QPS曲線,對于服務(wù)器來說是更友好的。

案例

需求:給/order/{orderId}這個(gè)資源設(shè)置限流,最大QPS為10,利用排隊(duì)的流控效果,超時(shí)時(shí)長設(shè)置為5s

1)添加流控規(guī)則微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)Jmeter測試

選擇《流控效果,隊(duì)列》:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

QPS為15,已經(jīng)超過了我們設(shè)定的10。

如果是之前的 快速失敗、warmup模式,超出的請求應(yīng)該會(huì)直接報(bào)錯(cuò)。

但是我們看看隊(duì)列模式的運(yùn)行結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

全部都通過了。

再去sentinel查看實(shí)時(shí)監(jiān)控的QPS曲線:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

QPS非常平滑,一致保持在10,但是超出的請求沒有被拒絕,而是放入隊(duì)列。因此響應(yīng)時(shí)間(等待時(shí)間)會(huì)越來越長。

當(dāng)隊(duì)列滿了以后,才會(huì)有部分請求失?。?img src="https://imgs.yssmx.com/Uploads/2023/06/511487-110.png" alt="微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel" referrerpolicy="no-referrer" />

?

2.3.3.總結(jié)

流控效果有哪些?

  • 快速失?。篞PS超過閾值時(shí),拒絕新的請求

  • warm up: QPS超過閾值時(shí),拒絕新的請求;QPS閾值是逐漸提升的,可以避免冷啟動(dòng)時(shí)高并發(fā)導(dǎo)致服務(wù)宕機(jī)。

  • 排隊(duì)等待:請求會(huì)進(jìn)入隊(duì)列,按照閾值允許的時(shí)間間隔依次執(zhí)行請求;如果請求預(yù)期等待時(shí)長大于超時(shí)時(shí)間,直接拒絕

2.4.熱點(diǎn)參數(shù)限流

之前的限流是統(tǒng)計(jì)訪問某個(gè)資源的所有請求,判斷是否超過QPS閾值。而熱點(diǎn)參數(shù)限流是分別統(tǒng)計(jì)參數(shù)值相同的請求,判斷是否超過QPS閾值。

2.4.1.全局參數(shù)限流

例如,一個(gè)根據(jù)id查詢商品的接口:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

訪問/goods/{id}的請求中,id參數(shù)值會(huì)有變化,熱點(diǎn)參數(shù)限流會(huì)根據(jù)參數(shù)值分別統(tǒng)計(jì)QPS,統(tǒng)計(jì)結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

當(dāng)id=1的請求觸發(fā)閾值被限流時(shí),id值不為1的請求不受影響。

配置示例:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

代表的含義是:對hot這個(gè)資源的0號參數(shù)(第一個(gè)參數(shù))做統(tǒng)計(jì),每1秒相同參數(shù)值的請求數(shù)不能超過5

2.4.2.熱點(diǎn)參數(shù)限流

剛才的配置中,對查詢商品這個(gè)接口的所有商品一視同仁,QPS都限定為5.

而在實(shí)際開發(fā)中,可能部分商品是熱點(diǎn)商品,例如秒殺商品,我們希望這部分商品的QPS限制與其它商品不一樣,高一些。那就需要配置熱點(diǎn)參數(shù)限流的高級選項(xiàng)了:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

結(jié)合上一個(gè)配置,這里的含義是對0號的long類型參數(shù)限流,每1秒相同參數(shù)的QPS不能超過5,有兩個(gè)例外:

?如果參數(shù)值是100,則每1秒允許的QPS為10

?如果參數(shù)值是101,則每1秒允許的QPS為15

2.4.4.案例

案例需求:給/order/{orderId}這個(gè)資源添加熱點(diǎn)參數(shù)限流,規(guī)則如下:

?默認(rèn)的熱點(diǎn)參數(shù)規(guī)則是每1秒請求量不超過2

?給102這個(gè)參數(shù)設(shè)置例外:每1秒請求量不超過4

?給103這個(gè)參數(shù)設(shè)置例外:每1秒請求量不超過10

注意事項(xiàng):熱點(diǎn)參數(shù)限流對默認(rèn)的SpringMVC資源無效,需要利用@SentinelResource注解標(biāo)記資源

1)標(biāo)記資源

給order-service中的OrderController中的/order/{orderId}資源添加注解:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)熱點(diǎn)參數(shù)限流規(guī)則

訪問該接口,可以看到我們標(biāo)記的hot資源出現(xiàn)了:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

這里不要點(diǎn)擊hot后面的按鈕,頁面有BUG

點(diǎn)擊左側(cè)菜單中熱點(diǎn)規(guī)則菜單:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

點(diǎn)擊新增,填寫表單:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

3)Jmeter測試

選擇《熱點(diǎn)參數(shù)限流 QPS1》:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

這里發(fā)起請求的QPS為5.

包含3個(gè)http請求:

普通參數(shù),QPS閾值為2微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

運(yùn)行結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

例外項(xiàng),QPS閾值為4微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

運(yùn)行結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

例外項(xiàng),QPS閾值為10微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

運(yùn)行結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

3.隔離和降級

限流是一種預(yù)防措施,雖然限流可以盡量避免因高并發(fā)而引起的服務(wù)故障,但服務(wù)還會(huì)因?yàn)槠渌蚨收稀?/p>

而要將這些故障控制在一定范圍,避免雪崩,就要靠線程隔離(艙壁模式)和熔斷降級手段了。

線程隔離之前講到過:調(diào)用者在調(diào)用服務(wù)提供者時(shí),給每個(gè)調(diào)用的請求分配獨(dú)立線程池,出現(xiàn)故障時(shí),最多消耗這個(gè)線程池內(nèi)資源,避免把調(diào)用者的所有資源耗盡。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

熔斷降級:是在調(diào)用方這邊加入斷路器,統(tǒng)計(jì)對服務(wù)提供者的調(diào)用,如果調(diào)用的失敗比例過高,則熔斷該業(yè)務(wù),不允許訪問該服務(wù)的提供者了。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

可以看到,不管是線程隔離還是熔斷降級,都是對客戶端(調(diào)用方)的保護(hù)。需要在調(diào)用方 發(fā)起遠(yuǎn)程調(diào)用時(shí)做線程隔離、或者服務(wù)熔斷。

而我們的微服務(wù)遠(yuǎn)程調(diào)用都是基于Feign來完成的,因此我們需要將Feign與Sentinel整合,在Feign里面實(shí)現(xiàn)線程隔離和服務(wù)熔斷。

3.1.FeignClient整合Sentinel

SpringCloud中,微服務(wù)調(diào)用都是通過Feign來實(shí)現(xiàn)的,因此做客戶端保護(hù)必須整合Feign和Sentinel。

3.1.1.修改配置,開啟sentinel功能

修改OrderService的application.yml文件,開啟Feign的Sentinel功能:

feign:
  sentinel:
    enabled: true # 開啟feign對sentinel的支持

3.1.2.編寫失敗降級邏輯

業(yè)務(wù)失敗后,不能直接報(bào)錯(cuò),而應(yīng)該返回用戶一個(gè)友好提示或者默認(rèn)結(jié)果,這個(gè)就是失敗降級邏輯。

給FeignClient編寫失敗后的降級邏輯

①方式一:FallbackClass,無法對遠(yuǎn)程調(diào)用的異常做處理

②方式二:FallbackFactory,可以對遠(yuǎn)程調(diào)用的異常做處理,我們選擇這種

這里我們演示方式二的失敗降級處理。

步驟一:在feing-api項(xiàng)目中定義類,實(shí)現(xiàn)FallbackFactory:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

代碼:


package cn.itcast.feign.clients.fallback;

import cn.itcast.feign.clients.UserClient;
import cn.itcast.feign.pojo.User;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable throwable) {
        return new UserClient() {
            @Override
            public User findById(Long id) {
                log.error("查詢用戶異常", throwable);
                return new User();
            }
        };
    }
}

步驟二:在feing-api項(xiàng)目中的DefaultFeignConfiguration類中將UserClientFallbackFactory注冊為一個(gè)Bean:


@Bean
public UserClientFallbackFactory userClientFallbackFactory(){
    return new UserClientFallbackFactory();
}

步驟三:在feing-api項(xiàng)目中的UserClient接口中使用UserClientFallbackFactory:


import cn.itcast.feign.clients.fallback.UserClientFallbackFactory;
import cn.itcast.feign.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

重啟后,訪問一次訂單查詢業(yè)務(wù),然后查看sentinel控制臺(tái),可以看到新的簇點(diǎn)鏈路:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

3.1.3.總結(jié)

Sentinel支持的雪崩解決方案:

  • 線程隔離(倉壁模式)

  • 降級熔斷

Feign整合Sentinel的步驟:

  • 在application.yml中配置:feign.sentienl.enable=true

  • 給FeignClient編寫FallbackFactory并注冊為Bean

  • 將FallbackFactory配置到FeignClient

3.2.線程隔離(艙壁模式)

3.2.1.線程隔離的實(shí)現(xiàn)方式

線程隔離有兩種方式實(shí)現(xiàn):

  • 線程池隔離

  • 信號量隔離(Sentinel默認(rèn)采用)

如圖:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

線程池隔離:給每個(gè)服務(wù)調(diào)用業(yè)務(wù)分配一個(gè)線程池,利用線程池本身實(shí)現(xiàn)隔離效果

信號量隔離:不創(chuàng)建線程池,而是計(jì)數(shù)器模式,記錄業(yè)務(wù)使用的線程數(shù)量,達(dá)到信號量上限時(shí),禁止新的請求。

兩者的優(yōu)缺點(diǎn):微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

3.2.2.sentinel的線程隔離

用法說明

在添加限流規(guī)則時(shí),可以選擇兩種閾值類型:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

  • QPS:就是每秒的請求數(shù),在快速入門中已經(jīng)演示過

  • 線程數(shù):是該資源能使用用的tomcat線程數(shù)的最大值。也就是通過限制線程數(shù)量,實(shí)現(xiàn)線程隔離(艙壁模式)。

案例需求:給 order-service服務(wù)中的UserClient的查詢用戶接口設(shè)置流控規(guī)則,線程數(shù)不能超過 2。然后利用jemeter測試。

1)配置隔離規(guī)則

選擇feign接口后面的流控按鈕:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

填寫表單:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)Jmeter測試

選擇《閾值類型-線程數(shù)<2》:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

一次發(fā)生10個(gè)請求,有較大概率并發(fā)線程數(shù)超過2,而超出的請求會(huì)走之前定義的失敗降級邏輯。

查看運(yùn)行結(jié)果:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

發(fā)現(xiàn)雖然結(jié)果都是通過了,不過部分請求得到的響應(yīng)是降級返回的null信息。

3.2.3.總結(jié)

線程隔離的兩種手段是?

  • 信號量隔離

  • 線程池隔離

信號量隔離的特點(diǎn)是?

  • 基于計(jì)數(shù)器模式,簡單,開銷小

線程池隔離的特點(diǎn)是?

  • 基于線程池模式,有額外開銷,但隔離控制更強(qiáng)

3.3.熔斷降級

熔斷降級是解決雪崩問題的重要手段。其思路是由斷路器統(tǒng)計(jì)服務(wù)調(diào)用的異常比例、慢請求比例,如果超出閾值則會(huì)熔斷該服務(wù)。即攔截訪問該服務(wù)的一切請求;而當(dāng)服務(wù)恢復(fù)時(shí),斷路器會(huì)放行訪問該服務(wù)的請求。

斷路器控制熔斷和放行是通過狀態(tài)機(jī)來完成的:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

狀態(tài)機(jī)包括三個(gè)狀態(tài):

  • closed:關(guān)閉狀態(tài),斷路器放行所有請求,并開始統(tǒng)計(jì)異常比例、慢請求比例。超過閾值則切換到open狀態(tài)

  • open:打開狀態(tài),服務(wù)調(diào)用被熔斷,訪問被熔斷服務(wù)的請求會(huì)被拒絕,快速失敗,直接走降級邏輯。Open狀態(tài)5秒后會(huì)進(jìn)入half-open狀態(tài)

  • half-open:半開狀態(tài),放行一次請求,根據(jù)執(zhí)行結(jié)果來判斷接下來的操作。

  • 請求成功:則切換到closed狀態(tài)

  • 請求失敗:則切換到open狀態(tài)

斷路器熔斷策略有三種:慢調(diào)用、異常比例、異常數(shù)

3.3.1.慢調(diào)用

慢調(diào)用:業(yè)務(wù)的響應(yīng)時(shí)長(RT)大于指定時(shí)長的請求認(rèn)定為慢調(diào)用請求。在指定時(shí)間內(nèi),如果請求數(shù)量超過設(shè)定的最小數(shù)量,慢調(diào)用比例大于設(shè)定的閾值,則觸發(fā)熔斷。

例如:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

解讀:RT超過500ms的調(diào)用是慢調(diào)用,統(tǒng)計(jì)最近10000ms內(nèi)的請求,如果請求量超過10次,并且慢調(diào)用比例不低于0.5,則觸發(fā)熔斷,熔斷時(shí)長為5秒。然后進(jìn)入half-open狀態(tài),放行一次請求做測試。

案例

需求:給 UserClient的查詢用戶接口設(shè)置降級規(guī)則,慢調(diào)用的RT閾值為50ms,統(tǒng)計(jì)時(shí)間為1秒,最小請求數(shù)量為5,失敗閾值比例為0.4,熔斷時(shí)長為5

1)設(shè)置慢調(diào)用

修改user-service中的/user/{id}這個(gè)接口的業(yè)務(wù)。通過休眠模擬一個(gè)延遲時(shí)間:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

此時(shí),orderId=101的訂單,關(guān)聯(lián)的是id為1的用戶,調(diào)用時(shí)長為60ms:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

orderId=102的訂單,關(guān)聯(lián)的是id為2的用戶,調(diào)用時(shí)長為非常短;微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

2)設(shè)置熔斷規(guī)則

下面,給feign接口設(shè)置降級規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

超過50ms的請求都會(huì)被認(rèn)為是慢請求

3)測試

在瀏覽器訪問:http://localhost:8088/order/101,快速刷新5次,可以發(fā)現(xiàn):微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

觸發(fā)了熔斷,請求時(shí)長縮短至5ms,快速失敗了,并且走降級邏輯,返回的null

在瀏覽器訪問:http://localhost:8088/order/102,竟然也被熔斷了:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

3.3.2.異常比例、異常數(shù)

異常比例或異常數(shù):統(tǒng)計(jì)指定時(shí)間內(nèi)的調(diào)用,如果調(diào)用次數(shù)超過指定請求數(shù),并且出現(xiàn)異常的比例達(dá)到設(shè)定的比例閾值(或超過指定異常數(shù)),則觸發(fā)熔斷。

例如,一個(gè)異常比例設(shè)置:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

解讀:統(tǒng)計(jì)最近1000ms內(nèi)的請求,如果請求量超過10次,并且異常比例不低于0.4,則觸發(fā)熔斷。

一個(gè)異常數(shù)設(shè)置:

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

解讀:統(tǒng)計(jì)最近1000ms內(nèi)的請求,如果請求量超過10次,并且異常比例不低于2次,則觸發(fā)熔斷。

案例

需求:給 UserClient的查詢用戶接口設(shè)置降級規(guī)則,統(tǒng)計(jì)時(shí)間為1秒,最小請求數(shù)量為5,失敗閾值比例為0.4,熔斷時(shí)長為5s

1)設(shè)置異常請求

首先,修改user-service中的/user/{id}這個(gè)接口的業(yè)務(wù)。手動(dòng)拋出異常,以觸發(fā)異常比例的熔斷:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

也就是說,id 為 2時(shí),就會(huì)觸發(fā)異常

2)設(shè)置熔斷規(guī)則

下面,給feign接口設(shè)置降級規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

在5次請求中,只要異常比例超過0.4,也就是有2次以上的異常,就會(huì)觸發(fā)熔斷。

3)測試

在瀏覽器快速訪問:http://localhost:8088/order/102,快速刷新5次,觸發(fā)熔斷:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

此時(shí),我們?nèi)ピL問本來應(yīng)該正常的103:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

4.授權(quán)規(guī)則

授權(quán)規(guī)則可以對請求方來源做判斷和控制。

4.1.授權(quán)規(guī)則

4.1.1.基本規(guī)則

授權(quán)規(guī)則可以對調(diào)用方的來源做控制,有白名單和黑名單兩種方式。

  • 白名單:來源(origin)在白名單內(nèi)的調(diào)用者允許訪問

  • 黑名單:來源(origin)在黑名單內(nèi)的調(diào)用者不允許訪問

點(diǎn)擊左側(cè)菜單的授權(quán),可以看到授權(quán)規(guī)則:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

  • 資源名:就是受保護(hù)的資源,例如/order/{orderId}

  • 流控應(yīng)用:是來源者的名單,

  • 如果是勾選白名單,則名單中的來源被許可訪問。

  • 如果是勾選黑名單,則名單中的來源被禁止訪問。

比如:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

我們允許請求從gateway到order-service,不允許瀏覽器訪問order-service,那么白名單中就要填寫網(wǎng)關(guān)的來源名稱(origin)。

4.1.2.如何獲取origin

Sentinel是通過RequestOriginParser這個(gè)接口的parseOrigin來獲取請求的來源的。


public interface RequestOriginParser {
    /**
     * 從請求request對象中獲取origin,獲取方式自定義
     */
    String parseOrigin(HttpServletRequest request);
}

這個(gè)方法的作用就是從request對象中,獲取請求者的origin值并返回。

默認(rèn)情況下,sentinel不管請求者從哪里來,返回值永遠(yuǎn)是default,也就是說一切請求的來源都被認(rèn)為是一樣的值default。

因此,我們需要自定義這個(gè)接口的實(shí)現(xiàn),讓不同的請求,返回不同的origin。

例如order-service服務(wù)中,我們定義一個(gè)RequestOriginParser的實(shí)現(xiàn)類:


package cn.itcast.order.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 1.獲取請求頭
        String origin = request.getHeader("origin");
        // 2.非空判斷
        if (StringUtils.isEmpty(origin)) {
            origin = "blank";
        }
        return origin;
    }
}

我們會(huì)嘗試從request-header中獲取origin值。

4.1.3.給網(wǎng)關(guān)添加請求頭

既然獲取請求origin的方式是從reques-header中獲取origin值,我們必須讓所有從gateway路由到微服務(wù)的請求都帶上origin頭。

這個(gè)需要利用之前學(xué)習(xí)的一個(gè)GatewayFilter來實(shí)現(xiàn),AddRequestHeaderGatewayFilter。

修改gateway服務(wù)中的application.yml,添加一個(gè)defaultFilter:

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=origin,gateway
      routes:
       # ...略

這樣,從gateway路由的所有請求都會(huì)帶上origin頭,值為gateway。而從其它地方到達(dá)微服務(wù)的請求則沒有這個(gè)頭。

4.1.4.配置授權(quán)規(guī)則

接下來,我們添加一個(gè)授權(quán)規(guī)則,放行origin值為gateway的請求。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

配置如下:

現(xiàn)在,我們直接跳過網(wǎng)關(guān),訪問order-service服務(wù):微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

通過網(wǎng)關(guān)訪問:微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

?

4.2.自定義異常結(jié)果

默認(rèn)情況下,發(fā)生限流、降級、授權(quán)攔截時(shí),都會(huì)拋出異常到調(diào)用方。異常結(jié)果都是flow limmiting(限流)。這樣不夠友好,無法得知是限流還是降級還是授權(quán)攔截。

4.2.1.異常類型

而如果要自定義異常時(shí)的返回結(jié)果,需要實(shí)現(xiàn)BlockExceptionHandler接口:


public interface BlockExceptionHandler {
    /**
     * 處理請求被限流、降級、授權(quán)攔截時(shí)拋出的異常:BlockException
     */
    void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}

這個(gè)方法有三個(gè)參數(shù):

  • HttpServletRequest request:request對象

  • HttpServletResponse response:response對象

  • BlockException e:被sentinel攔截時(shí)拋出的異常

這里的BlockException包含多個(gè)不同的子類:

異常

說明

FlowException

限流異常

ParamFlowException

熱點(diǎn)參數(shù)限流的異常

DegradeException

降級異常

AuthorityException

授權(quán)規(guī)則異常

SystemBlockException

系統(tǒng)規(guī)則異常

4.2.2.自定義異常處理

下面,我們就在order-service定義一個(gè)自定義異常處理類:


package cn.itcast.order.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = "未知異常";
        int status = 429;

        if (e instanceof FlowException) {
            msg = "請求被限流了";
        } else if (e instanceof ParamFlowException) {
            msg = "請求被熱點(diǎn)參數(shù)限流";
        } else if (e instanceof DegradeException) {
            msg = "請求被降級了";
        } else if (e instanceof AuthorityException) {
            msg = "沒有權(quán)限訪問";
            status = 401;
        }

        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status);
        response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
    }
}

重啟測試,在不同場景下,會(huì)返回不同的異常消息.

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

5.規(guī)則持久化

現(xiàn)在,sentinel的所有規(guī)則都是內(nèi)存存儲(chǔ),重啟后所有規(guī)則都會(huì)丟失。在生產(chǎn)環(huán)境下,我們必須確保這些規(guī)則的持久化,避免丟失。

5.1.規(guī)則管理模式

規(guī)則是否能持久化,取決于規(guī)則管理模式,sentinel支持三種規(guī)則管理模式:

  • 原始模式:Sentinel的默認(rèn)模式,將規(guī)則保存在內(nèi)存,重啟服務(wù)會(huì)丟失。

  • pull模式

  • push模式

5.1.1.pull模式

pull模式:控制臺(tái)將配置的規(guī)則推送到Sentinel客戶端,而客戶端會(huì)將配置規(guī)則保存在本地文件或數(shù)據(jù)庫中。以后會(huì)定時(shí)去本地文件或數(shù)據(jù)庫中查詢,更新本地規(guī)則。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

5.1.2.push模式

push模式:控制臺(tái)將配置規(guī)則推送到遠(yuǎn)程配置中心,例如Nacos。Sentinel客戶端監(jiān)聽Nacos,獲取配置變更的推送消息,完成本地配置更新。微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

5.2.實(shí)現(xiàn)push模式

詳細(xì)步驟可以參考課前資料的《sentinel規(guī)則持久化》:文章來源地址http://www.zghlxwxcb.cn/news/detail-511487.html

微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel

到了這里,關(guān)于微服務(wù)04 分布式搜索引擎 elasticsearch DSL數(shù)據(jù)聚合 自動(dòng)補(bǔ)全 數(shù)據(jù)同步 集群 Sentinel的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 微服務(wù)分布式搜索引擎 ElasticSearch 查詢文檔

    微服務(wù)分布式搜索引擎 ElasticSearch 查詢文檔

    本文參考黑馬 分布式Elastic search Elasticsearch是一款非常強(qiáng)大的開源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容 ElasticSearch 的查詢依然是基于 JSON風(fēng)格的DSL 來實(shí)現(xiàn)的。 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)來定義查詢。常見的

    2023年04月15日
    瀏覽(31)
  • 黑馬程序員微服務(wù) 分布式搜索引擎3

    黑馬程序員微服務(wù) 分布式搜索引擎3

    **聚合(aggregations)**可以讓我們極其方便的實(shí)現(xiàn)對數(shù)據(jù)的統(tǒng)計(jì)、分析、運(yùn)算。例如: 什么品牌的手機(jī)最受歡迎? 這些手機(jī)的平均價(jià)格、最高價(jià)格、最低價(jià)格? 這些手機(jī)每月的銷售情況如何? 實(shí)現(xiàn)這些統(tǒng)計(jì)功能的比數(shù)據(jù)庫的sql要方便的多,而且查詢速度非??欤梢詫?shí)現(xiàn)近

    2024年02月03日
    瀏覽(21)
  • 微服務(wù) 分布式搜索引擎 Elastic Search RestAPI

    微服務(wù) 分布式搜索引擎 Elastic Search RestAPI

    本文參考黑馬 分布式Elastic search Elasticsearch是一款非常強(qiáng)大的開源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容 ES官方提供了各種不同語言的客戶端,用來操作ES。這些客戶端的本質(zhì)就是組裝DSL語句,通過http請求發(fā)送給ES。官方文檔地址:

    2024年01月24日
    瀏覽(25)
  • 微服務(wù)一實(shí)用篇:分布式搜索引擎(ElasticSearch)基礎(chǔ)解析

    微服務(wù)一實(shí)用篇:分布式搜索引擎(ElasticSearch)基礎(chǔ)解析

    學(xué)習(xí)分布式搜索引擎(ElasticSearch)的基礎(chǔ)知識,包括初識ElasticSearch、倒排索引、ES的一些概念、安裝和分詞器等。

    2024年02月16日
    瀏覽(21)
  • 微服務(wù)分布式搜索引擎 ElasticSearch 搜索結(jié)果處理 排序、分頁與高亮

    微服務(wù)分布式搜索引擎 ElasticSearch 搜索結(jié)果處理 排序、分頁與高亮

    本文參考黑馬 分布式Elastic search Elasticsearch是一款非常強(qiáng)大的開源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容 搜索結(jié)果處理 搜索的結(jié)果可以按照用戶指定的方式去處理或展示。 elasticsearch默認(rèn)是根據(jù)相關(guān)度算分(_score)來排序,但是也支

    2024年02月02日
    瀏覽(44)
  • 微服務(wù)分布式搜索引擎 Elastic Search RestClient 操作文檔

    微服務(wù)分布式搜索引擎 Elastic Search RestClient 操作文檔

    本文參考黑馬 分布式Elastic search Elasticsearch是一款非常強(qiáng)大的開源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容 初始化RestHighLevelClient 為了與索引庫操作分離,我們再次參加一個(gè)測試類,做兩件事情: 初始化RestHighLevelClient 我們的酒店數(shù)據(jù)

    2024年01月24日
    瀏覽(25)
  • 分布式搜索引擎

    分布式搜索引擎

    elasticsearch的查詢依然是基于JSON風(fēng)格的DSL來實(shí)現(xiàn)的。 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)來定義查詢。常見的查詢類型包括: 查詢所有 :查詢出所有數(shù)據(jù),一般測試用。例如:match_all 全文檢索(full text)查詢 :利用分詞器對用戶輸入內(nèi)容分詞,然后去倒排索

    2024年02月10日
    瀏覽(25)
  • 火山引擎云搜索服務(wù)升級云原生新架構(gòu);提供數(shù)十億級分布式向量數(shù)據(jù)庫能力

    火山引擎云搜索服務(wù)升級云原生新架構(gòu);提供數(shù)十億級分布式向量數(shù)據(jù)庫能力

    從互聯(lián)網(wǎng)發(fā)展伊始,搜索技術(shù)就綻放出了驚人的社會(huì)和經(jīng)濟(jì)價(jià)值。隨著信息社會(huì)快速發(fā)展,數(shù)據(jù)呈爆炸式增長,搜索技術(shù)通過數(shù)據(jù)收集與處理,滿足信息共享與快速檢索的需求。 云搜索服務(wù) ESCloud 是火山引擎提供的 完全托管在線分布式搜索服務(wù) ,兼容 Elasticsearch、Kibana 等軟

    2024年02月16日
    瀏覽(30)
  • 分布式搜索引擎ElasticSearch——搜索功能

    分布式搜索引擎ElasticSearch——搜索功能

    DSL查詢分類 DSL官方文檔 全文檢索查詢 精確查詢 地理查詢 復(fù)合查詢 Function Score Query function score query Boolean Query 排序 分頁 官方文檔 高亮 快速入門 match,term,range,bool查詢 排序和分頁 高亮顯示 就是在前面抽取的解析代碼中進(jìn)一步添加關(guān)于高亮的解析部分,因?yàn)閔ighlight和so

    2024年02月01日
    瀏覽(28)
  • 分布式搜索引擎——elasticsearch搜索功能

    分布式搜索引擎——elasticsearch搜索功能

    Elasticsearch提供了基于JSON的DSL (Domain Specific Language)來定義查詢。常見的查詢類型包括: 查詢所有:查詢出所有數(shù)據(jù),一般測試用。例如:match_all 全文檢索(full text)查詢:利用分詞器對用戶輸入內(nèi)容分詞,然后去倒排索引庫中匹配。例如: match_query multi_match_query 精確查詢:根據(jù)精確詞條

    2024年02月05日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包