ecs如何提高cpu緩存命中率
『壹』 AWS - ECS + Application Load Balancer的思考
我們有一個前端應用項目,這個前端應用用來替換老的Web站點的部分頁面,其結構如下:
用戶的請穗橘或求首先會到Nginx,由Nginx做反向代理,根據請求路徑轉發到New Web App或者Legacy Website。
在部署這個應用的時候使用到了AWS ECS。下圖為最開始時的部署結構:
從圖中可以看到,應用的DNS(Route53)指向了一個外部可訪問到的負載均衡器(External Classic Load Balancer)。負載均衡器暴露了80埠(用於Http請求)和443埠(用於Https請求)。負載均衡器將80埠和443埠都映射到了AWS EC2 Instance上的80埠。
而由ECS管理的Nginx容器,它將宿主機(EC2 Instance)的80埠映射到了容器的80埠。這樣從External Classic Load Balancer來的請求都會轉發到Nginx容器。
那麼,當用戶請求到達Nginx容器後,由Nginx做反向代理,根據請求路徑將請求轉發到New Web App或者Legacy Website(Legacy Website並不屬於部署結構中,所以並沒有在部署結構圖中畫出)。
假設,這個請求需要轉發到New Web App中,那麼應該怎麼做呢?
由於AWS ECS並沒伍侍有服務自動發現機制,所以我們需要給New Web App Container Cluster添加一個內部可訪問到的負載均衡器(Internal Classic Load Balancer)。這個負載均衡器將80埠映射到了AWS EC2 Instance上的3000埠,而在創建Nginx Container的時候會將這個內部負載均衡器關聯起來。所以在請求需要轉發到New Web App中時,直接轉發到這個內部負載均衡器即可。
到此為止,這個方案看似還不錯,但是如果你細心研究,你就會發現它存在一些問題。
有沒有發現,我們將ELB埠映射到了Instance上,而這個映射是固定的。一個Instance上的某個埠一旦被佔用,就無法被其它進程綁定。這就意味著一個EC2 Instance上只能猜伍啟動一個Nginx容器、一個New Web App容器,因為它們都需要綁定到特定的EC2 Instance埠號。
那麼,如果說EC2 Instance上有足夠的資源能夠再啟動一個New Web App容器或者Nginx容器,但是由於埠已經被佔用所以這些資源只能被浪費掉。我們必須再啟動一台EC2 Instance給ECS使用,ECS發現這個新的EC2 Instance上沒有綁定過3000或者80埠,並且有足夠的資源(CPU, Memory)啟動New Web App或者Nginx容器,那麼New Web App或者Nginx容器就會在新的EC2 Instance上啟動。
由此,我們可以看到這種部署方式,給我們帶來了這樣的問題,即: 某種類型的容器只能在一個EC2 Instance上啟動一個 。這對於我們來說是一個極大的限制,為了解決這個問題,我們找到了AWS Application Load Balancer(ALB)。
首先,我們將Classic Load Balancer換成了Application Load Balancer,如下圖:
從圖中看,好像並沒有什麼改變。是的,如果還是使用固定埠的話對我們並沒有什麼幫助。但是,ALB有一個特性它可以實現 動態埠綁定 ,這個特性正式我們想要的。
通過,實現動態埠綁定我們的架構變為如下圖所示:
如圖所示,通過動態埠綁定,我們實現了在 一個EC2 Instance上啟動多個同類型的容器 。
『貳』 麻煩高手指點ecs g31t-m5主板怎麼超頻cpu(酷睿e5200)大概能超到多少
775平台用E5200就可以了,沒必要再升級CPU,E7500價格能買I3或者AMD4核了,E5200也不是很垃圾的CPU,日常夠用了,小超一下不見得比E7500慢多少。
要換就換個好點的顯卡,以後換主板和CPU了還能用告滲余。顯卡和你目前配置搭配就用個GT240或者HD4670之類500元以內的就成。
近期打算換主板和CPU的話喊改就買個GT450,GT460,HD5750,HD5770之類的。
最省錢的就是淘塊二手7600GT,8600GT,HD2600這個檔次要DDR3顯存的一百左右,9600GSO,9600GT,HD3850這襪滾檔次的能找到二手更好。都秒殺你的G210.
『叄』 綜保與ecs後台有延遲
原因有數據傳輸速度和大量並發。綜保(綜合保障平台)和ECS(企業雲服務平台)後台都有一定的延遲,數據需要在網路傳輸中進答巧行交換,速度慢則會導致延遲增加,有大量用戶同時在使用綜保或簡舉枯ECS後台,攔洞也會導致後台處理任務出現延遲。延遲是綜保和ECS後台使用中的常見問題,但這並不意味著它們不能正常運行,通過合理規劃和使用優化措施,可以有效地避免或減少延遲問題,提高平台的工作效率和穩定性。
『肆』 ECS伺服器CPU跑高,老是被這個safedogtray.exe程序占滿,如何解決,可以直接刪掉嗎急!
safedog是安全狗的程序,刪除後安全狗不能運營
如果你覺得安全狗佔用過高,推薦你使用另一款更好用的伺服器管理面板【雲幫手】
雲幫手是一款集中化伺服器管理軟體,提供全方位的雲伺服器管理服務。融合大數據分析、可視化、態勢感知、威脅情報分析技術,為客戶提供一站式雲安全產品、服務和解決方案,實現伺服器、網站及業務的安全穩定運行。
其全面支持所有主流雲服務提供商,同時兼容Windows、CentOS、Ubuntu、Debian、OpenSUSE、Fedora等主流雲伺服器操作系統。支持多台伺服器可視化管理,監控告警,日誌分析等便捷功能,提供跨雲多平台一站式批量雲伺服器安全管理服務。
『伍』 ecs/ecr使用
安裝aws cli參考 https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/cli-chap-install.html
執行aws configure配置終端許可權
上述操作羨吵成功後提示Login Succeeded
然後製作鏡像修改鏡像名稱為 {docker-hub-url}/{存儲庫名稱}:{版本}
執行上磨鎮傳:
准備好在ecr上傳的鏡像名稱
481118635851.dkr.ecr.cn-north-1.amazonaws.com.cn/test:latest
1.創建新任務
我這里選擇FARGATE
任務定義名稱*:自己定
網路模式:選awsvpc
任務執行角色:沒瞎派粗有的話選擇創建新的
任務內存 (GB):根據自己的服務來定
任務 CPU (vCPU):根據自己的服務來定
接下來添加容器:
主要配置容器名稱和映像(image)其它自行配置
添加完容器後選擇創建任務
啟動類型: FARGATE
服務名稱:自定
任務數:指啟動的實例數量
網路配置
選擇集群vpc
子網選擇創建時分配
然後一直下一步即可
『陸』 如何處理阿里雲ECS伺服器CPU利用率過高
如果你選擇的是t5類型的主機,那麼這個問題是無解的,因為這個類型本身就是限制了CPU性能基線在10%~15%,不能超過這個數字。
也有一種可能用的是共享型實例,特點是多台小雞共享一個母雞的系統資源,小雞之間存在了資源爭搶。
關於這個內容有一些解釋,長期建站和 windows 遠程桌面慎用阿里雲突發性能 t5 實例,我覺得寫的挺實在的,建議怎麼操作都有提供了
『柒』 阿里雲服務ECS為什麼那麼慢.1 vCPU 2 GiB (I/O優化) ecs.t5-lc1m2.small 1Mbps
阿里雲和其他雲伺服器不太一樣,需要在管理面板控制組那裡開啟允許訪問的埠
按說你這個配置用來掛機不應該卡的
你可以ping一下IP看看丟包率
『捌』 unityecs沒有繪制
性能;
減少不必要的內存使用
放一張圖,之前寫了demo測試,對於使用ecs,不使用ecs,做instancing優化3中情況下,性能的差別。
可以看到如果你渲染的object在500以內,ecs性能並沒有顯著提升,當超過1000後,ecs性能有顯著的優勢,在10000obj下,差不多100的性能差距。
所以對於200內obj的游戲,是不是用ecs差別不大。
另外ecs這是unity提出的一個系統化的方案和標准,我們自己也可以或多或少使用傳統方法做出類似的結果,沒必要非ecs不可。
demo是如下圖(Instancing),根據自帶的rotate demo完成對應的instancing和傳統方法版本,這個demo是1000個cube,有一個sphere旋轉,撞到cube後,cube會自轉一段時間,逐漸停止,所以需要1001個物體不停的update:
=========補充公司內分享的完整文章:
不再需要MonoBehaviour、Component和GameObject
以前MonoBehaviour承載了游戲邏輯和數據兩部分功能,我們通過創建GameObject然後銷宏首添加MB(MonoBehaviour,下同)然後通過Update來更新游戲邏輯,往往我們Update里就是更新一些數據,而MB的實現非常復雜,有很多不需要的功能都一股腦的被繼承下來,這導致我們一個非常簡單的任務可能需要浪費很多內存去應付那些不需要的功能,如果再無節制的使用MB,那基本就是游戲運行效率的噩夢。
之前的Component是繼承自MB,大部分時候Component的作用就是提供數據,但是通過Component組織的數組是對CPU cache不夠友好的,因為它並沒有把需要多次重復計算更新的數據組織到一起,使得CPU在做計算時可能cache miss,如果游戲邏輯需要大量對象虧數需要更新數據,可能這部分消耗是非常大的。
同時MB不能很好的解決執行順序問題,對於動態創建的GameObject,MB的更新順序是不確定的,我們往往系統某些MB的Update和Destroy在某些MB之後,以保證相互的依賴關系,但Unity的MB設計上沒有更好的解決這個問題,通過調整Script Execution Order既麻煩也沒啥卵用(之前測試對於動態創建的MB毫無作用,只能用於場景中靜態的MB)。
還有,如果游戲中存在大量的GameObject,上面綁定大量的Component,那麼執行大量的Update是非常耗時的,而且這些Update只能運行在主線程,無法並行。
為此,Unity 2018.2 引入了全新的ECS系統,用於解決上面提到的問題。
全數據化驅動
ECS的核心設計目標就是去掉傳統的MB,GameObject,Component對象結構,而改為全數據化驅動的代碼組織方式,通過這樣的改變,可以解決2個問題:
1)將數據更有效的組織,提高CPU cache利用率;
2)並行化。
先簡單看一個例子,這個是ECS sample自帶的例子:
這個例子可以看到,雖然畫面里有超過1000個物體,但並沒有對應1000個GameObject,當球體碰到方塊的時候,會產生自轉後衰減,同時可以保持在300-600的fps運行幀率。這在以前,我們要實現類似的效果需要創建1000個GameObject,然後有1000個MB負責更新GameObject的transform信息,我按照這樣的方法來實現,那麼這個demo大概只有1/3的fps。
注意到上圖會創建更多的GameObject,fps大概100-200fps之間,當然這么實現並不是最優化的,我們還可以使用Instancing優化drawcall,為了對比我又實現了Instancing的版本,對比如下:
fps大概150-300fps,可絕此以看到instancing大概提高了1倍的fps,在1000 objs測試下,不同實現方法之間差別大概1-2倍,貌似差別不是很大,於是我又測試了更高obj數量的fps,在更高的objs測試下,得到如下圖表:
可以看到在更高的obj數量下,ECS方法的優勢就體現出來了,在10000 obj下,ECS任然可以做到350的高fps,而即便Instance優化,也只剩下4fps,差距幾乎100倍。
現在我們回到開頭,ECS解決了如下2個問題:
1)將數據更有效的組織,提高CPU cache利用率;
2)並行化。
但是如何解決的呢?
將數據更有效的組織,提高CPU cache利用率
傳統的方法是將gameobject的數據放在Components上,比如可能是這樣(參考1):
using Unity.Mathematics;
class PlayerData// 48 bytes
{
public string public int[]
public quaternion
public float3
string name; // 8 bytes
someValues; // 8 bytes
}
PlayerData players[];
他的內存布局是這樣:
而這樣的設計對cpu cache是極度不友好的,當你試圖批量更新float3數據時,cpu cache預測總是失敗的,因為他們被分配到了內存中不連續的區域,cpu需要幾次定址跳轉才能找到對應的數據並操作,如果我們能夠將需要批量更新的數據連續的存放到一起,這將大大提高cpu cache的命中率,提升計算速度。
按ECS設計規范,就是將批量的更新的數據抽取出來,在內存中連續排列,從而在cache預讀中能夠將後續的數據一次性讀取進來,提高cpu操作的效率,
在實際計算的時候,通過間接索引,來更新全部entity的各個類型的數據,而不是更新每個entity的全部數據,如圖:
可以看到這里,最大的變化是:
在一個system(相當於以前的component)更新計算中,是將所有的entity的position放在一起批量更新的,因為這些position的float3數據在內中是連續的,cpu操作起來是最快的。
並行化
將數據單獨提取出來後,接下來的任務就是將這些數據計算並行化,充分利用多核。在以前,幾乎邏輯代碼都是跑在主線程,當然也有項目組意識到了這個問題,會將一些和顯示無關的邏輯放入多線程中並行,但都沒有徹底的在數據上抽象形成一套完整的開發框架,而ECS解決了這個問題。
ECS開放了底層的job system系統,在上層提供了c# job system,它是一套多線程調度系統。如果不同的數據是無相互依賴的,僅需要將這些數據通過c# job system放入多個線程並行化計算就可以了,如:
public class RotationSpeedSystem : JobComponentSystem
{
struct RotationSpeedRotation : IJobProcessComponentData<Rotation, RotationSpeed>
{
public float dt;
public void Execute(ref Rotation rotation, [ReadOnly]ref RotationSpeed speed)
{
rotation.Value = math.mul(math.normalize(rotation.Value), quaternion.axisAngle(math.up(), speed.Value * dt));
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var job = new RotationSpeedRotation() { dt = Time.deltaTime };
return job.Schele(this, 64, inputDeps);
}
}
如果不同的數據有依賴,需要其他的數據計算完才能完整計算,則可以設置任務依賴,c# job system會自動完成這樣任務的調用和依賴關系排序。
混合模式
目前已經存在大量的傳統方式開發的代碼,如果想享受到ECS帶來的高效,勢必要將現有代碼大幅改造,有沒有相對簡單的方法既能保持現有代碼沒有太大變動,又可以提高效率呢,答案是ECS提供一種兼容的混合模式。
例如如下代碼(參考2):
using Unity.Entities;using UnityEngine;
class Rotator : MonoBehaviour{
// The data - editable in the inspector public float Speed;
}
class RotatorSystem : ComponentSystem{
struct Group
{
// Define what components are required for this // ComponentSystem to handle them. public Transform Transform;
public Rotator Rotator;
}
override protected void OnUpdate()
{
float deltaTime = Time.deltaTime;
// ComponentSystem.GetEntities<Group> // lets us efficiently iterate over all GameObjects // that have both a Transform & Rotator component // (as defined above in Group struct). foreach (var e in GetEntities<Group>())
{
e.Transform.rotation *= Quaternion.AngleAxis(e.Rotator.Speed * deltaTime, Vector3.up);
}
}
}
主要的修改是把MB的Update函數移到了ComponentSystem的OnUpdate函數中,同時增加了一個Group的struct,用於在MB和ComponentSystem之間交換數據,同時在原GameObject上添加一個GameObjectEntity組件,這個組件的用途是將GameObject其他全部的Component抽取出來並創建一個Entity,這樣就可以通過GetEntities函數在ComponentSystem中遍歷對應的GameObject了。
Unity會在啟動的時候,把所有掛載了GameObjectEntity組件的GameObject,都創建對應ComponentSystem,這樣你任然可是使用以前的GameObject.Instantiate方法來創建GameObject。只是原本MB的Update函數被替換到了ComponentSystem的OnUpdate函數中。
通過這樣的修改,你可以混合ECS的部分能力又相對保持原本的代碼結果,總結來說:
混合模式可以分離數據和行為,可以批量化更新對象的數據,避免每個對象的virtual方法調用(抽象到了一個函數中),任然可以繼續使用inspector來觀察GameObject的屬性和數據。
但是這樣修改並沒有徹底改善什麼,創建、載入的時間沒有改善,數據的訪問任然是cache不友好的,並沒有把數據在內存中連續排布,也沒有並行化。
只能說這樣修改是為了進一步靠近純ECS做的階段性代碼重構,最終還是要完全使用純ECS才能獲得最大的性能提升。
『玖』 阿里雲ECS的CPU100%排查
一、背景和現象
初創公司,架構lanmp,web前端和後端分開伺服器,業務驅動主要是nginx和apache,nginx主要是處理靜態文件和反向代理,前後端、搜索引擎、緩存、隊列等附加的服務都是用docker容器部署。因為比較初級,上傳文件和採集文件都是直接寫在硬碟上,涉及到的目錄共享,就在其中一台伺服器存儲並且nfs共享。我們暫且分為ECS1(apache1)、ECS2(apache2)、ECS3(nginx)。某天網站業務中斷,但是沒有報錯。一直在等待響應,默認響應超時是一分鍾,所以很基礎高可用沒有起到作用。中斷10分鍾左右,重啟服務,提示「open too many files」,但是lsof統計沒幾個。因為初級處理不了,所以直接重啟伺服器,一段時間後一切恢復正常,可是第二天又來一次這種情況。
二、第一次出現後的排查思路
本來第一次發現這種問題的時候就要追查原因了,看了一下zabbix監控圖像其中斷了十分鍾,包括網路、內存、CPU、硬碟、IO等監控數據。首先想到的是網路問題,結論是zabbix-servert獲取不到了zabbix-agent採集的數據,估計就是網路不通了。
但是,這個結論站不住腳,因為我本身通過ssh登錄伺服器,並且命令輸入無卡頓,不至於頭文件都傳不過來。後來一看阿里雲的雲監控,上面有數據,似乎也可以佐證網路這個說法,因為雲監控是阿里雲內部的監控,可以內網獲取到監控數據。直到看CPU的使用率這項,發現有一段時間的CPU使用率100%。並且我重啟的時候CPU恢復正常,不能說網路一定沒問題,但系統肯定有問題。也可以解釋因為CPU使用已經是100%,zabbix-agent和根本不能正常運行,所以沒有監控數據。因為這個公司全部都是雲伺服器,沒有使用IDC所以我們也沒有安裝smokeping來監控,接著我們就不把重心在網路上了。
目前掌握的信息就是:在毫無徵兆的情況下,CPU暴漲到100%,重啟之前一直保留,重啟之後恢復原樣。匆忙之中又看了一下系統各日誌,因為太匆忙,沒有總結,沒有找到什麼有價值的東西。現在有下面幾種猜想:第一,程序的bug或者部署不當,觸發之後耗盡資源。第二、docker容器的bug。第三、網路攻擊。第四、病毒入侵。第五、阿里雲方系統不穩定。
小總結了一下,現在問題還沒有找出來。下次還有這個問題的可能,所以先盡量防範,但是又不能重啟一刀切。所以在zabbix上面設置了自動化,當檢測到ECS1獲取不到數據的時候馬上操作ECS3標記後端為ECS1的apache為down。保留異常現場。(請求停止的時候,CPU100%還在)
三、現場排查
1、相應的排查計劃(想到這些信息需要獲取的,實際上沒有嚴格按照這樣的步驟)
1)用htop和top命令監控CPU、內存使用大的進程。先看看哪個進程消耗資源較多,用戶態、內核態、內存、IO……同時sar -b查io的 歷史 定時抽樣。
2)統計tcp連接數,看看有沒有DDOS攻擊。netstat -anp |grep tcp |wc -l 。用iftop-i eth1看看通訊。同時用tail -n 1200 /var/log/messages查看內核日誌。
3)用pstree查看打開進程,ps aux|wc-l看看有沒有特別多的進程。雖然zabbix監控上說沒有,但是我們要檢查一下看看有沒有異常的進程名字。
4)查看全部容器的資源使用docker stats $(docker ps -a -q),看看能不能從容器上排查。
5)有了「too many open files」的啟發,計算打開文件數目lsof|wc -l,根據進程看看ll /proc/PID/fd文件描述符有沒有可疑的打開文件、文件描述符。
6)關於用lsof打開文件數找到的線索,排序打開文件找出進程號 lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more
7)關於用lsof打開文件數找到的線索,用lsof -p PID查看進程打開的句柄。直接查看打開的文件。
8)啟動容器的時候又總是「open too many files"。那就是打開文件數的問題,因為CPU的使用率是CPU的使用時間和空閑時間比,有可能因為打開文件數阻塞而導致CPU都在等待。針對連接數的問題,大不了最後一步試試echo 6553500 > /proc/sys/fs/file-max 測試打開文件對CPU的影響。
9)玩意測出來了消耗CPU的進程,可以使用strace最終程序。用戶態的函數調用跟蹤用「ltrace」,所以這里我們應該用「strace」-p PID
10)從程序裡面看到調用系統底層的函數可以跟蹤。跟蹤操作 strace -T -e * -p PID,主要看看代碼調用的函數有沒有問題。
2、現場排查
第二天同樣時間,ECS果然暴漲了CPU。這是時候zabbix的工作如希望進行保留了一台故障的ECS1給我。
1)用htop看到資源使用最大是,搜索引擎下我寫的一個判斷腳本xunsearch.sh。腳本裡面很簡單,判斷索引和搜索服務缺一個就全部重啟。就當是我的容器有問題我直接關掉搜索引擎容器。httpd頂上,我又關掉apache容器。rabbitmq相關進程又頂上。這時候我沒心情周旋了,肯定不也是這個原因。sar -b查看的 歷史 io也沒有異常。
2)統計tcp連接,幾百。先不用著重考慮攻擊了。用tail -n 1200 /var/log/messages查看內核日誌,是TCP TIME WAIT的錯誤。可以理解為CPU使用100%,程序無響應外面的tcp請求超時。這是結果,還是沒有找到根本原因。
接著往下看系統內核日誌,發現了和「open too many files」呼應的錯誤,「file-max limit 65535 reached」意思是,已到達了文件限制瓶頸。這里保持懷疑,繼續收集其他信息。
3)查看進程數量,數量幾百。列出來也看到都是熟悉的進程,可以先排除異常進程。
4)監控容器的資源使用,裡面很不穩定,首先是xunsearch容器使用80%的CPU,關掉xunsearch,又變成了其他容器使用CPU最高。很大程度上可以排查容器的問題和執行程序的問題。
5)查看了最大連接數cat /proc/sys/fs/file-max是65535但是用lsof查到的連接數是10000多,完全沒有達到連接數。
6)各項參數都正常,現在聚焦在打開的文件數這個問題上面。也可以用另外同一種方式查看一下內核統計文件 /proc/sys/fs/file-nr,比較一下差異,看看能不能找出問題。cat了一下,打開文件數是66080,果然超了!內核日誌就以這個為標准。
但是看lsof怎麼統計不出來,ll /proc/PID/fd也沒幾個。這個問題放在後面,先按照步驟echo 6553500 > /proc/sys/fs/file-max給連接數提高到100倍,CPU果然降了下來。原因確認了,但是必須找到根源,為什麼忽然有這么大的打開文件數。關掉全部docker容器和docker引擎,打開文件數是少了一點,但是仍然在65535差不多。我就先排除一下業務的影響,把ECS3的nginx直接指向視頻ECS2的apache,就等同於在ECS2上實現了ECS1的場景。查看一下ECS2的句柄數,才4000多,排除了業務相關應用對伺服器的影響。那就能下個小結論,ECS1被神秘程序打開了6萬多句柄數,打開業務就多了2000多的句柄數,然後就崩潰了。不過這個現象有點奇怪,ECS2和ECS1在一樣的機房一樣的配置一樣的網路環境,一樣的操作系統,一樣的服務,一樣的容器,為什麼一個有問題,一個沒問題呢?不同的只是有一台是共享nfs。難道是靜態文件共享了,其他人讀了,也算是本伺服器打開的?
7)現在程序找不到,沒法繼續lsof -p了。排查之前的猜想。帶著排查得到對的結論往下想。
程序的bug和部署不當,那是不可能的,因為主要問題來自於打開句柄數,當部署到ECS2那裡,一切正常。docker容器的bug,那也不可能的,每個都是我親自寫腳本,親自編譯,親自構建的,關鍵是我關掉了docker容器和引擎都沒有很大改善。網路攻擊也排除,因為網路連接數沒幾個,流量也不變。那就只剩下病毒入侵也不是,沒有異常進程。考慮到ECS的穩定性問題了。這方面就協助阿里雲工程師去排查。
8)阿里雲工程師用的排查手段和我差不多,最終也是沒能看到什麼。也只是給了我一些治標不治本的建議。後來上升到專家排查,專家直接在阿里雲後端抓取了coremp文件分析打開的文件是圖片,程序是nfsd。
好像印證了我剛才後面的猜想,應該就是ECS1使用了nfs共享其他伺服器打開瞭然後算在ECS1頭上。那問題又來了,我們的業務已經到達了可以影響伺服器的程度嗎?
9)既然問題解決到這一步,先不管程序有沒有關閉打開的文件和nfs的配置。我們架構上面的圖片應該是歸nginx讀取,難道是linux的內存機制讓它緩存了。帶著緩存的問題,首先去ECS3上釋放內存echo 3 > /proc/sys/vm/drop_caches,釋放之後,發現沒什麼改善,有點失落。總是覺得還有一台後端是PHP主導,但是邏輯上是寫入,沒有打開文件之說。後來從程序員中了解到,PHP也有打開圖片。我猛然去ECS2釋放一下內存,果然,句柄數降下來。(這里大家一定有個疑問,為什麼我直接想到內存緩存而不是目前打開的文件呢。其一,這是生產環境,web前端只有一個,不能亂來停服務。其二,第一次遇到問題的時候,重啟之後沒有問題,過了一天之後積累到一定的程度才爆發,這里已經引導了我的思路是積累的問題,那就是緩存不斷積累了)
10)因為ECS2的調用ECS1的nfs共享文件,所以lsof也有讀不到那麼多句柄數的理由。如果說是nfs的服務本身就有緩存,導致問題的話,我查看了配置文件,還是默認值允許緩存,30S過期,根本不會因為nfs的緩存造成打開文件過多。如果我們的後端程序打開之後沒好好處理的話,那倒有可能。然後嘗試排除:我改了ECS3的配置,使程序只讀ECS1後端,從ECS1上面卻看不到有什麼異常表現,說明PHP程序已經好好處理了打開的文件。也不是docker掛載了nfs的共享的問題,因為nginx也有掛載。排查到這里也很大程度上解決問題,而且緩存了nfs的全部共享文件,句柄並沒有增加,也算合理,所以就增加了打開文件數的限制。
11)現在排查的結果是跟後端和nfs共享有關。就是說,後端掛載了nfs的網路共享,被程序讀取。而程序釋放之後,在正常背景的硬碟文件是沒有緩存的。但是在nfs掛載的環境下,緩存並沒有得到釋放。
12)總結:很多問題的排查和我們的猜想結果一樣,但是有些例外的情況。比如這次我想到的原因都一一排除,但是問題也是在一步步排查中,逐步被發現的。