about 1 month ago

Arrays: map & each_with_index

在跑陣列(array) for-each 每一個 interation 可以帶上相對應的 index,利用 each_with_index 這個方法:

['a', 'b', 'c'].each_with_index do { |item, index|
  puts "#{index}-#{item}"
}

當然,我們也可以利用 index 對應到的 element 組成一個新的 object:

['a', 'b', 'c'].each_with_index.map { |item, index|
  { :letter => item,
    :position => index }
}

View: cycle is no even odd

在網頁設計上,常為了讓表格內容更容易被閱讀,讓表格每行的顏色交錯,像是:
{}bootstrap-table
正常寫法:

<% an_array.each_with_index do |element, index| %>
  <tr class="<%= index.odd? ? 'odd' : 'even' %>">
    <td>...</td>
  </tr>
<% end %>

在 Rails 有提供一個很棒的 helper 函式 cycle:

<% an_array.each do |item| %>
  <tr class="<%= cycle('odd','even') %>">
<td>...</td>
  </tr>
<% end %>

更多 cycle 用法可參考文件

try

這是 Ruby 語法中最讓我驚艷不已的一個...省掉超級多行。原先為避免對 nil 呼叫產生錯誤,會這樣寫:

if @person.present? && @person.a_property == 'foo'
  ..
end

<% if @an_array.present? %>
  <% @an_array.each do |item| %>
    ...
  <% end %>
<% end %>

學會 try 之後可以這樣寫:

if @person.try(:a_property) == 'foo'
   ...
end

<% @an_array.try(:each) do |item| %>
  ...
<% end %>
 
4 months ago

Sidekiq 在 heroku 的 deployment 可以參照官方的這篇文章:https://github.com/mperham/sidekiq/wiki/Deployment#heroku

大概整理以下要點與步驟:

  • Sidekiq 版本 3.0 以前會自動設定 Redis-to-Go 的相關 Redis 伺服器位置。3.0 後就要自己設定嚕,目前最新版本是 2015/2/6 的 v3.3.2。
  • 新增 heroku add-on: https://addons.heroku.com/
  • 因上點之描述,手動設定 heroku 環境變數,指定 redis server address
    heroku config:set REDIS_PROVIDER=REDISTOGO_URL # Redis to Go add-on
    heroku config:set REDIS_PROVIDER=REGISCLOUD_URL # Redis Cloud add-on
    
  • 重新啟動 heroku 去套用新的環境變數: heroku restart
 
5 months ago

{}order1
點選 WIFI (AirPort) 圖示 -> 網路偏好設定(Open Network Preferences)

{}order2
進去偏好設定後(預設已選取 WIFI) -> 進階(Advanced)

{}order3
從過去連線過的列表中,直接拖曳 WIFI AP 的名稱即可,越上面代表優先權越高。

 
5 months ago

最近因要幫朋友下載連續劇與影片做了些 survey,分享一些成果給大家

一些 BT 種子下載的地方:

下載 youtube, dailymotion 等各大影音平台的 chrome 套件:

註:沒辦法自定義下載的影片檔名,是唯一美中不足的地方。

希望大家也能好好享受 :D

 
5 months ago

稍微分享一下最近一個 rails project hosting 的數據,站上同時有約6000人,有大量使用 view cache。

環境架設部分

  • nginx + unicorn (worker * 4)
  • memcached server 512 MB(同一台機器...)
  • Linode 2G

這是一個純新聞媒體的網站,觀察這樣架構下,面對同時 6000 人,機器 loading 大概約50%不到,粗估是可以到萬人以上水準。

若 memcached 搬出去,再把 worker 數量增加兩個,相信會再更好 :D

 
5 months ago

承上篇PHP5-FPM with Nginx 效能調教 (1)

PHP5-FPM

最近觀察到許多次 php5-fpm 突然不工作的狀況,即連上網站吃到 502 response status。最後於 nginx 的 error log 中找到這樣的錯誤訊息:

