<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 學以致用 <div style="text-indent:2em;"> <p>隨著第4章的慢慢接近尾聲,我們需要獲取一些接近我們日常工作的知識。因此,我們決定把一個真實的案例分成兩個章節的內容。在本章節中,你將學到如何結合所學的知識,基于一些假設,構建一個容錯的、可擴展的集群。由于本章主要講配置相關的內容,我們也將聚焦集群的配置。也許結構和數據有所不同,但是對面同樣的數據量集群處理檢索需求的解決方案也許對你有用。</p> <h3>假設</h3> <p>在進入到紛繁的配置細節之前,我們來做一些假設,我們將基于這些假設來配置我們的ElasticSearch集群。</p> <h4>數據規模和檢索性能需求</h4> <p>假設我們有一個在線圖書館,目前線上銷售100,000種各種語言的書籍。我們希望查詢請求的平均響應時間不高于200毫秒,這樣就能避免用戶在使用搜索服務時等待太長的時間,也能避免瀏覽器渲染頁面時等待太長時間。所以,現在來實現期望負載。我們做了一些性能測試(內容超出本書的范圍),而且我們測到如下方案性能最好:給集群分配4個節點,數據切分到兩個分片,而且每個分片掛載一個副本。</p> <!--note structure --> <div style="height:220px;width:650px;text-indent:0em;"> <div style="float:left;width:13px;height:100%; background:black;"> <img src="../lm.png" height="210px" width="13px" style="margin-top:5px;"/> </div> <div style="float:left;width:50px;height:100%;position:relative;"> <img src="../note.png" style="position:absolute; top:30%; "/> </div> <div style="float:left; width:550px;height:100%;"> <p style="font-size:13px;margin-top:5px;">讀者也許想自己做一些性能測試。如果自己做,可以選擇一些開源工具來模擬用戶發送查詢命令到集群中。比如,Apache JMeter(http://jmeter.apache.org/) 或者ActionGenerator(https://github.com/sematext/ActionGenerator) 。除此之外,還可以通過ElasticSearch提供的一些插件來查看統計記錄,比如paramedic(https://github.com/karmi/elasticsearch-paramedic) ,或者BigDesk(https://github.com/lukas-vlcek/bigdesk) ,或者直接使用功能完善的監測和報警解決方案,比如Sematext公司開發,用于ElasticSearch的SPM系統(http://sematext.com/spm/elasticsearch-performancemonitoring/index.html) 。所有的這些工具都會提供性能測試的圖示,幫助用戶找到系統的瓶頸。除了上面提到的工具,讀者可能還需要監控JVM垃圾收集器的工作以及操作系統的行為(上面提到的工具中有部分工具提供了相應的功能)。</p> </div> <div style="float:left;width:13px;height:100%;background:black;"> <img src="../rm.png" height="210px" width="13px" style="margin-top:5px;"/> </div> </div> <!-- end of note structure --> <p>因此,我們希望我們的集群與下圖類似:</p> <center><img src="../46-cluster.png"/></center> <p>當然,分片及分片副本真實的放置位置可能有所不同,但是背后的邏輯是一致的:即我們希望一節點一分片。</p> <h4>集群完整配置</h4> <p>接下來我們為集群創建配置信息,并詳細討論為什么要在集群中使用如下的屬性:</p> <blockquote style="text-indent:0;">cluster.name: books<br/> \# node configuration<br/> node.master: true<br/> node.data: true<br/> node.max\_local\_storage\_nodes: 1<br/> \# indices configuration<br/> index.number\_of\_shards: 2<br/> index.number\_of\_replicas: 1<br/> index.routing.allocation.total\_shards\_per\_node: 1<br/> \# instance paths<br/> path.conf: /usr/share/elasticsearch/conf<br/> path.plugins: /usr/share/elasticsearch/plugins<br/> path.data: /mnt/data/elasticsearch<br/> path.work: /usr/share/elasticsearch/work<br/> path.logs: /var/log/elasticsearch<br/> \# swapping<br/> bootstrap.mlockall: true<br/> \#gateway<br/> gateway.type: local<br/> gateway.recover\_after\_nodes: 3<br/> gateway.recover\_after\_time: 30s<br/> gateway.expected\_nodes: 4<br/> \# recovery<br/> cluster.routing.allocation.node\_initial\_primaries\_recoveries: 1<br/> cluster.routing.allocation.node\_concurrent\_recoveries: 1<br/> indices.recovery.concurrent\_streams: 8<br/> \# discovery<br/> discovery.zen.minimum\_master\_nodes: 3<br/> \# search and fetch logging<br/> index.search.slowlog.threshold.query.info: 500ms<br/> index.search.slowlog.threshold.query.debug: 100ms<br/> index.search.slowlog.threshold.fetch.info: 1s<br/> index.search.slowlog.threshold.fetch.debug: 200ms<br/> \# JVM gargabe collection work logging<br/> monitor.jvm.gc.ParNew.info: 700ms<br/> monitor.jvm.gc.ParNew.debug: 400ms<br/> monitor.jvm.gc.ConcurrentMarkSweep.info: 5s<br/> monitor.jvm.gc.ConcurrentMarkSweep.debug: 2s </blockquote> <p>接下來了解各個屬性值的意義。</p> <h4>節點層面的配置</h4> <p>在節點層面的配置中,我們指定了一個集群名字(使用cluster.name屬性)來標識我們的集群。如果在同一個網段中配置了多個集群,名字相同的節點會守護甜心連接成一個集群。接下來,這個特殊的節點會被選舉成主節點(用node.master:true屬性),而且該節點可以容納索引數據(node.data:true)。此外,通過設置node.max\_local\_storeage\_nodes屬性值為1,可以限制一個節點上最多能夠運行1個ElasticSearch實例。</p> <h4>索引的配置</h4> <p>由于我們只有一個索引,而且暫時也不打算添加更多的索引,我們決定設置分片的默認數量為2(用index.number\_of\_shards屬性),設置分片副本的默認數量為1(用index.number\_of\_replicas屬性)。此外,我們還設置了index.routing.allocation.total\_shards\_per\_node屬性值為1,這意味著對于每個索引,ElasticSearch只會在單個節點上分配一個分片。這應用到我們的4-節點集群的例子中就是每個節點會平均分配所有的分片。</p> <h4>各種目錄的規劃</h4> <p>我們已經把ElasticSearch安裝到了/usr/share/elasticsearch目錄,基于此,conf目錄、plugins目錄和工作目錄都在該目錄下。由于這個原因,我們把數據單獨指定到硬盤的一個地方,這個地方就是/mnt/data/elasticsearch掛載點。最后,我們把日志文件安置到/var/log/elasticsearch目錄。基于這樣的目錄規劃,我們在做配置的更新操作時,只需要關注/usr/share/elasticsearch目錄即可,無需接觸其它的目錄。</p> <h4>Gateway的配置</h4> <p>正如讀者所了解的,gateway是負責存儲索引和元數據的模塊。在本例中,我們選擇推薦的,也是唯一沒有廢棄的gateway類型,即local(gateway.type屬性)。我們說我們希望當集群只有三個節點時,恢復進程就啟動(gateway.recover\_after\_nodes屬性),同時至少3個節點相互連接30秒后開始恢復任務(用gateway.recover\_after\_time屬性)。此外,我們還可以通過設置gateway.expected\_nodes屬性值為4,用來通知ElasticSearch,我們的集群將由4個節點組成。</p> <h4>集群恢復機制</h4> <p>對于ElasticSearch來說,最核心的一種配置就是集群恢復配置。盡管它不是每天都會用到,正如你不會每天都重啟ElasticSearch,也不希望集群經常失效一樣。但是防范于未然是必須的。因此我們來討論一下用到的相關屬性。我們已經設置了 cluster.routing.allocation.node\_initial\_ primaries\_recoveries屬性為1,這意味著我們只允許每個節點同時恢復一個主分片。這沒有問題,因為每個服務器上只有一個節點。然而請記住這個操作基于gateway的local類型時會非常快,因此如果一個節點上有多個主分片時,不妨把這個值設置得大一點。 我們也設置了cluster. routing.allocation.node\_concurrent\_recoveries屬性值為1,再一次限制每個節點同時恢復的分片數量(我們的集群中每個節點只有一個分片,不會觸發這條屬性的紅線,但是如果每個節點不止一個分片,而且系統I/O允許時,我們可以把這個值設置得稍微大一點)。此外,我們也設置了indices.recovery.concurrent\_streams屬性值為8,這是因為在最初測試recovery過程時,我們了解到我們的網絡 和服務器在從對等的分片中恢復一個分片時能夠輕松地使用8個并發流,這也意味著我們可以同時讀取8個索引文件。 </p> <h4>節點發現機制</h4> <p>在集群的discovery模塊配置上,我們只需要設置一個屬性:設置discovery.zen.minimum\_master\_nodes屬性值為3。它指定了組成集群所需要的最少主節點候選節點數。這個值至少要設置成節點數的50%+1,在本例中就是3。它用來防止集群出現如下的狀況:由于某些節點的失效,部分節點的網絡連接會斷開,并形成一個與原集群一樣名字的集群(這種情況也稱為“集群腦裂”狀況)。這個問題非常危險,因為兩個新形成的集群會同時索引和修改集群的數據。 </p> <h4>記錄慢查詢日志</h4> <p>使用ElasticSearch時有件事情可能會很有用,那就是記錄查詢命令執行過程中一段時間或者更長的日志。記住這種日志并非記錄命令的整個執行時間,而是單個分片上的執行時間,即命令的部分執行時間。在本例中,我們用INFO級別的日志來記錄執行時間長于500毫秒的查詢命令以及執行時間長于1秒的real time get請求。在調試時,我們把這些值分別設置為100毫秒和200毫秒。如下的配置片段用于上述需求: <blockquote style="text-indent:0;"> index.search.slowlog.threshold.query.info: 500ms index.search.slowlog.threshold.query.debug: 100ms index.search.slowlog.threshold.fetch.info: 1s index.search.slowlog.threshold.fetch.debug: 200ms </blockquote> </p> <h4>記錄垃圾回收器的工作日志</h4> <p>最后,由于我們的集群沒有監控解決方案(至少剛開始沒有),我們想看到垃圾收集器的工作狀態。說得更清楚一點,我們希望看到垃圾回收器是否花了太多的時間,如果是,是在哪個時間段。為了實現這一需求,我們在elasticsearch.yml文件中添加下面的信息: <blockquote style="text-indent:0;"> monitor.jvm.gc.ParNew.info: 700ms monitor.jvm.gc.ParNew.debug: 400ms monitor.jvm.gc.ConcurrentMarkSweep.info: 5s monitor.jvm.gc.ConcurrentMarkSweep.debug: 2s </blockquote> 在INFO級別的日志中,ElasticSearch會把運行時間太長的垃圾回收過程的相關信息記錄下來,按照設置,閾值為 concurrent mark sweep收集器收集過程超過5秒,新生垃圾收集超過700毫秒。我們也添加了DEBUG級別的日志來應對debug需求和問題的修復。 </p> <!--note structure --> <div style="height:50px;width:650px;text-indent:0em;"> <div style="float:left;width:13px;height:100%; background:black;"> <img src="../lm.png" height="40px" width="13px" style="margin-top:5px;"/> </div> <div style="float:left;width:50px;height:100%;position:relative;"> <img src="../note.png" style="position:absolute; top:30%; "/> </div> <div style="float:left; width:550px;height:100%;"> <p style="font-size:13px;margin-top:5px;">如果不清楚什么是新生代垃圾回收,或者不清楚什么是concurrent mark sweep,請參考Oracle的Java文檔:http://www.oracle.com/technetwork/java/javase/ gc-tuning-6-140523.html. </p> </div> <div style="float:left;width:13px;height:100%;background:black;"> <img src="../rm.png" height="40px" width="13px" style="margin-top:5px;"/> </div> </div> <!-- end of note structure --> <h4>內存設置</h4> <p>直到現在我們都沒有提到RAM內存的設置,所以本節來學習這一知識點。假設每個節點都有16GB RAM。通常不推薦將JVM 堆內存設置高于可用內存的50%,本例也是如此。我們設置Java的Xms屬性值為8g,對于我們的應用來說應該夠用了。由于我們的索引數據量不大,而且由于不需要facet較高基于的域,所以就沒有parent-child關系型數據。在前面顯示的配置信息中,我們在ElasticSearch中也設置了垃圾回收器的相關參數,但是對于長期監測,最好使用專業的監控工具,比如SPM(http://sematext.com/spm/index.html )或者Munin(http://munin-monitoring.org/ )。</p> <!--note structure --> <div style="height:160px;width:650px;text-indent:0em;"> <div style="float:left;width:13px;height:100%; background:black;"> <img src="../lm.png" height="150px" width="13px" style="margin-top:5px;"/> </div> <div style="float:left;width:50px;height:100%;position:relative;"> <img src="../note.png" style="position:absolute; top:30%; "/> </div> <div style="float:left; width:550px;height:100%;"> <p style="font-size:13px;margin-top:5px;">我們已經提到通用的規則,即50%的物理內存用于JVM,余下的內存用于操作系統。就像其它絕大部分規則一樣,這條規則也適用于絕大部分的場景。但是我讓設想一下,我們的索引數據會占到30GB的硬盤空間,我們有128GB的RAM內存,但是考慮到parent-child關系型的數據量和高基數的域中進行faceting操作,如果分配到JVM的堆內存是64G就會有出現out-of-memory異常的風險。在這樣的安全中,是否依然只分配50%的可用內存空間呢?在我們看來,答案是NO,但這只適用于特殊的案例,前面提到從128G內存中JVM分配64G內存后,單個索引的數據量遠遠小于JVM中可用內存的大小,所以我們可以適當增加。但是一定要記住給操作系統留下足夠的內存以避免swapping的出現。 </p> </div> <div style="float:left;width:13px;height:100%;background:black;"> <img src="../rm.png" height="150px" width="13px" style="margin-top:5px;"/> </div> </div> <!-- end of note structure --> <h4>遺失的美好</h4> <p>還有一點沒有提到,就是bootstrap.mlockall屬性。該屬性能夠讓ElasticSearch將堆內存鎖住,并確保該塊內存不會被操作系統替換成虛擬內存。如果把bootstrap.mlockall設置為true,推薦用戶把ES\_MIN\_ME和ES\_MAX\_ME兩個屬性設置成相同的值。這樣做可以確保服務器有足夠的物理內存來啟動ElasticSearch,并且保留足夠的內存給操作系統讓系統流暢運行。我們將在第6章<i>應對突發事件</i> 的 <i>避免Unix-like操作系統的swapping操作</i>一節中了解更多的相關知識。</p> <h4>量變引起質變</h4> <p>假定現在我們的服務做得很成功。訪問的流量也逐步增長。而且,一家大公司希望跟我們合作。這家大的供應商不是賣自己的書,只是供貨給零售商。預計該公司大概會上線200萬種圖書,所以系統需要處理的數據量將是現在的20倍(只估算索引文檔的數量)。我們必須為這些變化作準備,也就是說要更改我們的ElasticSearch集群,使我們的用戶體驗能夠得到保持甚至提升現。我們需要做什么呢?先解決容易的事情。我們可以更改(增加或者減少)分片副本的數量,這無需做其它的工作。這樣做系統就可以同時執行更多的查詢命令,當然也會相應地增加集群的壓力。這樣做的缺點就是增加了額外的硬盤空間開銷。我們同時也要確保額外的分片副本可以分配到集群的節點上(參考<i>選擇恰當的分片數量和分片副本數量</i>一節中的那個公式)。還要記住性能測試的結論:作為結果的吞吐量指標永遠依賴于多個無法用數學公式刻畫的因素。 </p> <p>添加主分片怎么樣?前面已經提到,我們無法在線修改主分片的數量。如果我們事多分配分片,就為預期的數據增長預留了空間。但是在本例中,集群有2個主分片,應對100,000的數據足夠了。但是在短時間里對于2,100,000(已經處理的數據和將要添加進來的數據)的數據量來說太少。誰會預想到會這么成功呢?因此,必須設想一個可以處理數據增長的解決方案,但是又必須盡可能減少停服的時間,畢竟停服就意味著金錢的損失。</p> <h4>重新索引</h4> <p>第一個選擇就是刪除舊的索引,然后創建有更多分片的索引。這是最簡單解決辦法,但是在重新索引期間服務不可用。在本例中,準備用于添加到索引數據是一個耗時的過程,而且從數據庫中導入數據用的時間也很長。公司的經營者說在整個重新索引數據期間停止服務是不可行的。第二個想法是創建第二個索引,并且添加數據,然后把應用接口調轉到新的索引。方案可行,但是有個小問題,創建新的索引需要額外的空間開銷。當然,我們將擁有新的存儲空間更大的機器(我們需要索引新的“大數據”),但是在得到機器前,我們要解決耗時的任務。我們決定尋找其它的更簡單的解決方案。 </p> <h4>路由</h4> <p>也許我們的例子中用routing解決會很方便?顯而易見的收獲就是通過routing可以用查詢命令只返回我們數據集中的書籍,或者只返回屬于合作伙伴的書籍(因為routing允許我們只查詢部分索引)。然而,我們需要應用恰當的filter,routing不保證來自兩個數據源的數據不在同一個分片上出現。不幸的是,我們的例子中還有另一個死胡同,引入routing需要進行重新索引數據。因此,我們只得把這個解決方案扔到桌子邊的垃圾桶里。</p> <h4>多索引結構</h4> <p>讓我們從基本的問題開始,為什么我們只需要一個索引?為什么我們要改變當前的系統。答案是我們想要搜索所有的文檔,確定它們是來自于原始數據還是和作伙伴的數據。請注意ElasticSearch允許我們直接搜索多個索引。我們可以通過API端點使用多個索引,比如,/book,partner1/。我們還有一個靈巧的方法簡單快速添加另一個合作伙伴,無需改變現有集群,也無需停止服務。我們可以用過別名(aliases)創建虛擬索引,這樣就無需修改應用的源代碼。</p> <p>經過頭腦風暴,我們決定選擇最后一個解決方案,通過一些額外的改善使得ElasticSearch在索引數據時壓力不大。我們所做的就是禁止集群的刷新率,然后刪除分片副本。 <blockquote>curl -XPUT localhost:9200/books/\_settings -d '{ "index" : { "refresh\_interval" : -1, "number\_of\_replicas" : 0 } }'</blockquote> 當然,索引數據后我們變回它原來的值,唯一的一個問題就是ElasticSearch不允許在線改變索引的名字,這導致在配置文件中修改索引名稱時,會使用服務短時間停止一下。 </p> </div>
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看