提升Ruby on Rails效能的幾個解決方案_ruby專題

來源:互聯網
上載者:User

簡介

Ruby On Rails 架構自它提出之日起就受到廣泛關注,在“不要重複自己”,“約定優於配置”等思想的指導下,Rails 帶給 Web 開發人員的是極高的開發效率。 ActiveRecord 的靈活讓你再也不用配置繁瑣的 Hibernate 即可實現非常易用的持久化,Github 和 Rubygems 上豐富多樣的 Rails 外掛程式是 Rails 開發高效率的又一有力保障。Rails 是一個真正徹底的 MVC(Model-View-Controller) 架構,Rails 清楚地將你的模型的代碼與你的控制器的應用邏輯從 View 代碼中分離出來。Rails 開發人員很少或者可能從未遇到過某些代碼該放於哪一層的困擾,在 Rails 的世界中,你的代碼的職責很清楚的被定位,你可以輕鬆的決定出它們應該位於哪一層。Rails1.2 之後的版本開始支援 Rest Service,通過這些內嵌的特別,你在開發你 Web 應用程式,展現給使用者 HTML 的頁面的同時,幾乎不費吹灰之力,就可又提供基於 Rest API 的 Web Service,另外,你也可以方便的像使用基本資料的 Model 一樣的去消費第三方提供的基於 Rest API 的 Web Service。

通過搜尋引擎,你可以找到很多類似於用 Ruby On Rails 十五分鐘建立 Blog 系統等類似的使用 Rails 進行快速開發的文章。 Ruby On Rails 對于敏捷開發過程的也是非常友好,在 Rails 架構中整合了 Unit Test, Function Test 對你的 Model 和應用邏輯進行測試。通過這些,你不需要再安裝任何外掛程式或者程式庫便可方便的進行測試驅動開發,通過 Watir 的支援,你可以輕鬆的用 Ruby 代碼實現基於瀏覽器的自動化的測試。 另外,在 Rspec 等外掛程式的支援下,你甚至可以進行行為驅動開發(Behaviour Driven Development),讓你的測試代碼變得更加有意義,也更加容易被客戶所接受。

雖然 Rails 的優點你可以一下子列出很多,你也可能會拿出用 Java/Hibernate/Spring/Struts 和 Ruby On Rails 開發同樣功能 Web 應用程式的程式碼比較來舉例,或者提供進行 Java/Hibernate/Spring/Struts 和 Ruby On Rails 開發所需要接受的培訓資料的書籍的對比照片來舉例,但我們都不可避免的會面對延展性(Scalability)的問題。很多 Web 應用程式會面對大量的使用者群,這樣的應用會遇到很大的並髮帶來的效能的考驗。 Rails 在這一點上,並沒有讓所有人信服,依然有很多的系統架構師和工程師對 Rails 是否適用於開發高負載高並發的 Web 應用程式持懷疑的態度。但不可否認,隨著 twitter, friends for sale,basecamp 這類大負載量的應用的出現,Rails 也越來越被認識是可擴充的,這些成熟的應用也告訴我們,開發出同時處理數百萬使用者請求的 Rails 應用是可能的。Ruby On Rails 架構在延展性上為人詬病無非集中於以下幾點,Ruby 語言本身效能問題,Ruby On Rails 缺少成熟的高效能的應用伺服器,對資料庫擴充的支援,互連網上缺乏可熟可靠的網路供應商等等。 本文將從這些點出發,介紹具延展性的 Rails 應用程式的部署架構,以及開發高效能的 Rails 應用程式的一些比較好的具體實踐。

通常的 Web2.0 應用,特別是高負載的應用,除了 Web 和應用伺服器選擇 , 負載平衡這類部署需要面對的問題之外,通常還必須得面對背景工作,高效能全文檢索搜尋這些開發上的問題,這些在 Java 或者 PHP 這些比較成熟的開發環境裡面都有比較成熟的方案,開發和架構人員通常都會有多種選擇,結合具體應用做出架構設計。在新興的 Rails 社區,這些還並不完善和成熟,本文將介紹一些高效能可伸縮的 Rails 應用程式的開發和部署的具體實踐,針對通常 Web 2.0 網站所遇到的具體問題做出分析和解決方案,旨在給 Rails 開發人員提供具體的參考。本文將介紹的內容可以用下圖來綜合表示:
圖 1. 本文總體結構

