讓程序員不再苦逼的四大神器

轉:【https://www.v2ex.com/t/202085】

做程序猿「媛」是一個苦逼的活,大週六地早起在技術羣裏招呼,看到沒有啥人響應,說了一句,「估計都沒有醒」,然後一位哥們拋過來,「在加班」 !

做 Web 開發更是一個苦逼的活,不像是做 iOS,搞定客戶端,基本上就萬事大吉了。做 Web 開發不僅僅是要做後端,前端也需要了解和熟悉!

做前後端通喫的 DevOps 全棧工程師絕對是最苦逼的活,不但需要做開發,而且還要了解運維、優化,不會運維的工程師絕對不是一個好架構師!

但所幸的事,一個優秀的工程師儘管很忙,儘管要熟悉前後端、系統、運營、優化,但是在他的工具箱裏,放着一大堆工具,讓這種生活變得不那麼苦逼。

這裏就介紹四個讓我們 DevOps 生活變得美好的神器。分別是 Xdebug、XHProf 、OneAPM 和 SocketLog。

Xdebug

作爲開發人員,睡得最踏實的事是對自己寫的代碼瞭如指掌,無論是從功能層面,還是性能層面。而做 Web PHP 開發,比較棘手的一件事情就是代碼的調試。作爲腳本語言,在遠程服務器端運行,客戶端生成的全是 HTML 代碼,一般認爲我們無法準確地調試運行的情況,更不要說單步調試、變量監控等事情了。其實這是有誤解的,有一個 PHP 擴展 Xdebug 能讓方便地讓我們調試遠程服務器上運行的代碼。

方法很簡單,從 Xdebug 下載最新版的源代碼。
wget 解壓:

tar –zxvf xdebug-2.3.3.tgz
cd xdebug-2.3.3
phpize
./configure –with-php-config=/usr/bin/php-config
make
make install

再增加相應的配置到 php.ini ,需要注意有兩點:

1. xdebug 是 zend_extension

2. 端口默認是 9000,和 php-fpm 的缺省端口衝突,所以這裏換用 9100

[xdebug]
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20121212/xdebug.so
xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9100

這樣就裝好了,就是如此簡單,下面我們可以開始使用了。以 ThinkPHP 應用開發做例子吧。ThinkPHP 典型的單入口應用,調用層次相對複雜。所以想要了解調用堆棧還是比較麻煩的。要想得到某一行的調用堆棧,可以使用 PHP 自帶的 debug_backtrace 函數可以獲得,但是不怎麼形象,返回來一個數組而已。而 Xdebug 就能讓這一切可視化起來。

配合 Xdebug 使用的是 Netbeans 自帶的調試工具。首先通過首選項修改了一下 PHP 調試的端口,從9000改成9100,其他不用動。注意在第一行停止是選上的,這將在 PHP 程序調試時,運行到第一行 PHP 代碼時停止,在 ThinkPHP 中,即入口文件 index.php 的第一行停止。

讓程序員不再苦逼的四大神器

在本例中,筆者做了一個租車管理系統的示例,項目名爲 zuches。將代碼部署在 http://localhost/zuches 能訪問的地方,索引文件是 index.php。

讓程序員不再苦逼的四大神器

由於 index.php 是入口文件,所以在 index.php 上點擊右鍵,選擇調試。

讓程序員不再苦逼的四大神器

然後 Netbeans 自動打開了如下地址,進入調試狀態 :http://localhost/zuches/index.php?XDEBUG_SESSION_START=netbeans-xdebug
同時運行位置指示停留到了 index.php 的第一行。如下:

讓程序員不再苦逼的四大神器

點擊繼續運行,由於在 IndexController.class.php 的 index 方法中加上了斷點,所以位置指示又停留在了相應的斷點處。

讓程序員不再苦逼的四大神器

這個時候,我們可以查看中斷時候的調用堆棧和變量了。通過堆棧可以方便地定位到各定位的類和相應方法。

讓程序員不再苦逼的四大神器

各種變量,無論是局部變量和實例屬性,無論是 cookie,還是提交數據,都能在變量表中看到,一目瞭然。

讓程序員不再苦逼的四大神器

總之,Xdebug 讓我們即使做的是服務器端頁面和 API 開發,也可以像桌面應用開發一樣,調試每一行代碼了。

Xdebug 除了使用來進行單步調試之外,還能收集請求中的執行日誌,記錄每一個函數的執行過程。這些日誌可以用 wincachegrind 等工具進行分析,看到函數的調用棧和所花的時間。這裏不再贅述,我們也不是很推薦,因爲 XHProf 在這塊要輕量級和強大的多,不用如此費勁地下載日誌,分析日誌。

XHProf

