【Elasticsearch】硬件資源優化

🧑 博主簡介:CSDN博客專家歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/?__c=1000,移動端可微信小程序搜索“歷代文學”)總架構師,15年工作經驗,精通Java編程高并發設計Springboot和微服務,熟悉LinuxESXI虛擬化以及云原生Docker和K8s,熱衷于探索科技的邊界,并將理論知識轉化為實際應用。保持對新技術的好奇心,樂于分享所學,希望通過我的實踐經歷和見解,啟發他人的創新思維。在這里,我希望能與志同道合的朋友交流探討,共同進步,一起在技術的世界里不斷學習成長。
技術合作請加本人wx(注明來自csdn):foreast_sea

在這里插入圖片描述


在這里插入圖片描述

【Elasticsearch 】硬件資源優化

引言

在當今數字化飛速發展的時代,數據量呈爆炸式增長,如何高效地存儲、檢索和分析這些海量數據成為了眾多開發者和企業面臨的關鍵挑戰。Elasticsearch 作為一款強大的分布式搜索引擎,憑借其高擴展性、實時搜索和分析能力,在眾多領域得到了廣泛應用。然而,要充分發揮 Elasticsearch 的性能優勢,合理優化硬件資源是必不可少的一環。

想象一下,你正在負責一個大型電商平臺的搜索功能開發,每天都有海量的商品數據需要索引和存儲,同時還要應對高并發的用戶查詢請求。如果硬件資源配置不合理,可能會出現搜索響應時間過長、系統頻繁卡頓甚至崩潰等問題,這無疑會嚴重影響用戶體驗,進而對業務造成巨大損失。

又或者,你在處理一個日志分析項目,需要對大量的系統日志進行快速檢索和分析,以便及時發現潛在的問題和安全隱患。若硬件資源無法滿足 Elasticsearch 的需求,那么分析結果的及時性和準確性都會大打折扣,無法為企業的決策提供有力支持。

正是基于這些實際場景中的痛點,深入了解 Elasticsearch 對硬件資源的需求與依賴關系,并掌握相應的優化策略顯得尤為重要。本文將圍繞 Java Elasticsearch 的硬件資源優化展開全面探討,從 CPU、內存、磁盤 I/O 到網絡帶寬,詳細闡述如何根據數據量與查詢負載的規模合理規劃硬件配置,以及如何通過優化內存分配、磁盤存儲設置等方面提升系統性能,確保 Elasticsearch 在各種復雜環境下都能穩定高效運行。

一、Elasticsearch 硬件資源基礎認知

1.1 Elasticsearch 架構概述

Elasticsearch 采用分布式架構,由多個節點組成集群。每個節點都可以存儲數據、處理請求。其中,有主節點負責集群的管理和協調,數據節點負責實際的數據存儲和檢索,協調節點負責接收客戶端請求并將其轉發到合適的數據節點。這種分布式架構使得 Elasticsearch 能夠輕松應對大規模數據和高并發查詢。

例如,在一個電商搜索系統中,可能有多個數據節點分別存儲不同品類的商品數據,協調節點接收到用戶的搜索請求后,會根據請求的內容將其分發到相應的數據節點進行查詢,最后匯總結果返回給用戶。

1.2 硬件資源對 Elasticsearch 性能的影響

1.2.1 CPU

CPU 是 Elasticsearch 處理數據和執行查詢的核心硬件。在索引數據時,CPU 負責對文檔進行分析、分詞、構建倒排索引等操作;在查詢時,CPU 要執行搜索算法、對結果進行排序等。如果 CPU 性能不足,會導致索引和查詢的速度變慢,響應時間延長。

比如,當處理大量復雜的文本分析任務時,如對新聞文章進行語義分析和索引,如果 CPU 核心數不足或頻率較低,就會使得索引過程變得非常緩慢,影響數據的及時更新和查詢效率。

1.2.2 內存