使用 Nginx+Passenger 來替代 Apache+Mongrel 來部署 Rails 應用

事實上,進行 Rails 部署可以描述得非常簡單,我們需要一些機器配置我們的環境,為了效能和成本,我們理所當然選用 Linux 系列的伺服器,可選的有 CentOS,Debian, Ubuntu Server 等。本文的所有程式,命令以及代碼如非特別說明,都預設是以 Linux 為基本環境的。 然後我們需要資料庫儲存我們的資料,我們可以選用免費的 Mysql,然後我們便開始開發我們的 Web 應用程式的 Rails 代碼,部署時,我們需要支援 Ruby On Rails 的應用伺服器讓我們的 Rails 代碼跑起來,這可能是 Rails 內建的 Webrick,當然這個可能性極小,也可能是 FastCGI, 或者是 Mongrel,Thin, Passenger 等等,然後我們通過 Apache,Nginx,Lighttpd,HAProxy 之類的 Web 服務器訪問我們的應用伺服器,這個訪問可以直接通過 HTTP 協議,也可以是 FastCGI,或者是自訂的其它協議,如此這般,我們便可以通過瀏覽器訪問我們的應用程式了。如下圖所示,這便是通常的 Rails 應用程式部署結構。
圖 2. Rails 應用程式部署結構

對於前端的 Web Server,Apache 是事實上的工業標準,在 Web 服務器市場,是佔有率最高的,全球大量的網站採用 Apache 來部署他們的應用,Apache 是一款成熟穩定的 Web 服務器,功能非常強大,提供對幾乎所有 Web 開發語言和架構的擴充支援,在對 Rails 架構的支援上,我們可以採用 mod_fcgid 模組,通過 FastCGI 協議與 Rails 進程通訊。或者利用 mod_proxy_balancer 對後端的獨立的 Rails 伺服器如 Thin Cluster,Mongrel Cluster 或者 Apach/Nginx+Passenger 進行 HTTP 分發。但 Apache 作為一個通用的伺服器,在效能上和一些輕量型的 Web 服務器相差甚遠。Apache 的 mod_proxy_balancer 模組的分發效能不高,比 Nginx 或者 HAproxy 都相差很多,另外,Apache 目前並不支援 Event(事件)模型,它僅支援 Prefork(進程)模式和 Worker(線程)模式,每處理一個連結,就需要建立一個進程或線程,而一些輕量級 Web 服務器如 Nginx 和 Lighttpd,則都很好地利用核心的事件機制提高效能,極大減少線程或進程數量,降低系統負載。

Nginx 是一個輕量級的高效快速的 Web 服務器,它作為 HTTP 伺服器和反向 Proxy伺服器時都具有很高的效能。Nginx 可以在大多數 Unix like OS 上編譯運行,並有 Windows 移植版。 Nginx 選擇了 Epoll 和 Kqueue 作為開發模型,它能夠支援高達 50,000 個並發串連數的響應,可以在內部直接支援 Rails 和 PHP 程式對外進行服務。另外,Nginx 作為負載平衡伺服器,也可以支援作為 HTTP Proxy 伺服器對外進行服務 , Nginx 不論是系統資源開銷還是 CPU 使用效率都比 Apache 要好很多。當你開啟 Nginx 官方網站,你會發現一個如此知名的 Web 服務器產品的官方首頁竟然如此簡單,其實,Nginx 本身就是一個安裝非常簡單,設定檔非常簡潔,甚至可以在設定檔中使用 Perl 文法。

在處理靜態檔案上, Apache 和 Nginx 都可以勝任。但對於應用伺服器或者是前端的負載平衡伺服器,我們推薦 Nginx 而不是相對 Nginx 較為重量級的 Apache。