[14-Dec-2014 12:20:45] ERROR: failed to ptrace(PEEKDATA) pid 13305: Input/output error (5)
[14-Dec-2014 12:20:45] NOTICE: finished trace of 13305
[14-Dec-2014 12:20:45] NOTICE: child 14008 stopped for tracing
[14-Dec-2014 12:20:45] NOTICE: about to trace 14008
[14-Dec-2014 12:20:45] ERROR: failed to ptrace(PEEKDATA) pid 14008: Input/output error (5)
[14-Dec-2014 12:20:45] NOTICE: finished trace of 14008
[14-Dec-2014 12:20:45] NOTICE: child 20877 stopped for tracing
[14-Dec-2014 12:20:45] NOTICE: about to trace 20877
[14-Dec-2014 12:20:45] ERROR: failed to ptrace(PEEKDATA) pid 20877: Input/output error (5)

原因是由於檔案同時開啟數量的限制:

In your case, the stack trace (to determine what the script is doing) is failing. If you're running out of processes, it is because either:

After php-fpm stops the process to trace it, the process fails to resume because of the error tracing it
The process is resuming but continues to run forever.

唯一辦法即是關掉 slow_log 以及 request_slowlog_timeout,網站便恢復穩定正常!強烈建議實際上線 production 的伺服器不要開啟 php5-fpm 的 slowlog 功能。

PHP5-FPM 參數調教

另外,最近也透過htop觀察到,雖然我們 php5-fpm 的 child process 數量給到破百,但常常同時在執行的數量只有1~3個。

應是因為一般的網站只有在使用者連進來的那一瞬間需要做頁面呈現上的處理,處理完便沒事了,故當然不可能隨時都一直有破百人同時進來,需要這麼多的 php5-fpm process。

