1. MINIT:Php擴展的初始化方法,整個模塊啟動時候被調用一次
2. RINIT:Php擴展的初始化方法,每個請求會調用一次
3. ClusterMap(簡稱CM):提供服務定位和集群地圖功能,通過接收心跳和主動探測方式收集節點狀態信息,統一管理多種異構集群,替換硬負載均衡設備
4. CMSubProxy:ClusterMap內部的一個訂閱者客戶端代理,定期和Server端通訊,獲取最新的集群信息,更新內部維護的機器列表
Nginx或者Php-CGI都是使用多進程 提供大並發服務的,如果服務內部想要提供一個通用的功能模塊,需要用戶自己寫一個Extension或者Module, 最近在做ClusterMap的訂閱者客戶端,訂閱者客戶端即Php的一個擴展,請求到來時,Php擴展會與CMServer通訊獲取最新的機器列表,但 是如果每次請求都去獲取機器列表開銷又特別大
在Apache的Module模式下,實現是 簡單的,Apache首先啟動父進程A會調用MINIT方法,調用完成後Fork其它Httpd子進程B,A和B是父子關系,這樣父進程A就可以定期更新 集群信息,然後通過管道方式和子進程通訊,子進程在每個請求過來時,讀取管道消息(即機器列表),實現了服務定位;但是Php-fpm模式略有不 同,Php-fpm進程管理器啟動進程A會調用MINIT方法,然後Fork出一個Fpm-Master進程B,進程B啟動多個Php-CGI子進程C, 啟動工作完成後,啟動進程A就退出了,子進程在每個請求過來時調用RINIT,這時父子AC進程管道通訊建立不起來,管道的數據沒有辦法消費,使得子進程 C如果寫滿就會阻塞。其實這個問題很普遍,如果用修改Php的源碼方式解決不見得是一個好的解決方案。
總結一下上述問題,說白了就是多個服務進程,每個進程在接到請求後,首先需要服務定位,獲得最新的機器列表(需要一次網絡開銷),然後再轉發請求給其他的服務,接下來我們以Fpm-Php為例介紹如果解決上述問題
案一:RInit中每個請求都先到Server端獲取最新的機器列表目前ClusterMap中采用的是方案三,通過共享內存的方式解決這個問題的
共享內存是mmap打開的,需要注意的是,在更新和讀取的時候需要讀寫鎖,並且鎖信號量要在共享內存中,關於多個進程間共享內存鎖
pthread_rwlockattr_t attr; pthread_rwlockattr_init(&attr); pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 手冊上對pthread_rwlockattr_setpshared的描述 pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared); DESCRIPTION The pthread_rwlockattr_setpshared() function sets the process-shared attribute of attr to the value referenced by pshared. pshared may be one of two values: PTHREAD_PROCESS_SHARED Any thread of any process that has access to the memory where the read/write lock resides can manipulate the lock.
CMSubProxy寫入共享內存中的數據是分全量和增量的,增量數據寫在全量數據之後,這裡就不詳細講述了