對於應用伺服器,Mongrel 一度是最流行的部署方式,它的 HTTP 協議的解析部分是用 C 語言編寫的,效率上有所保證。Mongrel 使用了 Ruby 的使用者線程機制來實現多線程並發 , 但是 Ruby 並不是本地線程 ,Rails 也不是安全執行緒的,因此 Mongrel 在執行 Rails 代碼的過程中,完全是加鎖的狀態,那和單進程其實也沒有太大差別。所有我們在使用 Mongrel 來部署 Rails 應用程式時,一般是在後台啟動一個 mongrel_cluster 來啟動多個 Mongrel 進程,如我們在 mongrel_cluster.yml 中進行如下配置可以在 8000~8009 連接埠啟動 10 個 Mongrel 進程。
清單 1. Mongrel_cluster.yml 配置

 ---  cwd: /var/www/test_app  log_file: log/Mongrel.log  port: "8000" environment: production  debug: false  pid_file: log/mongrel.pid  servers: 10

這樣的部署方式實際上也限制了 Mongrel 處理大並發應用的能力,在處理大資料量請求的時候,Mongrel 進程經常被掛過,但並發數一多,就會出現所有的 Mongrel 進都會被掛過的情況,這樣前端的伺服器便得不到返回,整個 Web 應用程式就陷入癱瘓。所以,Mongrel 並沒有被廣泛採用,很多網站寧願堅持使用最古老的 FastCGI 的部署方式也不使用 Mongrel 來部署應用,而且 Mongrel 也停止更新很久,Mongrel 的開發人員已完全不再進行 Mongrel 的開發了。所以,Mongrel 並不是現在最推薦的 Rails 應用伺服器。

Passenger 是類似於 mod_php 的 Rails 運行環境,而不是 Mongrel 那樣是獨立的 Http 伺服器。Passenger 對目前主流的 apache 和 Nginx 兩大 Web 服務器都有支援。Passenger 使用起來極其方便,而且它具有較高的效能,從 Passenger 官方網站公布的測試結果來看,Passenger 的效能要優於 Mongrel 伺服器,目前來說,Passenger 無疑是最好的選擇。Passenger 繼承了 Rails"不重複自己"的慣例,通過 Passenger 部署應用程式,你僅僅需要將 Rails 項目程式檔案上傳到目標伺服器,甚至都不需要重啟伺服器,非常簡單。

要在 Nginx 環境下安裝運行 Passenger, 你僅僅需要如下操作:
清單 2. 安裝 Passenger

 gem install passenger  Passenger-install-nginx-module

下面的代碼展示了在 Nginx 上配置 Passenger:
清單 3. 在 Nginx 上配置 Passenger

 http {   ...   server {     listen 80;     server_name www.test.com;     root /var/www/test/public;     passenger_enabled on;   }   ...  }

通過 Nginx+Passenger 構建 Ruby On Rails 的應用伺服器可以得到顯著的效能提升,同時,還可以採用 Ruby Enterprise Edition 來提升 Ruby 本身的效能。這個版本也是由 Phusion 開發的,採用 copy-on-write 的記憶體回收策略,並使用 tcmalloc 來改善記憶體配置,他們的網站公布的資料,使用 Ruby Enterprise Edition 能比普通的 Ruby 版本減少 33% 的記憶體消耗。

Nginx+Passenger 就部署在一台機器上的應用伺服器,但並發過大時,一台機器並不足以來提供這樣的處理能力,這個時候,一般會做負載平衡,這和通常的負載平衡策略並無二異,Nginx 在使用反向 Proxy來實現負載平衡的能力上要強於 Apache 的反向 Proxy模組,我們可以在多台 Nginx+Passenger 的前端可以再增加一台 Nginx 的 Web 服務器。甚至為了更強的處理能力,我們也可以採用 LVS 來進行負載平衡。

使用 Starling 和 Workling 去非同步執行 Rails 背景工作

