2015年10月24日 星期六

[Linux] 調校 Apache Web server 筆記 ab、systcl.conf、limits.conf、mpm_prefork.conf @ Ubuntu 14.04

最近又播空出來處理一下,之前機器在規劃時,幾乎都用系統預設的資源,接著就直接上 AWS Auto scaling,整體上進入 m3.medium 都還堪用,直到要上到 m3.large 規模時,開始發現當初設置的 Auto scaling rules 不是很適當。於是乎把 CPU 靈敏度下調,例如 CPU 只要衝到 15% 使用率就開新機器,反正大部分的時間都夠用 :P

而現在就老老實實先用 apache benchmark 試試! 首先操作環境都是 AWS EC2,先替機器上 Elastic IP 吧!因為 想測不同規格的機器,這時用個 Elastic IP 會方便一點,避免機器 IP 被換掉,此外,建議發動 ab 的機器規格要好於壓力測試的機器。

當發動 ab 測試的機器得到 apr_socket_recv: Connection reset by peer (104) 而被壓力測試的機器 dmesg 出現 TCP: TCP: Possible SYN flooding on port 80. Dropping request.  Check SNMP counters. 時,請調整壓力測試機器。

$ sudo vim /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_max_syn_backlog = 102400
net.ipv4.tcp_max_tw_buckets = 102400
$ sudo sysctl -p


其中 tcp_tw 代表 TCP Socket Time-Wait,而 syncookies 為 SYN Cookies 機制,而 syn_backlog 跟 tw_buckets 的數量,調大就是允許讓系統花多一點資源讓 client 等待而非直接 reject client。

而發動機器 file open 數量太小時,會出現 socket: Too many open files (24) 資訊,這時就先用 root 角色,並用 ulimit -n 8000 調高限制,若要保持其資源限制,就修改 /etc/security/limits.conf

$ sudo vim /etc/security/limits.conf
* soft nofile 12345
* hard nofile 23456

此例就是允許任何人開 12345 個檔案。

接著 ab 常用指令:

$ ab -c 300 -n 50000 http://ip/

記得若測試的 IP 位置在首頁,要有 "/" 結尾 :P 接著關注報表,例如 Requests per second 跟 Time per request 數字,若 requests per second 比 concurrent 數字還要大,那就調大 -c 的參數試試,去尋找一個合適的點即可。

另外,由於 Apache web server 預設採用 prefork MPM 模式,那邊也有些資源上限要調整:

$ sudo vim /etc/apache2/mods-enabled/mpm_prefork.conf
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxRequestWorkers: maximum number of server processes allowed to start
# MaxConnectionsPerChild: maximum number of requests a server process serves

<IfModule mpm_prefork_module>
ServerLimit 7500
StartServers 20
MinSpareServers 15
MaxSpareServers 50
MaxRequestWorkers 7500
MaxConnectionsPerChild 0
</IfModule>

$ sudo service apache2 reload


最後心得...在 AWS EC2 m3.large 的機器上,大多每秒就是處理一千五附近的連線,也就同時可處理 1500 連線。可以用 ab -k -c 1500 -n 5000000 測試看看。

2015年10月20日 星期二

透過 Bitbucket、Jenkins、Slack 打造持續發佈打屁等自動化架構

透過 Bitbucket 作為 git 版本控制的服務托管處,而 slack 則是工程師打屁好去處,而 Jenkins 則是打造一鍵發佈的便利介面。雖說連續動作也可以化簡成一隻 script,但能夠端出 Web UI 介面,還是大勝!

首先提一下 git 版本控制,透過 Bitbucket 服務,人多的話還是花一點小錢了!在 Bitbucket 可以建立群組概念,大概可粗略分成 Administrators、Developer、Deploy 三個個群組(若要細分則可以變成 iOS Developer、Android Developer、Web developer 或是甚至以專案為單位等),這邊設計讓所以有成員都進 Developer 並且 Developer group 預設對所有專案擁有 read only 權限。而埋了一個機器人在 deploy group 中,預設沒有任何權限(機器人不需進入 developer group)。當有專案要搭建自動發佈流程時,請專案擁有者或管理者,讓專案可供 Deploy Group 有 write 權限,這是為了 Jenkins 發佈新版時,能夠打個 tag 記錄狀態。而 Deploy group 裡的機器人,就只需添加個 ssh key 即可。

在 Jenkins Web UI:
  1. 建立作業 => 填寫作業名稱 => 建置 Free-Style 軟體專案 
  2. 設定 Slack Notifications => 進階設定 Team Domain、Integration Token 和 Project Channel => Test Connection
  3. 原始碼管理 => git => git@bitbucket.org:group/project.git => Credentials 搭配 Bitbucket SSH key => Branches to build 要指定 => Additional Behaviours => Advanced sub-modules behaviours => Recursively update submodules
  4. 建置環境 => Create a formatted version number => 設定 Environment Variable Name (VERSION) => Version Number Format String (1.0.0) 
  5. 建置 => 例如拉完程式碼後想要做的事,如 /path/project-build.sh project-name  $VERSION $BUILD_NUMBER $JOB_NAME 
  6. 建置後動作 => Git Publisher => Push Only If Build Succeeds => Tag to push (develop-$VERSION-$BUILD_NUMBER) => Target remote name (origin)
