線上一直以來都在用supervisor管理各項服務,感覺非常舒心,supervisor管理`gunicorn`和`celery`程序,web服務和非同步任務各司其職,跑起來一直很穩定。
前段時間卻不小心踩了乙個小坑,本來以為是celery的問題,後來查了半天才發現,原來根源在supervisor這兒。
靈異事件的表現是這樣的,乙個小專案裡有用到了非同步任務,但是傳送到非同步佇列的某乙個任務,有時候可以執行成功,有時候失敗,不穩定重現。
剛開始的時候懷疑任務本身出了問題,但有點說不通,因為並沒有任何的報錯被傳送出來,連任務**第一行的日誌都沒有被輸出。另外,其他任務都是正常的,日誌也是正常的,每一次的任務都能成功。
所以,目光又開始聚焦到了任務的呼叫方式上面,就先改成了同步試試,然後發現同步是可以成功的,這至少是排除了任務本身的問題了,任務函式是正確的。
剛抓住的稻草又沒了,只能再去分析了,又去翻了翻日誌,突然發現,自己以前寫的乙個函式裡的日誌輸出有異常,本來列印的info日誌裡面有個錯別字被改掉了,但是最近剛剛打出來的日誌,竟然還有這個錯別字。
到這問題基本已經清楚了,那就是有不止一組的celery任務程序在開著,並且有一部分是舊的**。趕緊驗證一下,`ps -ef | grep celery`看了一下,當下在跑著的任務裡,果然不止`supervisor`現在在監控的celery程序,還有一些老舊的celery程序,其父程序id都變成了1,好了,到此真相大白了。趕緊把這些任務kill掉,再驗證一遍,終於好了,任務又開始穩定得執行了。
後來問了問,原來是這台機器上的supervisord有一次被意外kill了,但是這些非同步任務卻留了下來,並且父程序id都成了1。後來supervisord被啟動了依賴,但是這個事情一直沒有被發現,這些任務程序也會連線到相同的訊息佇列去進行消耗,但舊的任務佇列裡面並沒有對應的新任務的處理方法,所以這些被舊的任務程序拿到的任務,就被丟棄了。
後來又看了看celery啟動時候的日誌,發現standalone啟動的時候,是有下面這段提示的
[2017-01-05 19:51:47,815: info/mainprocess] mingle: searching for neighbors[2017-01-05 19:51:48,821: info/mainprocess] mingle: all alone
而有同名的node name存在的時候,也是有下面的日誌的
[2017-02-09 19:10:50,872: info/mainprocess] mingle: searching for neighbors
要是早點看看celery的日誌,問題也是可以被解決的。
嗯,再次體現了看日誌的重要性,這次因為這個非同步任務本身並不怎麼重要,只有開發和部分運營的同學用到的功能裡包含了這個任務,所以並沒有造成什麼太大的損失。
但要是乙個重要的專案重要的任務出這種問題就悲劇了,後面需要針對這種事情做好監控,並且規範線上的操作,做好checklist完善和操作各項基礎設施的操作指南,避免這種事情再發生了。
Supervisor 踩坑日記
安裝 supervisor 後,編輯好 etc supervisor conf.d conf發現啟動都成問題 報錯 supervisor.service failed with result exit code 經過我個人的多次解除安裝再重安裝的經驗來看,pip3安裝是為了能夠讓 superviso...
Python 踩坑記錄
1.浮點數判斷 工作中遇到類似下面邏輯判斷 i 1 while i 1.5 i i 0.1 print i在想象中i應該停止在1.5就不輸出了,但是實際的輸出結果是無限迴圈。這是因為在計算機的邏輯中,浮點數的儲存規則決定了不是所有的浮點數都能準確表示,有些是不準確的,只是無限接近。如0.1轉換為二進...
Java踩坑記錄
1.quartz整合spring框架service層物件注入為null解決方案 jobdetailfactorybean中注入的是乙個cn.itcast.quartz.hellojob實現類的全路徑,底層會反射建立出乙個hellojob的物件,但是該物件不是由spring管理的,所以業務層的物件無法...