顯示具有 scale 標籤的文章。 顯示所有文章
顯示具有 scale 標籤的文章。 顯示所有文章

5/10/2007

Twitter , Rails , Scalibility...More

Twitter 是一個最近非常熱的 Web Site,他們主要是可以利用簡訊,網頁更新自己的近況。Twitter 的開發者 Alex Payne 在接受訪問的時候,拋出了一個震撼性的議題
Rails Scalibility 到底好不好的問題
夠震撼吧。我發現到很多人都開始發表了 「Rails 遇到效能上的問題...」。看到只能說,這是 Rails 社群第一個大挑戰,但是請不要太過武斷就直接認為是 Rails 的問題。如果大家仔細了解這個事情的情況,就可以大略推估應該是 Twitter Team 成功的太快,整個 team 的成長跟不上網站的成長速度。我們來看看到底事情的始末。

故事開始

Alex Payne 是 Twitter Team 其中一員,他接受了 Radical Behavior 的訪問,當被問到 Ruby on Rails 如何應付高速成長的流量時,他指出他認為 Ruby on Rails 有不少 Scability 的議題,Alex 的論點如下
  1. Ruby is slow
  2. Rails 一次不能 connection multi database
  3. Rails 有些東西 component,性能消耗太大,必須不去使用
此話一出,當然引起了 Rails 社群的積極辯護,跟其他語言社群基於「良心」的建議。當然,我們 Rails 社群當中的老大DHH ,也不落人後的提出相關的建議。DHH 似乎覺得 Twitter 有點太過於懶惰了點,Twitter 比很多人幸運,有機會碰到那麼大的流量,那就該好好的想辦法處理相關的問題。而不是等著別人幫你解決你應該解決的問題。Open source 的成功,是來自使用者遇到相關的問題,並且解決他,回報給社群,這樣社群才會繼續壯大起來。
Second, when you work with open source and you discover new requirements not met by the software, it's your shining opportunity to give something back. Rather than just sit around idle waiting for some vendor to fix your problems, you get the unique chance of being a steward of your own destiny. To become a participant in the community rather than a mere spectator. This is especially true with frameworks like Rails that are implemented in high-level languages like Ruby. The barriers to contribution are exceptionally low
至於 Rails 一次連結到多個 DB 的問題,老實說,這根本不是問題,Dr. Nick 早就提出了Magic Multi Connections,可以有效解決這個問題。至於 Twitter 團隊是不知道這個東西,還是試過這個 Plugin 之後發現不夠用呢?InfoQ 訪問了 Twitter 另外一個開發者 Blaine Cook,說到 Dr. Nic 的 Plugin 很棒,很有幫助, Blaine Cook 表示目前 Twitter 的 DB Connection 是 600 req/sec,雖然很高,但是現在 Twitter 沒有暫時 DB 的問題。(那之前 alex 不是質疑說他們的問題是在 DB ? 到底 Twitter Bottleneck 在那裡?有點不了解他們的 Point 。
"Dr. Nic's approach is a great first step, and adds some welcome helpers to selecting from a number of database connections." but noted that "Twitter isn't currently database bound, and won't be for a while yet"
這時 Dr. Nic 也出來打圓場了,他說「Twitter 已經貢獻了 Jabber API 了」,其實不用苛求太多啦。
The guys at Twitter have already contributed code to Ruby community (Jabber API)
話說回來,Twitter Team 也似乎感受到 Rails 社群對他們處於制高點的期待,也開始對社群做出了幫助。Blaine Cook 在 SDForum 發表了 「Scaling Twitter」,裡面提到許多他們的問題以及解決方式。

進入討論

OK ,我們已經把故事講完了,現在討論正經點的事情。
到底是 Twitter 技術上不夠厲害,或是 Rails 不夠 Scalibility?
我認為這個 case 無法認定那一個結論是正確的。我們看看 twitter 的流量成長
很明顯的,Twitter 在 2007 年的流量是一個暴發戶的成長方式,通常網站遇到了這樣突然爆增的流量,原本編制的 RD 跟網管應該都完全無法應付吧,那麼一時之間無法解決也是非常正常的事情。所以,他們應該也不是太懶惰,只是成功的太突然,沒辦法吃下來。

再來,根據Blaine Cook 在 SDForum 發表的「Scaling Twitter」投影片,他們一共有 180 Mongrel Instances,但是卻只有使用兩個 DB Server,這似乎完全不符合一般大網站所遇到的情況(就是一海票的 DB Server,每個 table 都是橫切縱切隨便切)。當然我們不排除 twitter 的 application 型態其實並不需要太多 DB 的 request ,不過180 Mongrel Instant 居然只有 兩台 DB Server ,未免也太少了點,也不符合比例原則。

Twitter 是 host 在 joyent 上面的,像這種有一定規模的網站公司居然沒有自己專屬的系統管理者,光是這點這就看出 Twitter 成長真的太快了。一般來說,Web Host 很難做到專門為某個 Service 最佳化吧。Scalibility 本來就是軟體開發者跟系統管理者並肩合作的工程,Twitter 該多請幾個系統設計師摟。

至於 Ruby 是不是真的太慢,Rails 是不是真的不夠 Scalibilty呢?

這個問題我也不知道,畢竟我沒 run 過那麼大的 site,而我看到的 site 都是效率很不錯的。LAMP 發展了很久,Java 跟 Python 發展了很久,他們擁有 Ruby and Rails 社群無法比擬的成熟度,這是不爭的事實。但是,為什麼 Rails 會讓那麼多人趨之若騖,而非那些其他的語言呢?
那是因為 Ruby on Rails 擁有一些別人沒有的東西。而那些東西是很難被取代的。

今天這件事情沒有誰對誰錯,Twitter 點出這個議題,並且強調這個議題的重要性,Rails 社群接收到 Twitter 的訊息,大家一起幫忙解決,這是一個良性的溝通。我相信 Scalibility 是可以被克服的議題,也是值得一起去加油的議題。


延伸閱讀

2/05/2007

Rails 的負載度議題 XD

今天早上 Ruby on Rails Blog 上面有一篇非常聳動的文章 Joyent makes Rails app go to 4,000 req/sec,在我看到內文之後就笑了。這不是在吹噓 Ruby on Rails 有多厲害,而是在幫 F5 Big-IP 打廣告。F5 Big-IP 是一個 HA 的 load balancing System,他會將 request redirect 到 backend server。


這個例子只能證明一件事,只要根據之前講過的 Ruby on Rails 伺服器架設原理,參照類似這樣的架構

這個架構在高負載之下會遇到的問題,在於前端的 HA Server 以及後端的 DB Server,而Ruby on Rails 效率方面是可以很簡單的用增加 Mongrel Server Farm 的數量來解決的。

也就是說,只要後端 DB 夠強夠快,前端的 HA 夠棒,是沒啥大問題的。而這個聳動的例子,因為沒有使用到 DB 的 Operation ,所以 Bottleneck 就只會出現在 HA 這端,只要前端 HA 夠力,別說 4000 req / sec,40000 req / sec 也是沒啥大問題的。

12/30/2006

Ruby on Rails 伺服器架設原理

一般來說,Ruby on Rails 架設原理很簡單,分成三個部份。
  1. Frontend Server
  2. Application Server
  3. Database Server
每個部份都有自己的功用。


Frontend Server 負責將所有 HTTP Request forward 給後端的 Application Server,也就是他是作類似 Reverse proxy 的工作。一般來說,Apache 2.2 跑 mod_reverse_proxy 是最常出現的選擇,nginx 也是不錯的選擇。Lighty 1.5 之後跑 mod_proxy_core 也很方便,等到 1.5 release 之後我會作詳細的評估。
Application Server 負責跑 Ruby on Rails 程式,你寫好的程式就在上面跑。一般來說可以用 Webricks,Fastcgi,scgi,Mongrel 等等 Ruby on Rails Runner來跑。Webricks 太慢,Fastcgi 有穩定性,以及不好設定的疑慮。SCGI 太年輕。目前最穩,最好用,而且已經被驗證過的 Application Server 就是 Mongrel。

Database Server 就是處理資料處理的工作。可以跑 SQLite,MySQL 之類的 RDBMS 。甚至使用 File 來當資料處理,或是使用 NFS 也未嘗不可。不過這裡通常大家都是使用一般大廠的 RDBMS資料庫。

組合方式

Apache 2.2 + Mongrel:穩定,高彈性的組合

Apache 2.2 遇到 user request 用 HTTP 分配給 Mongrel ,然後 Mongrel 去跑。這個組合的好處是每個 Application Server node 都可以很輕易的拆成不同台機器,並且很好管理。Apache 的穩定又是出名的。雖然不見得最快,但是方便 scale 以及穩定是他最好的優點。目前所有組合當中最穩定的方式,很多流量最大的 Ruby on Rails 站台也都是使用這個方式。適合在已經有一定規模的網站。設定方式在此我有介紹

Lighttpd + Fastcgi:單機最佳選擇
Lighttpd 1.4 跑 PHP 或是跑 Ruby on Rails 都是這樣跑。Lighttpd 為 Frontend Server ,他接到 request ,經由 unix socket 送給身為 Application Server 的 Fastcgi ,Fastcgi 再執行 Ruby on Rails 程式。通常這個方式是 Frontend Server 跟 Application Server 跑在同一個機器上面的,當然每個 Fastcgi 也可以跑在 TCP Mode ,然後 Fastcgi 放在不同機器上面,不過設定不易不常使用這個方式。這個組合的好處是執行效率非常快速,如果 Frontend 跟 Application 放在同一台機器上,Lighty 這個組合遠比 Apache 的組合來得輕快許多。但是缺點是多台機器設定複雜,不易擴展到多台機器上,Fastcgi 又有在高負載下罷工的負面報導。相反的,單台機器上面 Fastcgi 設定管理簡單,速度又飛快,非常適合小網站剛剛起步時,機器不足,流量不大的需求。設定方式在此我有介紹

Nginx or Lighttpd 1.5 + Mongrel:未來的新選擇

類似Apache 的組合,但是 nginx 或是 Lighttpd 1.5 都有一個優點,不像 Apache 2.2 那麼肥。反正這個 Frontend 只要作 reverse proxy 的工作,其實不需要 Apache 那麼大的 Server 來作。好處是 Frontend Server 比較快速。壞處是 nginx 這個俄國來的 Server 大家不熟悉,doc 又很少(俄文是很多啦)。Lighttpd 1.5 又只在 pre-release 階段,穩定程度還是得花點時間。不過如果扣掉 Frontend 的 X factor,這個組合兼具輕快跟方便 Scale ,可說是最好的組合。lighty 1.5設定方式在此我有介紹。nginx 的設定檔這裡有範例,可以參考。




12/21/2006

Rails + Memcached

這篇介紹如何將 Memcached 跟 Rails 做一個結合,先介紹一下 Memcached 這個著名的套件。Memcached 是一個分散式的 Memory Object 架構,最早是 Life Journal Team 為了加快速度而開發的套件。 他可以啟動許多 Deamon 來將所有其他 Client 的 Object 都集合起來,並且做到多機器同步化的工作。他最大的優點是在於不需要考慮資料 ACID,所以速度方面相當的快。

當然,我們可以使用 Database 去做到一模一樣的事情,但是其實 Database 在 ACID 上面已經付出太多 Overhaed。如果今天需要操作的東西,是一些像是 Cache ,Session 之類真的不見就算了的東西的話,你可以考慮使用效率比 Database 快的 Memcached。目前已經有相當多的網站使用 Memcached 的技術,可說是相當成熟。並且在 Web Server 使用考量上,Web Server 通常使用資源是高 CPU 低 Memory ,而 Memcached 是低 CPU 高 Memory 的使用方式,兩者可以結合彼此優缺點,讓 Web Server 跟 Memcached 跑在同一台機器上面來避免浪費資源使用率。

以 Ruby on Rails 來看,Memcached 可以用在
這三個用途。

我目前使用他都是在 Session Store 這個部分,他可以將 Multi Backend Application Server 的 Session 存放放在同一處,當然可以提高Rails Scaling 的部分。而在實做上面,Memcache 沒有設定檔。要在 Master 啟動一個 2G Memory,listen 在 1.2.3.4 ,port 11211 的 Memcache Deamon 是這樣啟動的
# ./memcached -d -m 2048 -l 1.2.3.4 -p 11211
Ruby 要使用 Memcached 是非常的簡單,只要用 Gem 安裝 Ruby 的 Memcached Client 即可。

這裡有兩個選擇,一個是出現在很多書上面的 ruby memcache ,也是比較老牌的選擇。
gem i ruby-memcache
但是現在還有更新的選擇, Robotcoop 所開發的 Ruby Memcached Client AP

# gem install memcache-client

要選擇其實是很容易的,因為兩者的 API 實做都一模一樣,應該說 memcached-client 遵照 ruby-memcached 的 API,但是 memcached-client 效能比 ruby-memcached 來得好,所以請用 memcached-client 吧。

要在 Rails 上面使用 Memcached 來當作 Session Handler 也相當的簡單,將 session store 設為 memcached 即可。你可以在 enviroment.rb 加入
require 'memcache'

memcache_options = {
:compression => false,
:debug => false,
:namespace => "app-#{RAILS_ENV}",
:readonly => false,
:urlencode => false
}
memcache_servers = [ '192.168.1.150:2222', '192.168.1.150:2223' ]

Rails::Initializer.run do |config|
....
config.action_controller.session_store = :mem_cache_store
...
config.action_controller.fragment_cache_store = :mem_cache_store, memcache_servers, memcache_options
...
end

...
cache_params = *([memcache_servers, memcache_options].flatten)
CACHE = MemCache.new *cache_params
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.merge!({ 'cache' => CACHE })

其實 Rails 對於 Scale 的準備還算是相當的完整,很多地方都有相當簡單方便的實做。



延伸閱讀



12/14/2006

Apache 2.2 + Mongrel 設定方式

本來沒有打算寫的,不過看到 RailsCN 似乎有人有問題,所以還是順便寫一下好了。架設一些觀念在此我有作介紹,可以參考一下。


設定 Mongrel Cluster

請將你的 Mongrel Cluster 設定好,這裡預設 port 從 4000 ~ 4009 ,一共十個,跑在 production 環境下
mongrel_rails cluster::configure -e production -p 4000 -N 10
mongrel_rails cluster::start
修改 Apache 2.2 設定檔

Apache 的設定檔放在 httpd.conf ,以下修改內容皆在 httpd.conf 裡面設定。

首先確定你的 Apach 2.2 有 enable apache 的其中一個 Module mod_proxy
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
再來我們開始設定 Mongrel Cluster 的 reverse proxy 設定,首先我們給這組 cluster 取名叫做 examplecluster,他是10組 Mongrel ,跑在 port 4000 ~ 4009 之中
<proxy balancer://examplecluster>
# cluster member 1
BalancerMember http://127.0.0.1:4000
BalancerMember http://127.0.0.1:4001
....
BalancerMember http://127.0.0.1:4009
</proxy>
再來假設你的 hostname 為 example.com,我們開始設定 virtual host
<virtualhost example.com:80>
ServerName example.com
ServerAdmin root@example.com
DocumentRoot "/var/www/example.com/htdocs"
ProxyPass /images !
ProxyPass /stylesheets !
ProxyPass /javascripts !
ProxyPass / balancer://examplecluster/
ProxyPassReverse / balancer://examplecluster/
</virtualhost>

重點是在於 ProxyPass,ProxyPass 代表 images,stylesheets,javascript 等 static file 交給 Apache 處理,不要給 Mongrel 處理。 還有 ProxyPassReverse 要指定正確的 cluster name ,我們要指定為 examplecluster。

最後重起 Apache 即可。本設定改自著名的文章 Scaling Rails with Apache 2.2, mod_proxy_balancer and Mongrel,還有 Robin 的 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails。設定是在 Gentoo Linux + Apache 2.2.3 + Mongrel 跑完全沒有任何問題。