內存對于 Elasticsearch 至關重要。它主要用于緩存數據和索引,減少磁盤 I/O 操作。Elasticsearch 的許多組件,如 Lucene 的段緩存、過濾器緩存等都依賴內存。合理的內存分配可以顯著提高查詢性能,若內存不足,頻繁的磁盤讀寫會導致系統性能急劇下降;而內存分配過多,又可能造成資源浪費,甚至引發 JVM 內存問題。

以一個日志監控系統為例,Elasticsearch 需要實時索引和查詢大量的日志數據。如果內存配置不足,無法有效緩存常用的索引和數據,每次查詢都需要從磁盤讀取,會導致查詢響應時間從毫秒級延長到秒級,嚴重影響監控的實時性。

1.2.3 磁盤 I/O

磁盤 I/O 性能直接影響 Elasticsearch 的數據讀寫速度。在索引數據時,需要將數據寫入磁盤;查詢時,又要從磁盤讀取數據和索引。如果磁盤 I/O 速度慢,會成為系統性能的瓶頸。不同類型的磁盤,如機械硬盤(HDD)和固態硬盤(SSD),其 I/O 性能差異巨大。

例如,在一個大數據分析項目中,每天有大量的傳感器數據需要存儲到 Elasticsearch。若使用機械硬盤,由于其讀寫速度有限,在數據寫入高峰時,可能會出現大量的 I/O 等待,導致索引延遲,進而影響數據分析的及時性。

1.2.4 網絡帶寬

網絡帶寬決定了 Elasticsearch 節點之間以及與客戶端之間的數據傳輸速度。在分布式環境下,節點之間需要頻繁地交換數據,如數據復制、集群狀態同步等。如果網絡帶寬不足,會導致數據傳輸延遲,影響集群的穩定性和性能。

比如,在一個跨地域的分布式搜索系統中,不同地區的節點之間需要進行數據同步和查詢協作。若網絡帶寬有限,數據傳輸時間會大幅增加,使得查詢結果的返回時間變長,降低用戶體驗。

二、根據數據量與查詢負載規劃硬件配置

2.1 數據量對硬件配置的影響

2.1.1 小規模數據(GB 級別)

對于數據量在 GB 級別的應用場景,硬件配置要求相對較低。CPU 方面,普通的多核處理器(如 4 核)通常就能滿足需求,因為數據處理量較小,CPU 的計算壓力不大。內存可以分配 4 - 8GB,這樣既能滿足基本的緩存需求,又不會造成資源浪費。磁盤方面,使用普通的固態硬盤(SSD)即可,SSD 的高速讀寫性能可以保證數據的快速存儲和檢索。網絡帶寬要求不高,百兆網絡一般就能應對。

例如,一個小型的企業內部知識庫系統,數據量可能只有幾 GB,使用上述配置的硬件,Elasticsearch 可以穩定運行,用戶在查詢知識文檔時能夠獲得較快的響應速度。

2.1.2 中等規模數據(TB 級別)

當數據量增長到 TB 級別時,硬件配置需要相應升級。CPU 建議選擇高性能的多核處理器,如 8 核或 16 核,以應對更復雜的數據處理任務。內存應增加到 16 - 32GB,以提供足夠的緩存空間,減少磁盤 I/O。磁盤方面,需要使用多塊 SSD 組成磁盤陣列,以提高數據讀寫的并行性和速度。網絡帶寬應提升到千兆網絡,確保節點之間的數據傳輸順暢。

以一個中型電商平臺的商品數據索引為例,隨著業務的發展,商品數據量達到了 TB 級別。此時,合理升級硬件配置后,Elasticsearch 能夠更高效地處理商品索引和用戶查詢請求,搜索響應時間得到有效控制。

2.1.3 大規模數據(PB 級別及以上)

對于數據量達到 PB 級別及以上的超大規模應用,硬件配置要求極高。CPU 通常需要使用多處理器系統,擁有大量的核心數,以應對海量數據的處理。內存可能需要分配 64GB 以上甚至更多,以滿足大規模緩存的需求。磁盤方面,需要采用高速的企業級 SSD 組成大規模的磁盤陣列,并且可能需要使用分布式文件系統來管理數據。網絡帶寬則要求萬兆網絡甚至更高,以保障集群內部和外部的數據傳輸效率。