如前文所述,對於 PHP 中函數調用棧和性能分析,XHProf 將 Xdebug 開的先河繼承併發揚光大。XHProf 也是 PHP 擴展,不過不建議從 http://pecl.php.net/package/xhprof 上下載,版本已有近2年沒有更新了,最好從 https://github.com/phacility/xhprof 上下載。下載編譯配置和使用過程都很簡單。

配置只需要加上如下兩行:

[xhprof]
extension=/usr/lib/php/extensions/no-debug-non-zts-20121212/xhprof.so

然後將要相應的 XHProf 代碼配置到需要監控的頁面中,即可以獲得整個頁面的執行中,各函數的調用報表。XHProf 提供了示例,配置成功運行如下:

讓程序員不再苦逼的四大神器

如何看到上面圖中的效果呢?將 examplesxhprof_htmlxhprof_lib 三個目錄放到瀏覽器能訪問到的地方,比如 localhost 的主目錄內。修改 examples/sample.php 中的 <xhprof-ui-address> 換成 如:localhost/xhprof_html/。即可。

然後訪問 http://localhost/examples/sample.php 即可以得到輸出結果如下:

讓程序員不再苦逼的四大神器

從 examples/sample.php 中可以看到,對於頁面的監測分析,在頁面頂部使用 xhprof_enable 開始,而性能的分析的結束,則是在頁面底部使用 xhprof_disable 結束 。這樣每次監控,都需要增加一段代碼,所以爲了規範起見。對 XHProf 相關的操作進行了封裝。繼續採用上例 ThinkPHP 版租車系統的例子,看看如何集成 XHProf 分析。

首先將對 XHProf 的操作封裝成了一個類。

<?php
class XHProf
{

    private static $strNameSpace = "";
    public static function init($strNameSpace = "myhome")
    {
        if (!function_exists("xhprof_enable"))
        {
            return;
        }
        self::$strNameSpace = strval($strNameSpace);

        $param = XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY;

    $path = getcwd();
        require_once $path.'/../xhprof_lib/utils/xhprof_lib.php';
        require_once $path.'/../xhprof_lib/utils/xhprof_runs.php';
        xhprof_enable($param);

        register_shutdown_function("XHProf::genResult");
    }

    public static function genResult()
    {

        $profiler_namespace = self::$strNameSpace;
        $xhprof_data = xhprof_disable();
        $xhprof_runs = new XHProfRuns_Default();
        $run_id = $xhprof_runs->save_run($xhprof_data, $profiler_namespace);
        $profiler_url = sprintf('http://' . $_SERVER['HTTP_HOST'] . '/xhprof_html/index.php?run=%s&source=%s', $run_id, $profiler_namespace);
        echo '<p style="position:absolute; left:0; top:0; background:orange; padding:8px;">'
        . '<a href="' . $profiler_url . '" target="_blank">Profiler output</a></p>';
    }

}

在這個封裝的類中,首先檢測了 xhprof_enable 函數是否存在,這可以用於判斷是否成功安裝配置了 xhprof 擴展。其次設置了參數,特別值得一提的是使用函數 register_shutdown_function 來註冊一個操作,這個操作在頁面結束之前,會自動運行。

這樣,在分析頁面性能之時,只需要在 ThinkPHP 應用的 index.php 上加上兩行,即可以了。

比如:

require_once "xhprof.php";
XHProf::init("zuches");

運行後,得到如下效果:

讓程序員不再苦逼的四大神器

並且每一個頁面,都有這樣的輸出。點擊「Profiler output」即得到了報表。

讓程序員不再苦逼的四大神器

在本例中,可以看到最後的集成方法,運行時間超過了2 S,是值得關注並優化了。從報表中,可以首先看到各個方法或者函數的調用次數,運行時間,以及可以層層點進去看到父子層級的調用關係 。

需要注意的是,在線上,如上使用 XHProf 要慎重,即使打開,也要有限制條件地打開,比如當前用戶是某些調試開發者用戶時纔打開。否則,普通用戶看到這樣的輸出,則不明所以,給用戶帶來困惑,當然,我們也可以不輸出,而將數據直接存儲,在後臺系統中查看,這樣用戶就感受不到了。有一個工具,可以完全消除這些糾結。那就是 OneAPM,在第四部分我們再介紹。

SocketLog

作爲程序員,除了新功能開發之外,最常見的一個工作就是查錯,尤其是遠程用戶的查錯,還是一個很痛苦的過程。當前又加上了微信開發,API 開發等操作。對於微信內、API 由遠程用戶所調用的時候,情況多變,查錯也更加地麻煩。這個時候,我們的第三個神器登場了。那就是 SocketLog。

SocketLog 是國內知名 PHP 開發者羅飛的作品,羅飛是 ThinkPHP 的核心開發者,也是優才學院全棧工程師主力講師。現任三生社羣 CTO。SocketLog 的 github 地址爲:https://github.com/luofei614/SocketLog ,在項目的主頁上,詳細地介紹了用法和所用的技術。這裏簡單地彙總講解一下。

