安裝 Let’s Encrypt 的憑證與支援 HTTP/2

昨天花了一個多小時的時間,申請了 Let’s Encrypt 的憑證並更新上去,並且升級到 Apache 2.4.17 來安裝 HTTP/2 Module。

Let’s Encrypt 使用的 ACME Client 程式,目前有實驗性的支援 FreeBSD,基本上按照信件中的說明安裝即可。如果是 FreeBSD 9.x 的話,需要按照這個 GitHub Issue 的方式,自行編譯 trunk 版本的 pyca/cryptography,即可完成 ACME Client 的安裝。

安裝完成後,可以指定 webroot 當作認證檔案存放的位置,來給 Let’s Encrypt 驗證這個網域確實是申請人所有:


./letsencrypt-auto --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path /home/data/websites/jnlin.org/webroot certonly

簽好的憑證會放在 /etc/letsencrypt/ 裡面,效期 90 天。官方建議每 60 天 renew 一次。我自己打算先手動 renew 一次,沒問題的話就丟到 cron 裡面,兩個月自動 renew 一次。

安裝 Apache 2.4 + HTTP/2 Module 就沒什麼特別的,直接 ports 安裝,結束之後,把憑證設定上去,即可打開 HTTP/2 的功能。反倒是解決 WordPress 的 mixed content 問題花了比較多時間 XD

Google Tag Manager 簡介 (3) – 自訂代碼

雖然 Google Tag Manager 有支援很多代碼,但沒有支援的代碼,一樣可以用自訂的方式設定上去。

自訂代碼分為兩種:HTML 與圖片代碼。當觸發條件被滿足時,指定的 HTML 或圖片代碼會被載入到頁面上。

在代碼中,可以用 {{ 變數名稱 }} 來帶入變數的值。
設定好之後,使用的方法跟套用 Google Analytics 一樣。

如果要利用 Google Tag Manager 來套用 Mixpanel 追蹤的話,可以參考這篇 Mixpanel 分享的說明

Google Tag Manager 簡介 (2) – 建立變數與自訂事件

上一篇文章中,我們建立了簡單的事件。但除了 PV 之外,我們還要追蹤網站上元素的點擊,或是其他特殊的事件。Google Tag Manager 已經有內建一些變數,可以指定條件,讓我們不需要寫程式就能追蹤部份的事件。

我們必須到「變數」這個 Tab 去啟用這些內建的變數。

目前支援的變數列表如下:

  • Page URL
    • Page Hostname
    • Page Path
    • Referrer
  • 公用程式
    • Event
    • Container ID
    • Container Version
    • Random Number
    • HTML ID
  • 錯誤
    • Error Message
    • Error URL
    • Error Line
    • Debug Mode
  • 點擊
    • Click Element
    • Click Classes
    • Click ID
    • Click Target
    • Click URL
    • Click Text
  • 表單
    • Form Element
    • Form Classes
    • Form ID
    • Form Target
    • Form URL
    • Form Text
  • 歷史紀錄
    • New History Fragment
    • Old History Fragment
    • New History State
    • Old History State
    • History Source

以下我們以「當使用者點擊頁面上 id 為 “to-be-clicked” 的物件」為例,建立一個事件:

1. 首先到「變數」,啟用「Click ID」這個變數。

2. 新增一個「觸發條件」,事件類型為「點擊」,觸發條件為「所有元素」,啟動時機為「部分點擊」。接著在啟動時機內設定條件為「Click ID 等於 “to-be-clicked”」。

3. 新增一個「代碼」,指定該「觸發條件」要發出的 Event 內容與要記錄到的 Google Analytics ID。

如果我們想設定的變數不在預設列表中,也可以用程式自訂一個變數。作法如下:

1. 新增一個「使用者定義的變數」,類型選擇「自訂 javascript」。

2. 輸入一個 javascript 函式,傳回值為變數值。例如:

function () {return $('body').data('state'); }

表示傳回 <body> 的 state 這個 data attribute。

另外,我們也可以在程式裡面觸發 Tag Manager 的自訂事件。首先先建立一個觸發條件,選擇「自訂事件」:

接著在程式內觸發此事件:

dataLayer.push({"event": "custom-event"});

Google Tag Manager 簡介 (1) – 建立事件

為了收集使用者資料與行為,現代的 Web App 或 Mobile App 都會埋很多 Tracking Code,例如 Google AnalyticsMixpanel 或是 Flurry 之類的。當埋的 Tracking Code 或需要追蹤的事件開始變多的時候,管理就會變的越來越複雜。另外,隨著分工越來越細,工程師們會常常接收到來自產品、數據或營運部門的資料紀錄需求。當資料需求越來愈多的時候,紀錄事件這件事情就變得很瑣碎。尤其,面對的是 Mobile App 時,由於每次要收集新的紀錄時,就必須將 App 重新送審,比起 Web App 來說會花費更多時間。

Google Tag Manager 提供一個「簡單滿足紀錄需求」的介面,讓紀錄事件這件事變得不一定要工程師寫程式來達成。不過需要對寫程式邏輯有一定的熟悉度,對於一般「企劃人員」可能還是有些門檻在。

在 Web 使用 Google Tag Manager 的方式很簡單,直接申請之後,會給你一串 HTML:

接著要到 Google Tag Manager 的頁面中建立要記錄到的服務。在 Google Tag Manager 介面中選擇「新增代碼」,可看到除了 Google Analytics 以外,還有以下的 Tracking Code 可以選擇:

設定完並存檔之後,我們就有一個代碼用來紀錄 Page View 了。接著在「觸發條件」這裡,設定想要追蹤的事件類型:

例如,建立一個「計時器」觸發條件,當網頁載入後超過 1 秒鐘,送出 timer1s 事件:

然後回到「代碼」這裡,再建立一個 GA 代碼,但這次「追蹤類型」要選擇「事件」,並且將剛剛建立的觸發條件設定為「啟動時機」:

這樣我們就順利建立了一個事件。最後,要記得要按下右上角的「發布」,剛剛設定的條件才會被佈署到正式的平台上,事件也才會被記錄到 Google Analytics 中:

下一篇文章,將會介紹「自訂事件」與「變數」的設定方式。

避免 PHP Imagick 把記憶體吃完…

PHP 的 Imagick 有 memory leak 的情形,當用 PHP-CGI 跑動態縮圖服務的時候,這個問題更加的嚴重。查了一下資料,可以設定參數限制使用的記憶體大小:


// set pixel cache max size to 256MB
IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 256 * 1024 * 1024);
// maximum amount of memory map to allocate for the pixel cache
IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 256 * 1024 * 1024);

單位是 Bytes。如果進行圖片處理時,所需的記憶體超過指定值時,會在 /tmp 寫入暫存檔案。可以使用 MAGICK_TMPDIR 這個環境變數來指定暫存目錄:


putenv('MAGICK_TMPDIR=/tmp/imagick');

Google Cloud Platform 在台灣設點

新聞稿:Google Cloud Platform expands to Asia Pacific

比較不舒服的是 Google Compute Engine (Google 的虛擬主機) 必須要裝 Google 提供的 SDK 才能連進去,門檻比較高。在 Windows 系統下需要安裝 cygwin 與 python 才能使用。

連進去之後速度還不錯,畢竟在島內還是有差。

                                                                   My traceroute  [v0.85]