比如,在一些大型的互聯網公司,如搜索引擎公司,每天處理的數據量達到 PB 級別。只有配備頂級的硬件資源,才能保證 Elasticsearch 集群的高效穩定運行,為用戶提供快速準確的搜索服務。

2.2 查詢負載對硬件配置的影響

2.2.1 低查詢負載

如果應用的查詢負載較低,即用戶查詢請求較少,硬件配置可以相對簡化。CPU 可以選擇較低性能的處理器,內存分配也可以適當減少,磁盤使用普通 SSD 即可,網絡帶寬要求不高。

例如,一個小型的社區論壇搜索功能,每天的查詢量有限,使用較低配置的硬件就能滿足需求,降低了硬件成本。

2.2.2 中等查詢負載

當中等查詢負載時,硬件配置需要相應加強。CPU 應選擇性能較好的多核處理器,以快速處理查詢請求。內存要適當增加,以緩存更多的查詢結果和索引數據。磁盤方面,考慮使用性能更好的 SSD 或磁盤陣列。網絡帶寬提升到千兆網絡,確保查詢請求能夠快速響應。

以一個企業級的項目管理系統為例,員工在日常工作中會頻繁查詢項目相關信息。隨著查詢負載的增加,合理升級硬件配置后,系統的查詢響應速度明顯提升,提高了員工的工作效率。

2.2.3 高查詢負載

在高查詢負載的場景下,硬件配置必須達到較高水平。CPU 要使用頂級的多核處理器,內存要足夠大以緩存大量數據和索引。磁盤需要采用高速的企業級 SSD 組成高性能磁盤陣列。網絡帶寬要達到萬兆網絡甚至更高,以應對高并發的查詢請求。

比如,在電商促銷活動期間,大量用戶同時進行商品搜索查詢,此時 Elasticsearch 面臨著極高的查詢負載。只有強大的硬件配置才能保證系統不出現卡頓,為用戶提供流暢的搜索體驗。

三、內存分配優化策略

3.1 JVM 堆內存大小設置

3.1.1 確定合適的堆內存大小原則

設置 JVM 堆內存大小需要綜合考慮多個因素。首先,要根據服務器的物理內存總量來確定,一般建議堆內存大小不超過物理內存的 50% - 70%,避免堆內存過大導致系統其他進程沒有足夠的內存可用。其次,要考慮數據量和查詢負載。如果數據量較大且查詢頻繁,需要適當增加堆內存,以提供更多的緩存空間;反之,如果數據量較小且查詢負載低,可以減少堆內存分配。

例如,在一個擁有 32GB 物理內存的服務器上運行 Elasticsearch,根據上述原則,可以將堆內存設置在 16GB - 22GB 之間。

3.1.2 調整堆內存大小的方法

在 Elasticsearch 中,可以通過修改 jvm.options 文件來調整堆內存大小。例如,要將堆內存的最小值和最大值都設置為 16GB,可以在 jvm.options 文件中添加以下配置:

-Xms16g
-Xmx16g

這里,-Xms 表示堆內存的初始大小,-Xmx 表示堆內存的最大大小。

3.2 合理配置內存使用參數

3.2.1 堆外內存設置

除了堆內存,Elasticsearch 還可以使用堆外內存。堆外內存不受 JVM 垃圾回收機制的管理,對于一些需要頻繁創建和銷毀對象的操作(如網絡通信、文件 I/O 等),使用堆外內存可以提高性能。可以通過設置 -XX:MaxDirectMemorySize 參數來調整堆外內存的大小。

例如,設置堆外內存大小為 4GB:

-XX:MaxDirectMemorySize=4g
3.2.2 垃圾回收器選擇

不同的垃圾回收器對 Elasticsearch 的性能有不同的影響。對于 Elasticsearch,通常推薦使用 G1 垃圾回收器。G1 垃圾回收器在處理大內存時具有更好的性能和可預測性。可以通過在 jvm.options 文件中添加以下配置來啟用 G1 垃圾回收器:

-XX:+UseG1GC