SocketLog 的使用,主要要分成三個步驟,第一步是安裝 Chrome 插件。可以從 github 下載的安裝包中去安裝,或者可以從 Chrome 應用商店下載。

第二步是需要啓動 Socket 服務,Socket 服務是 WebSocket 協議的,早期版本是 PHP 編寫的服務器,新的版本已經使用 Node.js 來實現了。啓動方法很簡單,進入解壓後的目錄。

執行 node server/index.js 即可。

安裝好插件之後,就在 Chrome 上看到如下圖標。灰色表示沒有連接上。

讓程序員不再苦逼的四大神器

同時啓動了服務器,做好設置,就會看到圖標變成藍色了。

讓程序員不再苦逼的四大神器

需要注意的是,儘管我們這裏監聽地址配置成了本地地址,其實也可以配置遠程地址。不過遠程地址的話記得打開服務器上的防火牆,因爲一般1229端口在防火牆中是關閉的。

SocketLog 的原理,是在服務器端,往 WebSocket 服務器上寫數據,作爲客戶端的 Chrome 插件,即能收到數據。所以不管是遠程 API 調用,還是網頁訪問,只要在程序中往這個 WebSocket 服務器寫了數據,只要監聽了這個 Websocket 服務的客戶端都能收到相應的調試日誌。

第三步是埋代碼。使用方法也很簡單。比如我們在上面的 ThinkPHP 的 index.php 加入兩行代碼。會看到如下輸出 。

讓程序員不再苦逼的四大神器

然後我們在其他終端上也訪問一下這臺機器的這個頁面地址,看看是否能得到輸出呢?開始沒有任何輸出效果。因爲缺省情況下是不記錄普通用戶所調用的 slog 的。

在 slog 之上的語句加上這一行,就有了。

slog(array('force_client_id'=>'test'),'set_config');

Test 這個插件的用戶,收到了所有的 slog 消息。如下圖所示:

讓程序員不再苦逼的四大神器

並且這種輸出 ,無論是別的用戶觸發,而還後臺服務程序,均可以輸出 。所以非常地方便,開發人員在自己的機器上就收集到了想要收集的用戶所觸發的調試信息。

然後爲了體現對 SQL 語句的監聽。我們在 ThinkPHP/Library/Think/Db/Driver.class.php 的第1139行加上 slog($str),然後再訪問頁面,就得到了如下輸出 ,可見實現了對 SQL 日誌的監控。

SocketLog 的功能看起來雖然簡單,但是卻非常有用、好用,是不可多得的開發神器。有關 SocketLog 的更多介紹和使用說明,建議現在就立刻下載,並且進入 github 主頁好好地研究吧!

OneAPM

從上面的使用來看,SocketLog 和 XHProf 都有兩個不足之處,一是需要埋代碼,二是隻是基於單獨一個頁面會話的。而 OneAPM 相對來講,就更強大了,可以理解爲雲端 SaaS 版的 XHProf 和更強大的 SocketLog。不過有着更爲強大的優勢。比如:

  1. OneAPM 的 PHP 探針,安裝完成之後,並不需要在代碼中埋入任何代碼。

  2. 在數據收集的過程中,不需要開發和運維的參與,探針全自動收集,並提交到遠程服務器。

  3. 由於數據累積,所以支持歷史報表,以及比 XHProf 和 SocketLog 更豐富的功能。

  4. PHP 只是 OneAPM 所支持的一種語言,它可以支持多種語言,HTML5、iOSAndroidJava.NETpythonNode.jsPHPruby等。

OneAPM 的安裝過程也比較簡單,不過由於是 SaaS 服務,所以得上官網註冊一個賬號。登錄了之後,在應用程序裏,點擊添加,再選中 PHP,就進入了安裝探針的說明。

讓程序員不再苦逼的四大神器
分爲如下幾步:

1. 獲取授權編號

OneAPM 授權憑證,用於配置和身份識別。

2. 下載 OneAPM PHP agent 安裝程序

3. 解壓 OneAPM PHP Agent

tar -xzf OneAPM_php_Agent_2.3.11.tar.gz

4. 安裝 OneAPM PHP Agent

  • 定位路徑至您的安裝包所在文件夾
cd oneapm-php5-linux-install-script
  • 執行安裝命令
sudo ./oneapm-install install

5. 輸入 License Key

請點擊步驟1中的「生成授權編號按鈕」成功安裝,界面如下:
讓程序員不再苦逼的四大神器

若出現以下信息,則代表安裝成功。

OneAPM is now installed on your system. Congratulations!

當頁面出現以下提示時,啓動 Daemon

And then start php-agent in /usr/bin/oneapm-daemon

運行以下指令來啓動 Daemon