如此一來,開發者可以用 bitbucket 持續開發,並且用不同 branch 管理,如 develop branch、alpha branch、release branch 等,而 Jenkins 就建立三個任務,分別從上述 branch 取資料出來使用,而在 "建置" 跟 "建置後動作" 都可以對各個 branch 操作做細部的調整。

例如"建置"中的 /path/project-build.sh 的程式,就可以包含建立 RPM 、更新 repos 等行為,同時有環境變數 $VERSION $BUILD_NUMBER $JOB_NAME 拿來輔助。

以上就是將程式碼編譯打包的流程,若要再添加上 deploy 流程時,可以再額外建置一個 Jenkins 工作,裡頭只需填寫 slack 通知和建置項目,而建置項目就可以一隻 script 處理發佈的動作即可,而在相對應工作中,把剛剛的 deploy task 建立相依性即可。

如此一來,當 Jenkins 每一次建置時,各個階段的都丟訊息至 slack 指定的頻道,等同通知相關人員。若需要做類似 git hook 來達成自動建置時,可以使用 Jenkins "建置觸發程式" 裡的輪詢  SCM 項目,例如每 10 分鐘確認一次 bitbucket 專案狀況等,達成類似 git hook 行為。

2015年10月19日 星期一

有限資源

西本願寺

最近剛加入的強者夥伴即將離開,得知時心情五味雜陳,但說真的,打從強者加入時,便一直等待著這事件到來。站在朋友的立場仍十分建議他去新環境闖闖,但站在團隊剛建立的初期,內心又有種落寞感,不禁回憶起當年離開前老闆時,我堅定的想法配著老闆孤寂的背影,不也是一樣嗎?

隨著年紀的增長,同輩之間仍不斷進步著,越來越明瞭同輩之間扣除一起當 co-founder 外,是不太可能共事的,因為職場上的機會跟資源是有限的,有時不是為了競爭,而是順應潮流,總要有個人當頭,就像創業過程中,五五分帳的股份永遠是最爛的策略一樣。然而,大家都很強,又該怎樣相處?這真的是個大哉問,最佳解可能是任職不同團隊吧?再怎樣扁平化管理,總是有人被老闆愛戴有人被老闆操 XD

或許,這是老天安排的訓練,好好面對團隊夥伴離開的事件吧!這件事永遠都會發生的。如同每個 leader 總會抱怨人力不夠,而這件事打從一開始就永遠存在的。人生就是一直在有限的資源中做最佳的策略。

2015年10月18日 星期日

Bash 筆記 - 使用 s3fs、mysqldump、find 透過 s3 定期備份 MySQL 資料庫資料

由於資料庫恰好有 timestamp 這個數值,除設計完 incremental backup 方式後(Bash 筆記 - 使用時間區間備份 MySQL 資料表),而備份好的資料又感到麻煩,所以就往 s3 丟吧!而 s3 的丟法就用 s3fs 來執行。

流程:
  1. 執行 db incremental backup
  2. 使用 s3fs 掛載 s3 空間
  3. 確認 s3 是否已有資料,若沒有則複製過去
其中我把 db backup 的(tar.bz2)產物都有做一次 checksum (tar.bz2.md5),因此判斷是否已在 s3 上時,可以判斷 checksum file 即可:

mkdir -p /data/fuse-tmp/my-s3-bucket
mkdir -p /data/s3/my-s3-bucket
touch /data/s3/my-s3-bucket.password
s3fs my-s3-bucket /data/s3/my-s3-bucket -d -o use_cache=/data/fuse-tmp -o passwd_file=/data/s3/my-s3-bucket.password

find /data/db/ -name "*.bz2" -exec bash -c "test -e {}.md5 && test ! -e /data/s3/my-s3-bucket/\`basename {}\`.md5 && echo 'upload {} , {}.md5 ... ' && time cp {} {}.md5 /data/s3/smy-s3-bucket/ && echo 'done' " \;

sync;sync;sync

fusermount -u /data/s3/my-s3-bucket


其中,/data/db 是擺放一堆 db.sql.tar.bz2 跟 db.sql.tar.bz2.md5 的位置,而我讓備份過程中最後產出 db.sql.tar.bz2.md5 檔,因此先判斷 /data/db/db.sql.tar.bz2.md5 是否產生也代表備份流程是否跑完,接著才檢查 /data/s3/my-s3-bucket/db.sql.tar.bz2.md5 資料來決定是否要上傳到 s3 。

最後,s3 還可以開啟版本控制,這樣可以避免不小心蓋掉檔案的問題 :) 達成完整可自動化的備份方案

2015年10月16日 星期五

[OSX] 使用 ImageMagick convert 處理 SVG 轉 PNG @ Mac OS X 10.11

$ sudo port install ImageMagick
$ convert test.svg test.png


若需要指定尺寸:

$ convert -density 300 test.svg test.png

若需要指定背景:

$ convert -background transparent -density 300 test.svg test.png