2019.9.16下午2:40左右發現環境出現故障,功能沒法正常運行。java
立刻進行排查
一、基礎服務端口運行都是正常的
二、查看環境上最近有新發版的三個微服務,發現都在不一樣頻率的打印這句日誌:node
2019-09-16 14:42:41,626 INFO [DubboMonitor.java:80] : [DUBBO] Send statistics to monitor zookeeper://192.168.1.101:2181/com.alibaba.dubbo.monitor.MonitorService?anyhost=true&application=dubbo-monitor&check=false&delay=-1&dubbo=crud&generic=false&interface=com.alibaba.dubbo.monitor.MonitorService&methods=lookup,collect&pid=11&revision=monitors&side=provider×tamp=1568598922300, dubbo version: crud, current host: 10.42.91.223
由於以前有一個微服務出現OutOfMemoryError的時候,就有一直打印這些日誌,所以將三個容器日誌導出來查看,剛剛導了兩個日誌,正在導第三個日誌的時候,發現docker命令沒法執行,docker掛了???git
先從新啓動了docker服務,恢復了業務,而後查看docker掛掉的緣由。docker
將messages文件中跟docker有關的內容過濾出來,發現了這樣的信息(部分日誌):api
Sep 16 14:43:07 rancher-node dockerd-current: time="2019-09-16T14:43:07.982713104+08:00" level=error msg="collecting stats for 587cf4938bed5e3172868d85ae41db3af37e9c1a6cd8192f1cfa22a4e969d53b: rpc error: code = 2 desc = fork/exec /usr/libexec/docker/docker-runc-current: cannot allocate memory: \"\"" Sep 16 14:45:04 rancher-node journal: Suppressed 1116 messages from /system.slice/docker.service Sep 16 14:45:05 rancher-node dockerd-current: time="2019-09-16T14:45:05.410928493+08:00" level=info msg="Processing signal 'terminated'" Sep 16 14:45:05 rancher-node journal: time="2019-09-16T06:45:05Z" level=error msg="Error processing event &events.Message{Status:\"kill\", ID:\"af42628b1354b74d08b195c0064d8c5d760c826626a3ad36501a85c824d2204d\", From:\"prod.locmn.cn/prod/locmn-drols-query-chq:latest\", Type:\"container\", Action:\"kill\", ..... Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?"
就是說在14:45的時候,docker就已經沒法分配到內存了
而後信號終止,docker進程被殺掉,所以docker的命令沒法運行,全部docker容器也都一塊兒掛掉了:bash
Sep 16 14:45:05 rancher-node dockerd-current: time="2019-09-16T14:45:05.410928493+08:00" level=info msg="Processing signal 'terminated(處理信號的終止)'" Sep 16 14:45:05 rancher-node journal: time="2019-09-16T06:45:05Z" level=error msg="Error processing event &events.Message{Status:\"kill\", ID:\"af42628b1354b74d08b195c0064d8c5d760c826626a3ad36501a85c824d2204d\", From:\"registry.locman.cn/sefon-online/locman-drools-query-chq:latest\", Type:\"container\", Action:\"kill\", ......Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?"
但是爲何分配不到內存呢?
查看了主機,內存還有10G的。app
後面細查新發版的三個微服務的業務的日誌,發如今14:03分的時候,有一個叫cud的服務有「java.lang.OutOfMemoryError」的報錯:ide
2019-09-16 14:03:10,554 ERROR [ExceptionFilter.java:87] : [DUBBO] Got unchecked and undeclared exception which called by 10.42.83.124. service: com.run.locman.api.crud.service.AlarmInfoCrudService, method: add, exception: java.lang.OutOfMemoryError: unable to create new native thread, dubbo version: crud, current host: 10.42.91.223 java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) ......(省略部分日誌內容) Exception in thread "pool-1-thread-3" java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714)
原來是這個叫cud服務的內存溢出了引起的故障,致使了docker服務被kill掉,全部的docker容器瞬間所有掛掉!微服務
和開發一塊兒對故障進行了分析,發現有兩個緣由:
一、這個服務有一個線程池,在代碼裏面設置的最小是8,最大限制是2147483647 ,用完的線程要1分鐘以後才能回收。這就存在兩個問題:
1、業務在持續不斷的發送請求,這個服務就會一直建立線程,而由於給定的線程最大值過大,至關於能夠無限制的建立線程了,會一直消耗資源;
2、用完的線程1分鐘以後纔會回收,時間過長。
在這兩點的影響下,程序跑一段時間,就會出現建立大量的線程,過分的消耗內存資源.gitlab
二、因爲docker容器在最初的時候沒有作容器的內存限制,因此默認狀況下容器使用的資源是不受限制的。
也就是可使用主機內核調度器所容許的最大資源,所以當主機發現內存不夠用的時候,也會拋出內存溢出的錯誤。並且會開始殺死一些進程用於釋放內存空間。可怕的是任何進程均可能成爲內核獵殺的對象,包括 docker daemon 和宿主機上的其它一些重要的程序。更危險的是若是某個支持系統運行的重要進程被kill掉了,整個系統也就宕掉了。
此次的docker服務進程就被殺掉了。
一、開發優化代碼,包括限制線程池的最大線程數量和線程回收的時間,從新發布代碼打補丁,後面觀察到目前,沒有再出現類這個問題了;
二、限制docker內存。從新優化了docker容器,限制了docker內存的使用量,減小docker容器過分佔用宿主機資源的風險;
三、增強對docker容器的監控與告警;
一、docker限制內存,很是重要!
二、限制內存的方式(放一個別人寫的修改內存的步驟):
方法一:靜態修改 -m
-m參數:限制docker容器最大使用內存例如:$ docker run -it -m 300M --memory-swap -1 --name con1 u-stress /bin/bash
上面的 docker run 命令中經過 -m 選項限制容器使用的內存上限爲 300M。
同時設置 memory-swap 值爲 -1,它表示容器程序使用內存的受限,而可使用的 swap 空間使用不受限制(宿主機有多少 swap 容器就可使用多少)。方法二:動態修改 docker update
docker update 動態修改docker容器內存例如:把一個運行着gitlab 的容器內存限制在2048M之內docker update --memory 2048m --memory-swap -1 gitlab