3.3 避免內存相關性能問題

3.3.1 內存不足導致的問題及解決方法

當內存不足時,Elasticsearch 可能會出現頻繁的垃圾回收、查詢響應時間變長甚至系統崩潰等問題。解決內存不足問題,首先要檢查堆內存和堆外內存的設置是否合理,是否需要增加內存分配。其次,可以優化查詢語句,減少不必要的數據加載和緩存,降低內存消耗。

例如,如果發現 Elasticsearch 在處理大量查詢時出現頻繁的垃圾回收,可以適當增加堆內存大小,并檢查查詢語句中是否存在全量掃描等消耗內存的操作,進行優化。

3.3.2 內存浪費問題及優化措施

內存浪費可能是由于不合理的緩存設置、對象創建和銷毀等原因導致。要優化內存浪費問題,可以通過調整緩存策略,如設置合理的緩存過期時間,避免緩存過多無用的數據。同時,優化代碼邏輯,減少不必要的對象創建和銷毀。

比如,在一個新聞搜索系統中,如果發現緩存中存在大量過期的新聞數據,占用了大量內存,可以通過設置合適的緩存過期時間,定期清理過期數據,釋放內存空間。

四、磁盤存儲設置優化

4.1 選擇合適的磁盤類型

4.1.1 SSD 與 HDD 的性能對比

固態硬盤(SSD)和機械硬盤(HDD)在性能上有巨大差異。SSD 采用閃存芯片作為存儲介質,讀寫速度遠遠高于 HDD。HDD 則通過機械部件進行數據讀寫,速度相對較慢。

例如,在順序讀取測試中,SSD 的讀取速度可以達到每秒數百 MB 甚至更高,而 HDD 通常只有每秒幾十 MB。在隨機讀寫方面,SSD 的優勢更加明顯,其隨機讀取延遲可以低至幾十微秒,而 HDD 則在毫秒級別。

4.1.2 優先選擇 SSD 的原因

由于 Elasticsearch 對磁盤 I/O 性能要求較高,優先選擇 SSD 可以顯著提高系統性能。SSD 的高速讀寫能力可以減少數據索引和查詢時的等待時間,提高系統的響應速度。同時,SSD 的可靠性也更高,減少了因磁盤故障導致的數據丟失風險。

在一個對實時性要求極高的金融交易監控系統中,使用 SSD 存儲 Elasticsearch 的數據,能夠快速索引和查詢交易數據,及時發現異常交易行為,保障交易安全。

4.2 配置磁盤陣列

4.2.1 磁盤陣列的原理與優勢

磁盤陣列是將多個磁盤組合在一起,通過一定的算法提高數據讀寫性能和可靠性。常見的磁盤陣列級別有 RAID0、RAID1、RAID5 等。RAID0 通過條帶化技術將數據分散存儲在多個磁盤上,提高了數據讀寫的并行性,從而提升了讀寫速度;RAID1 通過鏡像技術將數據復制到多個磁盤上,提高了數據的可靠性;RAID5 則結合了條帶化和奇偶校驗技術,在提高讀寫性能的同時保證了數據的可靠性。

4.2.2 選擇合適的磁盤陣列級別

對于 Elasticsearch,根據不同的需求可以選擇不同的磁盤陣列級別。如果更注重性能,可以選擇 RAID0,但要注意其數據可靠性較低;如果對數據可靠性要求較高,可以選擇 RAID1 或 RAID5。

例如,在一個數據備份系統中,為了保證數據的安全性和可靠性,可以選擇 RAID5 磁盤陣列。而在一個對性能要求極高的測試環境中,可以選擇 RAID0 磁盤陣列來提高數據讀寫速度。

4.3 調整磁盤 I/O 調度策略

4.3.1 常見的磁盤 I/O 調度算法

常見的磁盤 I/O 調度算法有 CFQ(完全公平隊列)、Deadline、Noop 等。CFQ 算法試圖公平地分配磁盤 I/O 資源,為每個進程提供大致相等的 I/O 帶寬;Deadline 算法則更注重減少 I/O 延遲,優先處理緊急的 I/O 請求;Noop 算法是一種簡單的調度算法,只對 I/O 請求進行合并和排序。

