elgg分佈式擴展和性能優化(一)

之前公司有個SNS方向的項目,由於有過Elgg的經驗,所以選定繼續採用Elgg作爲基礎來進行二次開發。項目中也更深入瞭解了Elgg的原理和特性,在性能優化和分佈式擴展上積累了一些經驗,分享記錄一下,希望對有興趣的童鞋有所幫助。

1. Elgg是什麼

簡單來說,Elgg是一套開源的基於PHP開發的社交網絡平臺套件,最初接觸到Elgg的時候是2008年國外InfoWorld組織的一個開源軟件評選,Elgg被評爲best open source social networking platform。Elgg實現了社交網絡常見的基本功能:關注、好友、微博、信息流、日誌、羣組等等。Elgg最有特點的是它的插件結構,除了極少數核心功能以外,大部分功能都是通過插件的形式實現,也就意味着各個功能模塊都可以被重載替換或者停用,很方便開發者分別對各個功能進行修改更新,而不影響其他模塊的正常運行。

此外,Elgg本身對object metadata和attribute的實現形式在編程開發上提供了很大的簡化,開發人員可以用類似NoSQL的賦值語法$object->anything = anything 添加和修改任意的metadata,而不用去考慮擴展數據庫表的字段等問題。

當然,這些優點在某些程度上反而變成了Elgg的缺點,開發上的便利對性能會有一定的影響,這些我會在以後的文章裏具體解釋。

2. Elgg的分佈式部署架構

Elgg本身是典型的LAMP架構,很明顯,單節點部署的模式不能滿足高可用、負載均衡等等已經不算很新的要求,於是有了下面這樣簡單的分佈式部署架構:

最前端用HA實現負載均衡,接一系列可以水平擴展的Web Server運行Elgg程序,後面接一個共用的Database (MySQL)。爲滿足可用性要求,MySQL也需要配置Master/Slave結構。

LAMP結構的這類應用,壓力瓶頸最容易集中在數據庫一層,因此在單臺數據庫能夠支撐之前,master/slave的結構夠用,能保證服務穩定運行,如果壓力進一步增大,則首先需要考慮實行讀寫分離,在應用中分別配置讀數據庫源和寫數據庫源(需要修改一定的代碼),如果嫌麻煩,也可以使用mysql自帶的一個mysql-proxy組件來實現讀寫分離,分散數據壓力。如果數據量增長到更大的規模,則需要考慮進行分表了。當然,優化不是一步到位就可以搞定的,等到你必須要進行分表的時候,你的業務的訪問量應該已經大到相當驚人的規模了:) 在那之前,倒不用過多考慮這樣的問題,還是先想想怎麼把業務做到那麼大訪問規模再說:)

3. Elgg+Nginx+Php-fpm

傳統的LAMP架構中都是指的Apache服務器,對web服務器領域有所瞭解的同學一定都知道Nginx,是比apache更高效更靈活的選擇,所以我們首先將web server這一層換成nginx,再接一個Php-fpm後臺程序用來解析PHP代碼。由於Elgg本身只提供了爲apache準備的htaccess文件,需要編輯nginx的配置文件,下面給出一個elgg的nginx配置示例:

server {
	listen   80; ## listen for ipv4
	server_name  localhost;
	root   /opt/web;
        index  index.php index.html index.htm;
	access_log off;
        error_log  /var/log/nginx/elgg.error.log;
	location ~* favicon.ico {
                log_not_found  off;
        }
	rewrite action/([A-Za-z0-9\_\-\/]+)$ /engine/handlers/action_handler.php?action=$1 last;
        rewrite pg/([A-Za-z0-9\_\-]+)/(.*)$ /engine/handlers/page_handler.php?handler=$1&page=$2 last;
        rewrite pg/([A-Za-z0-9\_\-]+)$ /engine/handlers/page_handler.php?handler=$1 last;
        rewrite cache/(.*)$ /engine/handlers/cache_handler.php?request=$1 last;
        rewrite services/api/([A-Za-z0-9\_\-]+)/(.*)$ /engine/handlers/service_handler.php?handler=$1&request=$2 last;
        rewrite export\/([A-Za-z]+)\/([0-9]+)/?$ /engine/handlers/export_handler.php?view=$1&guid=$2 last;
        rewrite export\/([A-Za-z]+)\/([0-9]+)/([A-Za-z]+)\/([A-Za-z0-9\_]+)/$ /engine/handlers/export_handler.php?view=$1&guid=$2&type=$3&idname=$4 last;
        rewrite xml-rpc\.php /engine/handlers/xml-rpc_handler.php last;
        rewrite mt/mt-xmlrpc\.cgi /engine/handlers/xml-rpc_handler.php last;
        rewrite tag/(.+)/?$ /engine/handlers/page_handler.php?handler=search&page=$1 last;
        rewrite rewrite\.php$ /install.php last;
        if (!-e $request_filename){     
                rewrite ([A-Za-z0-9\_\-]+)/(.*)$ /engine/handlers/page_handler.php?handler=$1&page=$2 last;
                rewrite ([A-Za-z0-9\_\-]+)$ /engine/handlers/page_handler.php?handler=$1 last;
        }
        location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                include        fastcgi_params;
		client_max_body_size  200m;
		proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
		fastcgi_buffer_size 1024k;
		fastcgi_buffers 32 1024k;
		fastcgi_busy_buffers_size 2048k;
		fastcgi_temp_file_write_size 2048k;
	}
	location ~* \.(css|js) {
		expires  30d;
	}
	location ~*  \.(bmp|ico|gif|jpg|jpeg|png)$
	{
		expires  30d;
	}
}

這裏有些細節說明一下:上面這個配置 php-fpm在本地的9000端口上提供服務,如果需要的話,可以配置一組php-fpm的upstream server, 然後配置nginx使用這一組服務器,真正做到水平橫向擴展。此外,nginx本身有緩存靜態文件的能力,對css,js和圖像等靜態內容,設置了緩存和失效時間,提高訪問效率。

以上是在架構和配置上對Elgg進行擴展的基本介紹,後續我會深入Elgg的代碼,從數據庫訪問、ache緩存、引擎啓動優化等等各個方面解釋對我們對Elgg進行的改造和優化,還有一些自己對這個架構的思考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章