所以,除透過自身伺服器可用資源(RAM, # of CPU Core)去調整 child process 數量外,也可透過自身網站的需求去做評估。若網站執行效率不會一直卡著(正常有這狀況也不會讓網站上線吧XDDD),也沒有類似 socket / long polling 之類的需求(即使用者需一直跟伺服器發出 request),那其實 php5-fpm 預設的設定就很足夠惹~

Memcached

通常我們架設 php 網站,例如:wordpress,都會使用 memcached 來做快取,以加快整體網站速度,與降低伺服器與資料庫的承載(loading)。

建議可利用htop觀察 memcached 的使用量,並做適當的調整,如不夠則可以給予 memcached 更多的 memory 供使用。如:

5874 nobody 20 0 246M 121M 2256 S 0.0 1.5 0:00.00 /usr/bin/memcached -m 1536 -p 11211 -u nobody -l 127.0.0.1

可看到目前 memcached 使用了 121MB,而我們實際上給予 1536MB,還有相當充裕的使用空間。

Reference
 
6 months ago

2014年因為工作需求,恰巧有機會調整到兩個台灣百大網站級的伺服器(infra structure),環境主要是 php 網站可執行的條件,有 laravel 開發的,也有放 wordpress 的,曾經最高同時在線人數約有5000~6000水準。以下就針對最近調整一台放 wordpress 的機器心得作分享,主要 mysql server 部分。

調整機器 performance loading 可從三個地方著手

  • Web Server
  • DB
  • Memory Usage (是否充分利用 memory cache)

Web Server 部分可參考本站的PHP5-FPM with Nginx 效能調教 (1)10 Tips For Optimizing NGINX And PHP-Fpm For High Traffic Sites。BTW, 上次那篇文章講解時的環境是 AWS Solution,但這次的需求是 linode,為了省錢而沒有轉去 AWS 使用猛猛的 RDS,是自己架設的 mysql......因此研究了如何調整 mysql

#機器是 CPU Core * 6, 8G RAM

修改 my.cnf (/etc/mysql/my.cnf)

max_connections 1000 # 一般是500~1000
thread_stack 256K # 192K for 32 bit systems and 256K for 64 bit systems. use 'uname -a' to find out
thread_concurrency = 12 # 數量設置為CPU核心數量的兩倍.
thread_cache_size 64 # 按照內存大小來設置, 1G=8, 2G=16, 3G=32, >3G=64
query_cache_limit = 256K # 允許進入查詢緩衝區的最小數據大小,默認值是1MB,可以修改的小一點以滿足更多查詢的需求。但是如果設置的過於小,則會導致很多新的小查詢結果,將原有的查詢結果交換出去,增加系統的不穩。
query_cache_size = 512M # 查詢緩衝,默認是0,所以必須打開以提高mysql性能

確認 mysql 優化是否有效

進去 mysql 後輸入「SHOW STATUS LIKE 'Qcache%';」

查看數據中的 Qcache_queries_in_cache 是否有增加

+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 2698 |
| Qcache_free_memory | 24065728 |
| Qcache_hits | 49367684 |
| Qcache_inserts | 10431164 |
| Qcache_lowmem_prunes | 825016 |
| Qcache_not_cached | 2826264 |
| Qcache_queries_in_cache | 27635 |
| Qcache_total_blocks | 59360 |
+-------------------------+----------+

基本上這些調教都是因為,隨著機器開的越大(因網站流量也大),可用資源就越多,相對我們也會希望 mysql server 使用更多,才會需要去做調整。

Reference

 
7 months ago

總算在前幾天花一個下午嘗試架起 ghost 丟到 heroku 上(免費!),並將文章等等無縫 migrate 到 ghost 上,真是太開燻了~~

透過這次 migration 也貢獻了一下 octoghost,這是一個 python script,可以將 octopress 的 markdown 文章檔案,轉成 ghost 可以 import 的 json 格式作匯入~

用法很簡單,如下:

python octopress2ghost.py <octopress-posts> <ghost-data> | python -mjson.tool > import-this.json
  • < octopress-posts >: 所有 octopress 格式 markdown 檔案的資料夾位置
  • < ghost-data >: 去 ghost 後台匯出一份 json 檔案,然後填入該檔案位置
  • 執行前安裝 pip install translitcodec 即可

會再整理一些安裝過程,希望能讓大家一起加入 ghost blogging,是說編輯器也不難用,是在自己的線上後台,目前為止對於速度還有整個上手度十分滿意。

 
10 months ago

許多時候一個團隊會 hosting 許多平台,且往往各平台間都是有所關聯,像是 flyingv 還有 VShop, VEvent。其會員資料庫都是共用,且同樣的登入方式。若在平台間瀏覽操作需要一直重新登入,是否也太令人不悅了~
因此可以設定這些平台的 cookie (通常登入判斷的資訊都會存於此)為同樣的 Domain,不同的 Sub Domain。例如 domain name 為 example.com,其他平台是 shop.example.com, event.example.com, ...

此處在 Laravel 的設定主要相關三個檔案 app/config/app.php, app/config/cache.php, app/config/session.php,環境為下:

  • Nginx
  • php5-fpm
  • Laravel 4.1
  • PHP 5.5

關鍵1: app/config/app.php

各平台 project 的此檔案 "Encryption Key" 記得相同,可從其中一個 project 複製到其他專案

'key' => 'a random 32 character string',

關鍵2: app/config/session.php

Session Driver 此處假設都為 memcached,Cookie Name 都為 ex_session,Cookie Domain 都為 .example.com

'driver' => 'memcached',
'cookie' => 'ex_session',
'domain' => '.example.com',

若 Session Drive 為 Native,記得設定 files 為同樣的位置

'files' => '/srv/shared/sessions',

關鍵3: app/config/cache.php

因 session driver 指定為 memcached,故此處須設定 Cache Drive 與 memcached server 的位址

'driver' => 'memcached',
'memcached' => array(

        array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100),

    ),