4.3.2 為 Elasticsearch 選擇合適的調度算法

對于 Elasticsearch,通常推薦使用 Deadline 調度算法。因為 Elasticsearch 對 I/O 延遲較為敏感,Deadline 算法能夠優先處理緊急的 I/O 請求,減少查詢響應時間。可以通過修改 /sys/block/sda/queue/scheduler 文件(假設磁盤設備為 sda)來調整調度算法。

例如,將調度算法設置為 Deadline:

echo deadline > /sys/block/sda/queue/scheduler

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67826.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67826.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67826.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bootstrap.yml文件未自動加載問題解決方案

在添加bootstrap.yml文件后,程序未自動掃描到,即圖標是這樣的: 查了一些資料,是缺少bootstrap相關依賴,雖然已經添加了spring-cloud-context依賴,但是這個依賴并未引入bootstrap依賴,可能是版本問題,需要手動引入 <dependency><groupId>org.springframework.cloud&…

C++底層學習預備:模板初階

文章目錄 1.編程范式2.函數模板2.1 函數模板概念2.2 函數模板原理2.3 函數模板實例化2.3.1 隱式實例化2.3.2 顯式實例化 2.4 模板參數的匹配原則 3.類模板希望讀者們多多三連支持小編會繼續更新你們的鼓勵就是我前進的動力&#xff01; 進入STL庫學習之前我們要先了解有關模板的…

【玩轉 Postman 接口測試與開發2_015】第12章:模擬服務器(Mock servers)在 Postman 中的創建與用法(含完整實測效果圖)

《API Testing and Development with Postman》最新第二版封面 文章目錄 第十二章 模擬服務器&#xff08;Mock servers&#xff09;在 Postman 中的創建與用法1 模擬服務器的概念2 模擬服務器的創建2.1 開啟側邊欄2.2 模擬服務器的兩種創建方式2.3 私有模擬器的 API 秘鑰的用法…

【算法】回溯算法專題③ ——排列型回溯 python

目錄 前置小試牛刀回歸經典舉一反三總結 前置 【算法】回溯算法專題① ——子集型回溯 python 【算法】回溯算法專題② ——組合型回溯 剪枝 python 小試牛刀 全排列 https://leetcode.cn/problems/permutations/description/ 給定一個不含重復數字的數組 nums &#xff0c;返…

8.原型模式(Prototype)

動機 在軟件系統中&#xff0c;經常面臨著某些結構復雜的對象的創建工作&#xff1b;由于需求的變化&#xff0c;這些對象經常面臨著劇烈的變化&#xff0c;但是它們卻擁有比較穩定一致的接口。 之前的工廠方法和抽象工廠將抽象基類和具體的實現分開。原型模式也差不多&#…

LabVIEW如何高頻采集溫度數據?

在LabVIEW中進行高頻溫度數據采集時&#xff0c;選擇合適的傳感器&#xff08;如熱電偶或熱電阻&#xff09;和采集硬件是關鍵。下面是一些建議&#xff0c;幫助實現高效的溫度數據采集&#xff1a; 1. 傳感器選擇&#xff1a; 熱電偶&#xff08;Thermocouple&#xff09;&am…

Kotlin 委托詳解

Kotlin 委托詳解 引言 Kotlin 作為一種現代化的編程語言&#xff0c;在 Android 開發等領域得到了廣泛的應用。在 Kotlin 中&#xff0c;委托&#xff08;Delegation&#xff09;是一種強大的特性&#xff0c;它可以讓我們以更簡潔的方式實現代碼的復用和擴展。本文將詳細解析…

npm 和 pip 安裝中常見問題總結

安裝路徑的疑惑&#xff1a;NPM 和 PIP 的安裝機制 NPM 安裝路徑規則&#xff1a; 依賴安裝在項目目錄下&#xff1a; 當你運行 npm install --save-dev jest&#xff0c;它會在當前目錄&#xff08;例如 F:\&#xff09;下創建一個 node_modules 文件夾&#xff0c;把 jest 安…

