Skip to content

Zeroplex 生活隨筆

軟體開發和生活瑣事

小 縮小字型大小。 中 重設字型大小。 大 放大字型大小。

標籤: PHP

Apache / Nginx 與 PHP 各種搭配方式的效能測試

Posted on 2017 年 8 月 2 日2021 年 3 月 12 日 By 日落 在〈Apache / Nginx 與 PHP 各種搭配方式的效能測試〉中尚無留言

以 PHP 為主的 HTTP server 有很多種架設方式,最傳統的大概就是 Apache + mod_php 來執行 PHP scripts。隨著技術一直在翻新,後來也有了 Nginx + php-fpm 的搭配模式出現,甚至連 PHP 在 5.4.0 都推出了 built-in server。

因公司需要,就順手測試了以下幾種搭配:
  • Apache mpm-prefork + mod_php
  • Apache mpm-worker using mod_proxy + php-fpm
  • Apache mpm-worker using mod_proxy + php-fpm (by unix socket)
  • Nginx + php-fpm
  • Nginx + php-fpm (using unix socket)
  • PHP build-in server
在開始看壓力測試結果之前,先來說一下測試環境:
  • 所有的 HTTP server 除了以上搭配方式之外,其他都使用預設值 (像是不開啟 gzip 壓縮等)
  • 另外壓力測試的 PHP script 內容也很簡單,僅有「phpinfo();」一行
  • 1 core CPU
  • 4 GB RAM
  • 使用 ab (Apache Bench) 做測試
  • ab 中每個 concurrency 固定會發出 1000 個 HTTP request,如 concurrency = 1 時僅有 1000 個 request,concurrency = 100 時,則送出 1000 x 100 個 request。
  • 每次 ab 跑完一次壓力測試,均重新啟動 HTTP server 與 PHP server,以防止使用到 cache。
先簡單做個結論,詳細的壓力測試結果再請大家自行過目:
  • concurrency = 1 時,沒有壓力測試會出現的情況,不過可以把 response time 和伺服器的 CPU、記憶體使用量當作一個基準值作為參考。
  • Apache mpm-prefork 搭配 mod_php 的記憶體使用量最大,畢竟要 fork 一個 Apache instance 出來就要把 Apache 的 module 也 initialize 出來。小型伺服器不推薦這個方案。
  • php-fpm 即使設定「pm.max_children = 50」,也可以輕鬆負荷超過 50 個 concurrency。比較微妙的是從 htop 看不出 php-fpm 有使用 thread 來同時處理 request。
  • php-fpm listen on Unix socket 的效率比 listen TCP (127.0.0.1:9000) 的效率還要高一些,但是在高負荷的情況下會變得很不穩定,猜測和 OS 的 socket 實作、設定有關連。
  • PHP built-in server 遇到在高負載的情況下表現的不錯,唯獨 log 給的資訊太少,不方便做分析。但也可考慮透過 Nginx proxy 給 PHP built-in server,讓 Nginx 來處理 log。
最後做個廣告,Hackmd 真不錯用,筆記寫完最後還以轉換成 HTML 下載,有夠方便的啦!
Tags:Apache, Linux, Nginx, PHP, 資訊學習

在 PHP 判斷參數為 anonymous function 的方法

Posted on 2017 年 8 月 1 日2021 年 3 月 12 日 By 日落 在〈在 PHP 判斷參數為 anonymous function 的方法〉中尚無留言

在追各個 framework 的一些元件結構,anonymous function 已經被大量使用在不同的用途上了。

如果 function 要判斷外部傳進來的參數,是否為 anonymous function,有幾個作法。

一個是判斷是否可以被呼叫:

is_callable($param)

另外,由於所有的 anonymous function 其實屬於一個 PHP Closure 類別,所以也可以用下面這個方法做判斷 (且判斷結果還比較準確):

$param instanceof Closure
Tags:PHP, 資訊學習

Nginx URL rewrite for REST API in subfolder

Posted on 2017 年 7 月 14 日2021 年 3 月 12 日 By 日落 在〈Nginx URL rewrite for REST API in subfolder〉中尚無留言

一般來說,要讓 Nginx 遇到 PHP 程式時,只要按照以下寫法就可以將 request 轉接給 php-fpm 處理:

server {
    location / {
        try_files $uri $uri/index.html =404;
    }

    location ~ .php* {
        root /home/www/data;

        include        fastcgi_params;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }
}

假設 project 在 document root (如上面的就是 /home/www/data),設定方式其實不難,網路到處都可以找的到。像是 Laravel 可以參考 pretty URL 的設定方式,把 index.php 隱藏起來:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

上面這個設定,可以讓 request 從「http://my.site/user/1」,被改寫為「http://my.site/index.php/user/1」,這個時候 index.php 就可以從 $_SERVER 的參數來判斷到底要走哪個 route。

但假設寫的專案沒有一個 domain name、沒辦法做 virtual host,可以讓專案根目錄當作 document root,且新的 PHP framework 都會把 index.php 放在 /public 目錄下來避免安全問題,這樣的 URL rewrite 就會出問題。

例如今天的 request 是「http://my.site/project/user/1」,在經過上面的 route 以後會被轉成「http://my.site/index.php/project/user/1」,而實際上我們需要的是「http://my.site/project/index.php/user/1」才能讓專案正確運作。

這時需要另外建立 route 規則。先把 http://my.site/project 對應到的正確檔案路徑設定好:

location ^~ /project {
    # define script real path
    alias /home/www/data/project/public;

    try_files $uri $uri/ /project/public/index.php$uri;
}

到這邊算是設定完成一半,暫停來看一下目前 routing 的情況。請求「http://my.site/project/user/1」會被轉換為「http://my.site/project/public/index.php/project/user/1」。index.php 後半部的參數差了一點點,把「project/」片段拿掉就完成了。

這時我們再新增一條規則,使用 REGEX 來處理後面這段參數:

location @project-rule {
    # 若 URI 起始為 /project/
    # 把後面的參數抓出來,放在 /project/public/index.php/ 後方 
    rewrite ^/project/(.*)$ /project/public/index.php/$1 last;
}

調整後,完整的 Nginx URL rewrite 規則會長這樣:

location ^~ /project {
    alias /home/www/data/project/public;

    # 一般規則無法正確找到路徑
    # 就使用 @project-rule 規則來做查詢
    try_files $uri $uri/ @project-rule;
}

location @project-rule {
    rewrite ^/project/(.*)$ /project/public/index.php/$1 last;
}

Nginx 的 rewrite rule 實在很難 debug,這段是自己花了數小時嘗試錯誤並觀察 $_SERVER 參數變化才找到規律的,希望多少對大家有一點幫助。

Tags:Nginx, PHP, 分享, 資訊學習

Phalcon PHP framework 的 URL rewrite 方法

Posted on 2017 年 6 月 29 日2021 年 3 月 12 日 By 日落 在〈Phalcon PHP framework 的 URL rewrite 方法〉中尚無留言

幾個比較常見的 PHP framework 像是 Silex、Slim、FuelPHP 和 Laravel,都是將 resource path 直接放在 index.php 後方。例如網址為「/my.site/user/10」則會被改寫為「/my.site/index.php/user/10」,所以在測試環境下,如果不想設定 URL rewrite 可以直接把 resource path 手動放在 index.php 後方。

今天研究 Phalcon 的 routing 很久,不管怎麼設定就是沒有 match 到 controller,而且還沒有任何錯誤訊息。把整個文件都翻遍以後,才發現 .htaccess 有個不一樣的地方:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^((?s).*)$ index.php?_url=/$1 [QSA,L]
</IfModule>

Phalcon 的 rewrite 行為和上述的不一樣,resource path 會轉到「_url」這個參數上面,所以若是沒有動到「_url」這個參數,router 就視為要開啟首頁,不管 index.php 後面接什麼都不會改變行為 ….。

可惡,八小時就這樣飛了 …..

Tags:PHP, 生活雜記

prestissimo for composer

Posted on 2017 年 5 月 12 日2021 年 3 月 12 日 By 日落 在〈prestissimo for composer〉中尚無留言

composer 是一個解決 dependency hell 的好工具,但令人詬病的是跑得實在有點慢,特別是 composer update 的時候,搞不好就一直 update 到下班了 … Orz

所以這裡介紹一個工具:prestissimo。當有多個 packages 需要下載時,prestissimo 會自動跑 multi-process 來下載 depends:

composer install -vvv
.....
Dependency resolution completed in 0.093 seconds
    Prefetch start: total: 27
    1/27:    https://codeload.github.com/sebastianbergmann/php-file-iterator/legacy.zip/3cc8f69b3028d0f96a9078e6295d86e9bf019be5
    2/27:    https://codeload.github.com/sebastianbergmann/code-unit-reverse-lookup/legacy.zip/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18
    3/27:    https://codeload.github.com/sebastianbergmann/php-timer/legacy.zip/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f
    4/27:    https://codeload.github.com/sebastianbergmann/php-text-template/legacy.zip/31f8b717e51d9a2afca6c9f046f5d69fc27c8686
    5/27:    https://codeload.github.com/sebastianbergmann/php-token-stream/legacy.zip/e03f8f67534427a787e21a385a67ec3ca6978ea7
    6/27:    https://codeload.github.com/myclabs/DeepCopy/legacy.zip/8e6e04167378abf1ddb4d3522d8755c5fd90d102
    7/27:    https://codeload.github.com/sebastianbergmann/diff/legacy.zip/13edfd8706462032c2f52b4b862974dd46b71c9e
    8/27:    https://codeload.github.com/sebastianbergmann/version/legacy.zip/99732be0ddb3361e16ad77b68ba41efc8e979019
    9/27:    https://codeload.github.com/sebastianbergmann/object-enumerator/legacy.zip/1311872ac850040a79c3c058bea3e22d0f09cbb7
    10/27:    https://codeload.github.com/phpDocumentor/ReflectionDocBlock/legacy.zip/8331b5efe816ae05461b7ca1e721c01b46bafb3e
    11/27:    https://codeload.github.com/sebastianbergmann/global-state/legacy.zip/bc37d50fea7d017d3d340f230811c9f1d7280af4
    12/27:    https://codeload.github.com/sebastianbergmann/comparator/legacy.zip/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be
    13/27:    https://codeload.github.com/phpspec/prophecy/legacy.zip/93d39f1f7f9326d746203c7c056f300f7f126073
    14/27:    https://codeload.github.com/mockery/mockery/legacy.zip/6fdb61243844dc924071d3404bb23994ea0b6856
    15/27:    https://codeload.github.com/symfony/yaml/legacy.zip/acec26fcf7f3031e094e910b94b002fa53d4e4d6
    16/27:    https://codeload.github.com/sebastianbergmann/php-code-coverage/legacy.zip/ef7b2f56815df854e66ceaee8ebe9393ae36a40d
    17/27:    https://codeload.github.com/sebastianbergmann/phpunit/legacy.zip/69c4f49ff376af2692bad9cebd883d17ebaa98a1
    Finished: success:17, skipped:10, failure:0, total: 27

我的 project 只有 27 個 packages 所以效果沒有很顯著,但若超過 50 個 packages 要抓時,相信你會非常有感覺。

安豬方法很簡單,把他裝成 global 的 composer package:

$ composer global require hirak/prestissimo

安裝完成以後 prestissimo 便會自動開始運作。

若覺得預設值不夠你用,可以到設定檔裡面自己調整需要的參數 (以下應該不是預設值,被我改過一次了):

$ cat ~/.composer/config.json
{
  "config": {
    "prestissimo": {
      "maxConnections": 10,
      "minConnections": 3,
      "pipeline": false,
      "verbose": false,
      "insecure": true,
      "cainfo": "/absolute/path/to/cacert.pem",
      "userAgent": "",
      "privatePackages": []
    }
  }
}
Tags:PHP

文章分頁

上一頁 1 ... 15 16 17 ... 27 下一頁

其他

關於我  (About me)

  文章 RSS Feed

  留言 RSS Feed

Apache AWS Bash C/C++ Docker FreeBSD GCP Git Google Java JavaScript Laravel Linux Microsoft MSSQL MySQL Nginx PHP PHPUnit PostgreSQL Python Qt Raspberry Pi Ubuntu Unix Vim Web Windows XD 作業系統 分享 好站推薦 專題 攝影 新奇搞笑 新聞 旅遊 生活雜記 程式設計 網路架站 網頁設計 資訊學習 資訊安全 遊戲 音樂


創用 CC 授權條款
本著作係採用創用 CC 姓名標示-相同方式分享 4.0 國際 授權條款授權.