以上完成後便可做到 Cross-Domain 登入 Cookie 的判斷,若無法可以試試看重新啟動 php5-fpm,將 cgi 中 cache 住的 php script 更新。

 
about 1 year ago

在開始前建議先去安裝 htop 這個 linux 即時監控軟體。主要因應不同的 # of process core 與 memory size,可以調整 php5-fpm 與 nginx 中兩個部分的設定。

php-fpm-with-nginx-htop.png

Nginx

在 /etc/nginx/nginx.conf 下約莫第二行有個 worker_processes 參數。

worker_processes 4;

根據運行機器的 cpu 核心數填入即可,可用 htop 或輸入以下 shell command 取得

cat /proc/cpuinfo| grep processor 

PHP5-FPM

位置:/etc/php5/fpm/pool.d/www.conf
在約莫 88 行有個 pm 變數可設定 Process Manager 要以什麼型態呈現,有 static, dynamic, ondemand。

  • static: 根據 pm.max_children 所設定的值,一直固定運行這個數量的 php-fpm child process 來處理 php script 的執行需求。如一般的 process 一樣,所耗用的 memory 會隨著運行而有一定程度的增加。
  • dynamic: 根據 pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers 這四個變數值來發揮作用。即一開始運作 php5-fpm 時就運行 pm.start_servers 數量的 child process,若沒事的 child process 就會被殺掉以維持在 pm.min_spare_servers ~ pm.max_spare_servers 的數量,因應需求最多不會產生超過 pm.max_children 的 child process 數量。通常,pm.start_servers, pm.min_spare_servers, pm.max_spare_servers 這三個參數值會是一樣。
  • ondemand: 根據 pm.max_children, pm.process_idle_timeout 這兩個參數來發揮作用。在這個模式下,一開始啟動 php5-fpm 時不會產生任何 child process,只有當有需求時才會去產生。若產生的 child process 超過 pm.process_idle_timeout 秒都沒事做的話就殺了它!

基本上 ondemand 與 dynamic 模式差不多的感覺,都是能有效 release 出 memory 供其他程式使用,但也因此在每次重新喚起新的 child process 時都會花額外的時間,不像 static 就是一直保持 child process 待命的狀態。

如何決定 pm.max_children

那至於 child process 數量要怎麼決定呢?通常一安裝 php5-fpm 時預設就是 static 搭配 pm.max_children = 32 的設定,最土法煉鋼的方式,就~運行網站個一兩天觀察一下每個 php-fpm child process 運作一段時間後需花多少 memory(如上方的 htop 截圖),即可以抓到每個 child process 所需的 memory 最大值。如此案例,就可以抓每個 child process 大概是 1% of total memory,即約 75 MB。保險起見就抓個 100 MB 來做計算,以這台機器約 8G 的 RAM,就可以設定 pm.max_children 為 70(記得保留 1~2 G 的 quota 給其他的程式哟),或大膽一點就設定 100 XDDD

最後

那~根據最近兩三個禮拜的測試,dynamic, ondemand 固然能一直保持 memory 一直有著一定量的 free memory 供其他程式使用,維持機器處於一個較高效能的狀態,但一旦有超大需求(request)衝進來,那它是不管你三七二十一,直接就衝上所設定最高的 # of child process,很容易導致 memory 超需,機器就會爆惹.....(最近兩個禮拜就因為這樣 G 掉兩次QQ)。因為大量需求一進來,當然你跟機器說我最大能做到那程度,它當然也就盡它所能發揮到極致,畢竟目前看起來是還沒能設定每個 php5-fpm child process 能使用的最大 memory 上限的功能,OS 似乎也沒看過有這樣的支援(窘~

所以已決定放棄追求高效能,把 pm 改回 static,追求伺服器穩定。畢竟伺服器穩穩乖乖的,我們才有好日子可以過~

BTW, 希望以後還能有這系列的續集

Reference