人工智能:農業領域的變革力量

在當今科技飛速發展的時代&#xff0c;人工智能正以前所未有的態勢滲透進各個領域&#xff0c;農業也不例外。想象一下&#xff0c;未來的農田里&#xff0c;農民不再是彎腰勞作的形象&#xff0c;而是坐在高科技的“智能農場”里&#xff0c;悠閑地喝著咖啡&#xff0c;指揮著…

LLM的Deep Research功能:重構人類認知與創新的新范式

在人工智能迅速發展的今天&#xff0c;大語言模型&#xff08;LLM&#xff09;的deep research功能正在成為重構人類認知方式的關鍵力量。 這一突破性的技術進展不僅帶來了工具層面的革新&#xff0c;更深刻地觸及了人類認知能力的本質。 本文將從認知科學的視角出發&#xf…

【Cadence仿真技巧學習筆記】求解65nm庫晶體管參數un, e0, Cox

在設計放大器的第一步就是確定好晶體管參數和直流工作點的選取。通過閱讀文獻&#xff0c;我了解到L波段低噪聲放大器的mos器件最優寬度計算公式為 W o p t . p 3 2 1 ω L C o x R s Q s p W_{opt.p}\frac{3}{2}\frac{1}{\omega LC_{ox}R_{s}Q_{sp}} Wopt.p?23?ωLCox?Rs…

前端力扣刷題 | 6:hot100之 矩陣

73. 矩陣置零 給定一個 m x n 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存儲需要置零的行索引let setY new Set(); //…

每日一題——有效括號序列

有效括號序列 題目描述數據范圍&#xff1a;復雜度要求&#xff1a; 示例題解代碼實現代碼解析1. 定義棧和棧操作2. 棧的基本操作3. 主函數 isValid4. 返回值 時間和空間復雜度分析 題目描述 給出一個僅包含字符 (, ), {, }, [, ] 的字符串&#xff0c;判斷該字符串是否是一個…

集合通訊概覽

&#xff08;1&#xff09;通信的算法 是根據通訊的鏈路組成的 &#xff08;2&#xff09;因為通信鏈路 跟硬件強相關&#xff0c;所以每個CCL的庫都不一樣 芯片與芯片、不同U之間是怎么通信的&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 很重要…

紅黑樹的封裝

一、封裝思路 在 STL 中 map set 的底層就是封裝了一棵紅黑樹。 其中連接紅黑樹和容器的是迭代器&#xff0c;map set 暴露出的接口都不是自己寫的&#xff0c;而是紅黑樹寫的&#xff0c;外部接口封裝紅黑樹接口。 所以寫出紅黑樹為 map set 寫的接口&#xff0c;再在上層的…

java異常處理——try catch finally

單個異常處理 1.當try里的代碼發生了catch里指定類型的異常之后&#xff0c;才會執行catch里的代碼&#xff0c;程序正常執行到結尾 2.如果try里的代碼發生了非catch指定類型的異常&#xff0c;則會強制停止程序&#xff0c;報錯 3.finally修飾的代碼一定會執行&#xff0c;除…

使用QMUI實現用戶協議對話框

使用QMUI實現用戶協議對話框 懶加載用于初始化 TermServiceDialogController 對象。 懶加載 lazy var 的作用 lazy var dialogController: TermServiceDialogController {let r TermServiceDialogController()r.primaryButton.addTarget(self, action: #selector(primaryC…

C++進階: 紅黑樹及map與set封裝

紅黑樹總結整理 紅黑色概述&#xff1a; 紅黑樹整理與AVL樹類似&#xff0c;但在對樹的平衡做控制時&#xff0c;AVL樹會比紅黑樹更嚴格。 AVL樹是通過引入平衡因子的概念進行對樹高度控制。 紅黑樹則是對每個節點標記顏色&#xff0c;對顏色進行控制。 紅黑樹控制規則&…

在Qt中,slots 關鍵字有什么用?

有下面的Qt代碼&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr…

列表標簽(無序列表、有序列表)

無序列表 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><…