在進行 Web 應用程式開發時,每個 Web 請求都需要迅速的得到返回,這時候有些計算量比較大的操作可以放在後台去非同步執行,比如大量的資料更新操作,只需要在 Web 應用程式中進行觸發,然後在後台進行執行。而有些操作則需要定期去執行,比如資料的備份,一些資料的統計分析,圖片的處理,郵件的發送等等。這些操作如果放在 Web 應用程式中即時返回顯然是不合適的,而且也會帶來機器的負載很嚴重,對於 Rails 應用程式來說,除了影響使用者體驗,這樣的操作還會阻塞 Rails 伺服器執行個體,從而帶來整體效能的下降。對於這類操作,我們可以使用一個任務隊列,將需要執行的操作依次入隊,然後在後台再啟動進程進隊列中取出這些任務,並執行,隊列可以使用資料庫,Memcached, ActiveMQ 或者 Amazon SQS 來實現,而後端進程則可以使用 Rails 裡面的 cronjob+script/runner 或者 BackgrounDRb 等等來操作。這裡要介紹的解決方案則是採用 twitter 開發人員貢獻出來的採用 Memcache 協議的 Starling 訊息佇列和 Workling 外掛程式來進行實現。

Starling 是 twitter Team Dev從 twitter 項目抽象出來開源的 Rails 外掛程式,雖然說 Starling 並不完全就是 twitter 的線上版本所用的外掛程式,但我們也可以足以相信 Starling 的效能和應對高並發的處理能力。類似的外掛程式還有 backgroundrb,background job, background_fu。backgroundrb 是使用 drb 實現隊列的訊息傳遞,但它還有一個問題,更新隊列的時候,backgroundrb 使用的是悲觀鎖,在大訪問量的情況下,這種情況是不容允許的。 background job 和 background_fu 則是基於資料庫的訊息佇列,在大負載量的情況下資料庫的效能也不容易得到保證。而 Starling 是基於 Memcached 協議的訊息佇列,效率更高,也更容易伸縮,通常你可以在每台應用伺服器上都運行一個 Starling 伺服器,並在同一台機器或者其它機器上去運行背景程式與之互動。

我們通過如下命令來安裝 Starling:
清單 4. 安裝 Starling

 gem sources -a http://gems.github.com/  sudo gem install starling-starling  mkdir /var/spool/starling

在讀取 Starling Server 時,我們需要 memcache-client,這個 gem 的 1.5.0 版本有一些問題,在 fiveruns-memcache-client 得到修正,這個 fiveruns-memcache-client gem 在 starling-starling gem 中是作為依賴項自動安裝的。

安裝完 Starling 之後,使用 sudo Starling -d -p 15151 這個命令來啟動它,啟動時用 -p 參數來指定所要使用的連接埠,一般加 -d 參數使它以 daemon 方式在後台運行:

為了明白 Starling 的機制和 Starling 究竟做了哪些工作,在啟動了 Starling 之後,我們可以使用我們開啟 irb 下面的程式來進行簡單的測試:

進行簡單的測試
清單 5. 測試 Starling

 >> require 'starling' => true  >> Starling = Starling.new('127.0.0.1:15151)  => MemCache: 1 servers, ns: nil, ro: false  >> Starling.set('test_queue', 123)  => nil  >> loop { puts Starling.get('test_queue'); sleep 1 }  123  nil  nil  ...

這裡我們可以看到確實啟動了 Server,然後我們向這裡插入資料,我們用一個迴圈去訪問這個隊列,最後的輸出便是我們想要的結果。

接下來我們安裝 workling:
清單 6. 安裝 workling

 script/plugin install git://github.com/purzelrakete/workling.git

Workling 支援多種方式來進行背景工作操作,其中就包括上面已經安裝的 Starling,安裝好 Starling 後,我們需要在 Rails 應用程式中的 environment.rb 加上以下代碼來配置 Workling 使用 Starling:
清單 7. 使用 workling

 Workling::Remote.dispatcher = Workling::Remote::Runners::StarlingRunner.new

Workling 的設定檔在 workling.yml, 和其它 Rails 的設定檔類似,workling.yml 也可以針對不同產品模式進行不同的模式,這裡僅列出 production 的配置。
清單 8. Workling 配置

 production:    listens_on:localhost:15151, localhost:15152, localhost:15153    sleep_time: 2    reset_time: 30    memcache_options:     namespace: myapp

listens_on 參數即為 workling_client 去訪問的 Starling 啟動的地址和連接埠,這裡可以允許多個 Starling 地址,這就意味著你啟動多個 Starling 伺服器,而用一個 workling_client 去調用。sleep_time 即為 workling_client 去隊列中取資料的等待時間,reset_time 則定義了如果出現 memcache 錯誤時,workling_client 等待去重建和伺服器串連的時間。 在 memcache_options 的 namespace 參數則定義了所使用的命名空間,這在同一台伺服器如果為不同的 Rails 應用啟動同一個 Starling 伺服器時是非常有用的。

用 script/workling_client start 指令碼便可以啟動 workling_client 進程,有時候我們覺得一個 workling_client 不夠用,我們可以修改 script/workling_client start 來支援多個 workling_client 執行個體,這樣每運行 script/workling_client start 一次都會新啟動一個 workling_client 執行個體。
清單 9. 多 client 的 Workling 配置

 options = {  :app_name  => "workling",  :ARGV    => ARGV,  :dir_mode  => :normal,  :dir    => File.join(File.dirname(__FILE__), '..', 'log'),  :log_output => true,  :multiple  => true,  :backtrace => true,  :monitor  => true  }

使用 Memcached 和 cache-money 來快取資料

Rails 自身提供四種緩衝方式,即 Page Cache, Action Cache,Fragment Cache 和 ActiveRecord Cache 這三種緩衝。Page Cache 是最高效的緩衝機制,他把整個頁面以靜態頁面 HTML 的形式進行緩衝,這對於不會經常發生變化的頁面是非常有效。Action Cache 是對某個 action 進行緩衝,與 Page Cache 的區別在於:HTTP 要求會經過 Rails 應用伺服器,直到所有的 before filters 都被處理,這種緩衝就能處理 Page Cache 無法處理的如需要登入驗證的頁面,可以所驗證的步驟加入 before filter 中,Fragment Cache 則為了快取頁面面中的某一部分,同一個頁面中的不同部分還可以採用不同的到期策略。對於 Rails 本身的緩衝機制,我們可以寫 sweeper 進行到期和清除的處理。ActiveRecord Cache 則是較新版本 Rails 中新推出的對 ActiveRecord 的緩衝機制,使用 SQL 查詢快取,對於同一 action 裡面同一 SQL 陳述式的資料庫操作會使用緩衝。

Rails 的緩衝機制能非常有效提升網站效能,Rails 預設是將緩衝存在於檔案系統中,這並不是適合生產環境下的儲存方式,檔案 IO 的效率有限,Rails 還支援在同一進程的記憶體中儲存 Cache,但如果有多個 Rails application,它們之間不能共用快取。我們這裡推薦的是以 MemCached 的方式進行儲存,這也是目前是流行的緩衝儲存方式。

Memcached 是由 Danga Interactive 開發,用於提升 LiveJournal.com 訪問速度的。LiveJournal.com 每秒有幾千次動態網頁面訪問量,使用者 700 萬。Memcached 是一個具有極高效能的分布式記憶體對象緩衝系統 , 基於一個儲存鍵 / 值對的雜湊表。其守護進程(daemon)是用 C 寫的 , Memcached 將資料庫負載大幅度降低,更好的分配資源,更快速存取。可以用各種其它語言去實現用戶端。上文的介紹中已經安裝了 Rails 的 Memcached 用戶端,因為我們只需要在 Rails 應用程式中做如下配置:
清單 10. Memcached 配置

 config.cache_store = :mem_cache_store, 'localhost:11211'

便可以進行使用 MemCached 進行快取資料。除了 Rails 本身的緩衝機制,我們還直接用 Rails.cache 操作 Memcached 進行資料緩衝,如,我們讀取所有 blog 的數量,可以如下使用緩衝:
清單 11. 使用 Rails.cache

 blogs_count = Rails.cache.fetch("blogs_count") do   Blog.count  end

Rails 自身的 ActiveRecord 作用有限,只適用同一個 action 中的 SQL 查詢語句進行緩衝,我們需要一個更強大的 ActiveRecord 緩衝,而 cache-money 更是為瞭解決如此問題而推出的。當 twitter 網站變得越來越穩定,逐漸擺脫被人拿來作為"Rails 無法擴充的"典型例子的陰影時,人們便期待 twitter Team Dev能向 Rails 社區有更多的貢獻,cache-money 便是在 Starling 之後 twitter 團隊貢獻出來的另一個外掛程式。cache-money 和 Hibernate 的二級緩衝類似,是一個讀寫式(write-through)緩衝。在 ActiveRecord 對象更新的時候不是將緩衝中的資料清除,而是直接將更新的內容寫入到緩衝中去。

cache-money 有許多很棒的特性,如:緩衝自動清除機制 ( 利用 after_save/after_destroy) ;支援事務,由於 Rails 的 Active Record 沒有提供 after_commit 機制,目前常見的快取區外掛程式在高並發下會出現緩衝更新競爭衝突,而這個特性對於解決這個問題會很有協助,可以通過 gem 來安裝 cache-money:
清單 12. 安裝 cache-money

 gem sources -a http://gems.github.com  sudo gem install nkallen-cache-money  require 'cache_money'

清單 13. 配置 config/memcached.yml

 production:  ttl: 604800  namespace: ...  sessions: false  debug: false  servers: localhost:11211  development:   ....

清單 14. 使用 config/initializers/cache_money.rb 來初始化

 config = YAML.load(IO.read(File.join(Rails_ROOT, "config", "Memcached.yml")))[Rails_ENV]  $memcache = MemCache.new(config)  $memcache.servers = config['servers']  $local = Cash::Local.new($memcache)  $lock = Cash::Lock.new($memcache)  $cache = Cash::Transactional.new($local, $lock)  class ActiveRecord::Base  is_cached :repository => $cache  end

使用 cache-money 非常方便,不需要額外的操作,只需要在你的 Model 裡面進行簡單的配置,如:
清單 15. 配置 Model 來使用 cache_money

 class User < ActiveRecord::Base  index :name  end  class Post < ActiveRecord::Base  index [:title, :author]  end  class Article < ActiveRecord::Base  version 7  index ...  end

然後便可以跟以前一樣使用 Rails ActiveRecord 各種方法以及事務操作。如果你改變了資料庫的表結構,你可以改變 Model 的版本號碼來使以前的緩衝失效,而不需要重啟 Memcached 伺服器。

使用 Sphinx+LibMMSeg+Ultrasphinx 進行全文檢索搜尋

很多應用會有全文檢索搜尋的需求,當然你可以直接整合 google 或者其它搜尋引擎提供的搜尋服務,但如果你要更好的控制你的搜尋結果,或者對你的搜尋結果進行再次利用,你恐怕必須得自己實現全文檢索搜尋了。在進行中文全文檢索搜尋時,一般要考慮兩個方面的問題,即所使用搜尋工具的效能問題,以及中文分詞的準備度。在 Java 的世界裡,Lucene 是做全文檢索搜尋絕對的權威和首選,雖然它本身沒有對中文分詞很好的支援,但有很多第三方外掛程式可以利用來提高中文分詞的準備率和效能。Ferret 一度是最流行的 Rails 全文檢索搜尋外掛程式,但本文推薦是效率更高的 Sphinx。Sphinx 是俄羅斯人 Andrew Aksyonoff 開發的,這個詞的意思“獅身人面”,它能在一兩分鐘的時間內完成數百萬條記錄的索引,並在毫秒級的時間類返回搜尋結果。 Sphinx 和資料庫整合良好,可以通過設定檔,直接用來對資料庫的資料進行索引,另外,Sphinx 開發了一個 SphinxSE 資料庫引擎,可以在編譯 Mysql 的時候直接編譯到 Mysql 裡面去來實現資料庫層級的高效能索引。在 Rails 中使用 Sphinx 可以通過 Ultrasphinx 外掛程式,Rails 開發人員可以使用它來很方便地調用 Sphinx 的功能。

可以從這裡 http://www.sphinxsearch.com/downloads.html 下載 Sphinx

在安裝好 Sphinx 後可以直接從 Rubyforge 上安裝 Ultrasphinx:
清單 16. 安裝 ultrasphinx

 Ruby script/plugin install svn://Rubyforge.org/var/svn/fauna/ultrasphinx/trunk

LibMMSeg 就是一個中文分詞程式,當前最新版本是 0.7.3,採用 C++ 開發,分詞演算法採用的是“複雜最大匹配 (Complex maximum matching)”,同時支援 Linux 平台和 Windows 平台,切分速度大約在 300K/s(PM-1.2G),LibMMSeg 從 0.7.2 版本開始,作者提供了 Ruby 調用的介面,所以我們可以直接在 Ruby 中用 LibMMSeg 進行分詞,相當方便。LibMMSeg 可以通過 http://www.coreseek.cn/opensource/mmseg/ 來下載安裝。

使用者可以通過修改詞典檔案增加自己的自訂詞,以提高分詞法在某一具體領域的切分精度,系統預設的詞典檔案在 data/unigram.txt中。 然後通過 mmseg -u unigram.txt這個命令來產生一個名為 unigram.txt.uni的檔案,將該檔案改名為 uni.lib,完成詞典的構造。需要注意的是,unigram.txt必須為 UTF-8 編碼。

LibMMSeg 的開發人員為了更好的讓 Sphinx 使用 LibMMSeg 進行中文分詞,為 Sphinx 開發了相關的補丁,從這裡 http://www.coreseek.cn/opensource/Sphinx/ 下載兩個補丁檔案:

http://www.coreseek.com/uploads/sources/sphinx-0.98rc2.zhcn-support.patch

http://www.coreseek.com/uploads/sources/fix-crash-in-excerpts.patch

然後打上補丁:
清單 17. 安裝 Sphinx 補丁

 cd sphinx-0.9.8-rc2  patch -p1 < ../sphinx-0.98rc2.zhcn-support.patch  patch -p1 < ../fix-crash-in-excerpts.patch

安裝完這幾個外掛程式和補丁之後,我們便可以進行配置來讓 Rails 應用程式來支援全文檢索搜尋了,

首先我們將 ultrasphinx 外掛程式目錄下的 vendor/plugins/ultrasphinx/examples/default.base複製到:config/ultrasphinx/default.base,開啟這個檔案,將其中的:

charset_type = utf-8改為:charset_type = zh_cn.utf-8來支援中文字元的全文檢索索引, 並且在 charset_type 設定的下面加入一行:

charset_dictpath = /home/test/Search/lib,這個就是上文講到的 uni.lib 字典所在的路徑,然後刪除所有 charset_table 相關的設定。

在 Rails 應用程式中的 Model 代碼,加入全文檢索索引支援:

如有一個 Model 為 Article,其中有兩個屬性叫做 title,body,我希望對這兩個屬性做全文檢索索引,便可以在 article.rb 中加入一行:
清單 18. 使用 ultrasphinx

 is_indexed :fields => ['created_at','title', 'body']

進行完這個配置後,我們可以使用 rake ultrasphinx:configure 這個命令來產生Sphinx 的設定檔,這條命令在 config/ultrasphinx 下建立了一個 development.conf,這個檔案就是 Sphinx 的設定檔。並用rake ultrasphinx:index 這個命令來建立索引。rake ultrasphinx:daemon:start 和 rake ultrasphinx:daemon:stop 則對應著Sphinx 的searchd服務的啟動和停止。searchd 會在 3313 連接埠啟動一個 searchd,搜尋請求將會全部發送到這個連接埠來執行。我們在控制台中進行簡單的測試:
清單 19. 測試全文索引

 search = Ultrasphinx::Search.new(:class_names => 'Article')  search.run  Search.results 

一切運行正常後,我們便可以在 action 的代碼中進行全文檢索搜尋了。

使用 Capistrano 進行快速部署

在進行 Rails 部署的時候你可以直接從 svn 或者 git 下面更新代碼,運行 db:migrate 來進行資料庫的更新,然後進行這樣那樣的操作後,再啟動伺服器,便可進行部署,即便你只有一台機器,你也會覺得太麻煩,如果你需要多台機器來運行,那你可能就會覺得每次手工部署都是一場惡夢,你可以使用 shell 指令碼來簡化部署的程式。在用 Rails 開發應用時,你可以使用 Capistrano 外掛程式來進行更簡單的部署工作。簡單來說,Capistrano 是一個通過 SSH 並行的在多台機器上執行相同命令的工具,使用用來安裝一整批機器。 它通過一個個已有的和使用者自定製的任務讓部署過程簡單化。
清單 20. 安裝 Capistrano

 gem sources -a http://gems.github.com/  gem install Capistrano

然後在 config/deploy.rb 中配置要部署的伺服器的地址,各種伺服器的角色以及每個伺服器統一的使用者名稱和密碼,如下面的範例配置:
清單 21. 配置 Capistrano

 set :application, "test_app" # 應用的名稱 set :scm_username, "test"  # 資產庫的使用者名稱 set :scm_password, 'test'  # 資產庫的密碼 set :repository, Proc.new {"--username #{scm_username}  --password #{scm_password} svn://localhost/test_app/trunk"}   # 資產庫 set :user, "test"  # 伺服器 SSH 使用者名稱 set :password, 'test' # 伺服器 SSH 密碼 set :deploy_to,    "/var/www/#{application} "  # 在伺服器上的部署路徑,預設的部署路徑是 /u/apps/#{application}  role :Web, 'Web.test_app.com' # 前端網頁伺服器 role :app, 'app1.test_app.com', 'app2.test_app.com', 'app3.test_app.com' #Rails 應用伺服器 role :db, 'app1.test_app.com', :primary => true  # 運行 migrate 指令碼的機器,通常為其中一台應用伺服器。

在使用 Capistrano 進行部署的時候,通常是這樣使用 cap sometask來運行任務。你可以先用 cap -h查看所有的選項,並用 cap -T查看現有的所有任務。如 cap migrate則在 role 為 db 的機器上執行 rake db:migrate命令。使用 Capistrano 的更多資料可以參考 http://wiki.capify.org 這個網站。另外,Capistrano 還可以使用在非 Rails 環境下進行自動部署,在配置好 ruby 環境和 Capistrano 外掛程式後,再安裝下面的外掛程式即可:
清單 22. 非 Rails 環境使用 Capistrano

 gem sources -a http://gems.github.com/  gem install leehambley-railsless-deploy

結束語

本文著重使用 Ruby On Rails 來開發和部署 Web 應用程式時一些有用的具體實踐,沒有具體去介紹一些通常應用程式都需要面對的普遍問題,如資料庫的最佳化和分布式部署,這是一個大並發的 Web 應用程式都需要面對和解決的問題,比如可以採用 master-slave 的方式去部署分布式的資料庫,或者採用分庫或者分表的方式對資料庫進行拆分。另外,在運行 Rails 伺服器或者其它後台應用程式時,通過還需要另外的進程去進行監控,如用 God 去監控 Rails 進程也是一個 Rails 應用通常都會採用的策略。另外,很多時候,可以採用更敏捷更輕量級的 Rack 去代替 Rails 來進行更高效的開發的提供服務。並且,Engineyard ,Joyent 以及 Heroku 等這類 Rails 網路供應商的湧現也在相當程度上堅定了用 Rails 開發和部署大規模大並發 Web 應用程式的信心。雖然 Ruby On Rails 自身的缺陷不可避免, 但是開發可伸縮的高效能的應用程式並不是不可能的。本文希望能夠協助 Rails 開發人員快速掌握一些具體實踐,能夠編寫出並部署效能高伸縮性強的 Web 應用程式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.