sudo /usr/bin/oneapm-daemon

重啓 Apache 或你使用的 web 調度程序 「如 php-fpm 」

6. 靜候5分鐘,開啓 OneAPM 之旅

靜候5分鐘,等待應用程序向 OneAPM 發送應用程序性能數據,即可開始使用 OneAPM 應用性能管理。

OneAPM 收集的數據很豐富。將收集的響應時間數據,分爲四個大塊:

  • Web 事務,就是頁面業務邏輯本身

  • 數據庫,數據庫的連接和數據讀取

  • 錯誤統計,對所有類型的錯誤做了歸類統計

  • 外部服務,即外部 API 等的設備

以筆者的站點爲例,12小時的數據如下圖:

讓程序員不再苦逼的四大神器

從上面這個圖,我們看到響應時間,慢的達到了600 ms 以上,那是什麼導致的呢?我們可以分別查看:

讓程序員不再苦逼的四大神器

可見 Web 事務比較穩定,可以比較清楚地看到平均的響應時間在 50ms-75ms之間。

讓程序員不再苦逼的四大神器

數據庫響應時間也很短,在幾 ms 這個級別。而外部服務就明顯在幾百 ms 這個級別,還有的高達 600 ms 。

讓程序員不再苦逼的四大神器

不說別的,就通過這簡單的報表,從目前看,就可以定位到,想要做優化,從外部服務的響應時間上下手優化,帶來的效果是最大的。

下面我們再來看看三個細化一層的報表 ,在 Web 事務統計中,儘管平均數很低,但是也列出了響應時間最長的5個請求。如下:

讓程序員不再苦逼的四大神器

從上面的數據可以看出,響應時間最長的幾個,主要突出在 bind.php,這個是負責 QQ 登錄的請求,需要向騰訊請求數據。

而在數據庫一欄中,可以看到最慢的5個表格的情況。

讓程序員不再苦逼的四大神器

在外部的服務中,果不出所料,是對微博、微信、QQ 登錄、七牛上傳、支付寶通知等外部服務,所佔時間最長。如下圖所示。

讓程序員不再苦逼的四大神器

這只是普通的統計報表,對於具體的某一個慢的頁面,更有詳細的調用分析。

比如上面的 bind.php ,果真最慢的是從網絡上獲取數據。也就是說,第三方登錄時,從第三方網站取數據花了絕大部分時間。 去查看詳情,有兩個不足之處,一是需要埋代碼,二是隻是基於單獨一個頁面會話的。而 OneAPM 稱爲慢事務追蹤,拉到頁面的最底部就能看到。

讓程序員不再苦逼的四大神器

讓程序員不再苦逼的四大神器

在後臺報表中,我們同樣也能看到是哪些 SQL 語句慢。比如如下是 bind.php 中慢的 SQL 語句。

讓程序員不再苦逼的四大神器

更爲重要的是,還有所有錯誤信息的收集,也一目瞭然。

讓程序員不再苦逼的四大神器

所以無論從功能之強大,還是易用之方便,有兩個不足之處,一是需要埋代碼,二是隻是基於單獨一個頁面會話的。而 OneAPM 不愧是商業化的 SaaS 服務,比 XHProf 勝去了不少。在筆者的項目中,已經大量使用。並取得了好的效果。

以上四個項目,讓我們對自己所寫的代碼,更加成竹在胸,無論是執行過程還是調優着手了都有了充分的把握。特意對比,彙總整理的這四大神器,希望它們能改善每一位 PHP 開發者的生活,讓我們的 PHP 開發不再那麼地苦逼!

第 1 條附言  ·  2015-06-30 14:43:35 +08:00
因爲評論有問到關於安全性和性能的問題,所以統一回復下: 

OneAPM 從如下幾方面確保安全性: 

1.過濾 URL 中的敏感信息:通過配置關鍵字進行過濾,如 password、credit,對於需要過濾的內容可以自行增加關鍵字; 

2.過濾 SQL 語句中的參數:默認是用“ ? ” 號代替,如果定位問題需要可以打開此項配置即可; 

3.探針與 Server 端使用 https 加密傳輸數據:杜絕被抓包分析; 

4.提供審計模式:打開審計模式可以看到所有傳出數據; 

性能影響: 

簡單介紹一下 PHP 探針原理吧,通過插件方式完成數據採集,在 Transaction 相關過程進行埋點,過程的出入打時間戳,收集性能數據,沒有特別消耗 CPU 的邏輯,假設一個應用 Server 每分鐘處理 100w 併發,對 OneAPM 來說只是最終是某個 Transaction 的吞吐量( cpm )值爲100w,數據量也不會增加很多。數據採集過程中採用的是國際通用的採樣策略,在高負載的時候會降低採樣頻率,確保不會影響用戶的業務代碼的執行,因此探針不會佔用很多內存和CPU。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章