aqua (0.0.0.0)                                                                                                                     Tue Apr 15 22:43:50 2014
Keys:  Help   Display mode   Restart statistics   Order of fields   quit
                                                                                                                   Packets               Pings
 Host                                                                                                            Loss%   Snt   Last   Avg  Best  Wrst StDev
 1. 10.1.1.251                                                                                                    0.0%    37    0.2   0.2   0.1   0.5   0.0
 2. 60-199-247-252.static.pixnet.tw                                                                               0.0%    37    0.4   3.3   0.3  36.4   7.6
 3. 60-199-236-149.static.tfn.net.tw                                                                              0.0%    37    0.9   0.6   0.4   3.9   0.6
 4. 60-199-255-4.static.tfn.net.tw                                                                                0.0%    37    0.5   1.8   0.4  45.5   7.4
 5. 60-199-20-161.static.tfn.net.tw                                                                               0.0%    37    0.6   1.8   0.4  47.2   7.7
 6. 60-199-3-190.static.tfn.net.tw                                                                                0.0%    37    1.0   2.0   1.0  27.2   4.4
 7. 60-199-23-42.static.tfn.net.tw                                                                                0.0%    37    1.6   3.4   1.1  14.5   3.7
 8. 72.14.212.145                                                                                                 0.0%    37    1.2   5.9   1.2  44.6   8.8
 9. 209.85.243.26                                                                                                 0.0%    37    1.9   3.0   1.3  29.2   5.1
10. 209.85.250.101                                                                                                0.0%    37    3.0   3.1   2.8   5.8   0.7
11. ???
12. 172.178.167.107.bc.googleusercontent.com                                                                      0.0%    36    6.6   6.7   6.6   7.4   0.0

MySQL 的 Thread Pool (Percona 版本) 實測

MySQL Thread Pool 的介紹可以參考 Percona 的文章:,以及 DK 的介紹:MySQL 上的 Thread Pool…

一言以蔽之:資源使用量有減少,但看不出明顯的效能改善,可能是負載還不夠大。

MySQL Thread 數量(開啟 Thread Pool 前):

MySQL Thread 數量(開啟 Thread Pool 後):

System Thread 數量(開啟 Thread Pool 前):

System Thread 數量(開啟 Thread Pool 後):

可以看到在同樣約 2000 個 MySQL Thread 的情況下,開啟 Thread Pool 的 System Thread 數量只有約 200 個;開啟前約需要 3000 個 Thread。兩張圖是使用配備完全相同的兩台機器測試的。

Galera 3.x 的 Replication Relaying

Galera 3.x 為了多機房間的 Replication,設計了 gmcast.segment 這個參數。前陣子 Percona 的人出來介紹了這個參數背後的機制:Automatic replication relaying in Galera 3.x (available with PXC 5.6)。大致摘錄如下:

  1. 同一個機房內資料庫的 gmcast.segment 參數要設為相同。
  2. 機房與機房之間的 Replication 會自動找一個 node 進行 Relay,以降低 Replication 需要的頻寬。

    Image from: Automatic replication relaying in Galera 3.x (available with PXC 5.6)

如果沒有設定 gmcast.segment 參數的話,同樣是三個 Node,會耗用兩倍的頻寬:

Image from: Automatic replication relaying in Galera 3.x (available with PXC 5.6)

原文中另外有對作了 segment 與不作 segment 的 commit latency 進行比較,結果作了 segment 的 commit latency 並沒有比較高。如果有跨機房需求,應該要設定 gmcast.segment。

MySQL 5.6 的 Index Condition Pushdown

MySQL 5.6 以前的 Multi-column Index,當位於 index 中間的 column(如下例的 j)需要進行 range query 的時候,只能利用到部分的 index,需要另外讀取資料列的內容來進行判斷。舉例來說,如果有一個 Table 結構是這樣:

CREATE TABLE mytable (
id int not null auto_increment primary key,
i int(11) NOT NULL,
j int(11) NOT NULL,
k int(11) NOT NULL,
val char(10) NOT NULL,
KEY ijk (i,j,k)
) ENGINE=InnoDB;

在 MySQL 5.6 之前,SQL Query 「SELECT sum(length(val)) FROM T WHERE i=1 AND j<100 AND k=100」 會把所有 i=1 的資料列拉出來,逐一比較 j 與 k 的值。MySQL 5.6 的 Index Condition Pushdown (ICP) 功能,把這個動作改為比較 Index tuple 而非資料列內容,可避免拉出整個資料列,降低磁碟 IO(因為資料列通常比 Index 大)。

詳細的說明可以看 MySQL 的官方文件:Index Condition Pushdown Optimization 與 Percona 的測試:Multiple column index vs multiple indexes with MySQL 5.6