
如何快速實現REST API集成以優化業務流程
面對不同的業務集群,作為服務方需要兼顧靈活和標準, 首先通過從眾多的接口訪問信息中抽出來標準化的數據信息集,如集群名稱,接口uri,http Code,訪問量,訪問時長,超時量,失敗量等具體的數據,標準化的數據保證了傳輸的順暢,為后續的分析,統計,展示奠定基礎。其次提供靈活的可配置方案,兼容不同集群,不同采集間隔和自動化uri采集模型,去實現業務的靈活變通。
wrm.enable=1
wrm.tick=60
wrm.timeout=2000
wrm.collector_register_url=https://****.**.com/****/****
wrm.collector_port=****
wrm.cluster=***_***_***
wrm.total_url_num=500
wrm.enable_sync_uri=1
wrm.sync_uri_url=****.**.com/****/****
利用PHP的底層特性以擴展形式在PHP進程啟動的時候加載,避免開發同學因接入監控服務而需要做出額外的開發,實現無感知的數據采集。
合理選型數據結構和接入方式,依托于PHP-FPM主進程的監控進程,避免對系統額外的cpu和內存資源占用,保證線程安全調用。
1. ?首先啟動PHP Zend引擎后,在注冊動態擴展的過程中通過調用MINIT鉤子,fork出來監聽進程,從而在每次request開始/結束時 執行業務邏輯。
2. 監聽根據系統配置,初始化全局變量如上報時長,內存大小,上報地址等信息,以及通過mmap開辟共享內存空間和pthread去實現線程安全上報。
3. 每次request在請求時會初始化php_request_startup,并依次遍歷調用擴展中調用Rinit,在這個過程中收集到uri,http code,訪問時長等信息存儲如對應的結構體。
4. 監聽進程根據配置tick收集指定間隔時間的數據后,通過切換數據hash的內存塊指針,平滑變更hashtable的角色屬性,啟動上報線程,開始壓縮數據并異步上報至數據中心服務側。
PHP引擎啟動過程中通過php_module_startup遍歷php_extension_list中在php.ini注冊的動態擴展,并依次調用對應的Minit鉤子函數,在這個過程中我們在Minit中fork出來上報進程,根據配置的url個數初始化共享內存,并依據bkrdhash算法實現uri的hash存儲,同時一個hash做輸出,一個hash做存儲,并通過指針動態切換.該進程同時會監聽主進程。
在Rinit的鉤子中,依賴于sapi_getenv和SG去獲取本次請求的參數,如header和Server信息,根據uri路由,收集后存儲于trace實體中,在此鉤子中不做其他操作,保證最小粒度干擾線上的資源開銷,在Rshutdown鉤子中,統計響應狀態,耗時等日志信息,并存儲到對應的hash中。
typedef struct wrm_trace_analyze {
int mutex; // 互斥量
struct timeval total_duration;
int success_times;
int failed_times;
int timeout_times;
int server_port;
char server_addr[32];
char uri[256];
} wrm_trace_analyze;
依托于配置中的上報周期,上報線程會將數據存儲的hash指針做切換,從這一刻起,另外一個空hash結構體開始接受新數據做存儲,同時原輸出hash開始壓縮并上報數據中心服務側,上報完成后等待下個周期的切換,如此循環往復。
鑒于每次的http請求都會產生一條日志數據,如果每次都進行上報則對服務端是個很大的流量沖擊,針對這種情況我們通過合理設計本地存儲結構,實現時間周期內的日志數據匯總存儲,壓縮&定期上報匯總數據。
數據實現hash存儲,key值采用bkrdhash算法,以質數作為種子,每個字符串的ascii加和,保證每個字符串都參與到運算中,同時hash中只存儲有效的日志數據,如http code 200/500次數,時間等信息,以10000個uri舉例,只額外占用不到10M內存,并在數據udp上報到服務側之前通過gz壓縮,保證資源的合理優化。
我們采用的futex內核級同步鎖.在眾多php-fpm在同一時間點寫入同一個hash的,如果采用自旋鎖+等待,在線程較多的時候其他上下文的切換的資源開銷不低,但是通過futex內核級鎖,在通過雙向鏈表的隊列維護競爭的線程,在占用鎖資源的線程釋放資源后,會按順序從隊列中喚起等待的線程寫入。
我們采用的方案是通過監聽進程的存儲層開辟一個共享內存區域,分別為分為存儲區A和上報區B,在監控服務收集的過程中所有數據沉淀在A上,等待上報周期時間點一到則會將數據寫入的指針指向B,此時B角色切換為存儲區,A角色變更為上報區,線程將A上的數據進行上報,上報成功后clean掉數據,等待下一次的角色變更,如此循環往復,實現線程安全的異步上報流程。
我們以php擴展為獨立載體,不依賴任何框架,支持公司內部物理機和私有云等集群環境。業務集群需要監控服務則可將此.so文件加載到項目extension/下目錄或者 php配置級的extension下,同時在項目中的extension.conf配置采集參數即可方便使用,也因此實現項目級的日志采集能力。此擴展語法同時支持PHP7.0.0以上的版本集群環境。
Restful的自動化日志監控服務,在租房業務線集群以擴展的形式已成功部署至生產環境,各業務線負責人可以方便的通過公司的提供的可視化工具平臺(WF manager)直觀看到所屬的接口訪問詳情,從而節省各個業務線手動開發,標準不一的開發代價和維護成本。?目前租房業務線累計已有幾十個集群先后通過此擴展接入wfmanager系統,覆蓋百余臺PHP服務器,每分鐘采集日志超上百萬次,覆蓋90%的租房業務線上流量,為服務的平穩運行提供有力保障。通過可視化的線上接口實時訪問數據,對應服務的負責人實現了對所屬服務的主動關注/被動報警能力,為服務質量和穩定性提供了有力的支持,具體體現在以下兩個方面:
1. 在工程效率方面,過往線上出現接口訪問超時現象到問題解決的時間跨度周期往往超過1天,通過此擴展接入日志采集能力后,實現了線上的訪問實時監控預警,從問題出現到解決的時間跨度也降低為分鐘級別,如 一些APP端的詳情頁在優化之前接口加載時長達到300ms以上,接入日志監控擴展后清晰看到線上的真實耗時,對應同學收到預警后,經過幾輪實時技術優化對比,已成功將耗時降低為100ms以下。
2. 在數據分析維度,過往分析日志從單機awk統計到現在集群整體視角,粒度甚至細分至單機uri的級別,直觀監測到實時訪問數據,實現了同比,環比的流量波動分析,精準掌握產品的線上的訪問流量,為保證服務可用性的增擴容以及優化提供有力決策支持。?
文章轉自微信公眾號@58技術