顯示具有 apache 標籤的文章。 顯示所有文章
顯示具有 apache 標籤的文章。 顯示所有文章

2016年3月4日 星期五

設定 Nginx 透過 proxy_pass 存取 Apache web server + SVN + DAV 服務 @ Ubuntu 14.04

這個故事是這樣的,當所有的 server deploy 都用預設用 nginx 後,有個成員跳出來說要用 SVN over HTTP 服務時,就發現必須架設 Apache Web server ,因為 SVN over HTTP 的相關模組就只有 Apache Web server 才有,所以就變成此況的窘境了。

總之,架設 Apache web server 很容易,而安裝 mod_dav_svn 也差不多:

$ sudo apt-get install subversion libapache2-mod-svn apache2
$ sudo vim /etc/apache2/ports.conf
從 Listen 80 改成 Listen 8000,避開跟 Nginx 預設 80 port 衝到
$ sudo vim /etc/apache2/sites-available/000-default.conf
從 <VirtualHost *:80> 改成 <VirtualHost *:8000>
$ sudo a2enmod dav_svn authz_svn
$ sudo vim /etc/apache2/conf-available/svn.conf
<Location /svn>
        DAV svn
        SVNParentPath /path/svn
        AuthzSVNAccessFile /path/svn_access
        AuthType Basic
        AuthName "Web svn"
        AuthUserFile /path/svn_auth
        Require valid-user
</Location>
$ sudo service apache2 restart


接著設定 Nginx:

location /svn/ {
proxy_pass http://127.0.0.1:8000/svn/;
}

# 更新:假設 svn repo 裡有 .ht 開頭的檔案,可能會被 nginx 條件擋下
location ~ /svn/.*\.ht {
proxy_pass http://127.0.0.1:8000/;
}


如此一來即可搞定。

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月6日 星期二

[PHP] 處理 PHP CodeIgniter 與 apache web server、nginx 的 Rewrite Rules

之前比較常用 Apache Web server ,在使用 PHP CodeIngiter 時,常常設定 Rewrite Rules 時,需要做一些手腳,例如:http://hostname/ci 想要瀏覽到 PHP CodeIgniter Project,而 ci 這個並非實體目錄,且 PHP CI Project 並非擺在 DocumentRoot 裡,這時就有很多環境變數需處理。

由於要符合 PHP CodeIgniter 的 routing rules,必須把 /ci 這個 path 給去掉,在 Apache Web server 透過 RewriteBase 處理,而 Nginx 又更麻煩一點,需處理 fastcgi_param REQUEST_URI 跟 fastcgi_param SCRIPT_FILENAME 資訊。

Apache 的設定:

Alias /ci /data/ci-project
<Directory /data/ci-project>
       Options FollowSymLinks
       DirectoryIndex index.php
       AllowOverride None

       Require all granted
       <IfModule mod_rewrite.c>
               RewriteEngine On
               RewriteBase /ci

               RewriteCond %{REQUEST_URI} ^system.*
               RewriteRule ^(.*)$ /index.php?/$1 [L]
 
               RewriteCond %{REQUEST_URI} ^application.*
               RewriteRule ^(.*)$ /index.php?/$1 [L]

               RewriteCond %{REQUEST_FILENAME} !-f
               RewriteCond %{REQUEST_FILENAME} !-d
               RewriteRule ^(.*)$ index.php?/$1 [L]
       </IfModule>
</Directory>


Nginx 設定:

        set $request_prefix '/ci/';
        set $ci_sys_dir '/opt/actions-channel-api/';

        location /ci/ {
                alias $ci_sys_dir;
                index  index.php index.html index.htm;

                try_files $uri $uri/ /ci/index.php?$query_string;
        }
        location ~* \.php$ {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_split_path_info ^(.+\.php)(.*)$;
                include fastcgi_params;

                set $target_request_uri $request_uri;
                if ($target_request_uri ~ ^/ci/(.*)$ ) {
                        set $target_request_uri /$1;
                }
                fastcgi_param REQUEST_URI $target_request_uri;

                set $target_fastcgi_script_name $fastcgi_script_name;
                if ($target_fastcgi_script_name ~ ^/ci/(.*)$ ) {
                        set $target_fastcgi_script_name $1;
                }
                fastcgi_param SCRIPT_FILENAME $ci_sys_dir$target_fastcgi_script_name;
        }


其他 Nginx 筆記:

  • alias 的數值記得要補上最後的 "/" ;alias 跟 root 的最大差別是 alias 的位置不需要在 document root  裡頭
  • 在 try_files 流程中,一旦符合條件後,就不會再執行該 nginx location 底部項目,因此還是把 php handler 拉到最外層,而不要全部都寫在 location /ci/ 此區塊裡頭
  • nginx 可定義很多環境變數,若想要看它就寫到 log 即可:
    • http {
          log_format proxy ' "$request"  "$status"  "$http_referer"  "$http_user_agent"  $request_time  $upstream_response_time "$ci_sys_dir" "$target_fastcgi_script_name"  "$target_request_uri"  '
      }

2015年5月14日 星期四

AWS 筆記 - 關於 Amazon EC2、Elastic Load Balancer (ELB)、Auto Scaling 與 CPU loading 過低問題 @ Ubuntu 14.04, Apache 2.4

使用 ELB + Auto Scaling 好一陣子了,最近因為服務量變大導致 Web Server 變多,然而,在部署程式方面就累了許多,因此朝 Scaling up 來進行一下,限縮機器數量並提升機器規格。

在這個過程中,從 m3.medium 改到 m3.large 或 m3.xlarge 等,卻發現越高級的機器,其 CPU Loading 衝不上去,並且限縮機器後導致服務極為不穩,連 Health check 也發現。但明明機器都不忙啊?!

接著因為非常忙,拖了兩個禮拜才正視這個問題。追了許多後,發現...只是 Apache Multi-Processing Module (MPM) 設定未同步拉高 XD 好蠢的一件事啊。此外,由於服務眾多,尚未有空最佳化,就先繼續用 prefork 架構了。

$ apache2 -v
Server version: Apache/2.4.7 (Ubuntu)
Server built:   Mar 10 2015 13:05:59
$ sudo vim /etc/apache2/mods-enabled/mpm_prefork.conf
<IfModule mpm_prefork_module>
        ServerLimit                7500 # 預設才 256
        StartServers               20
        MinSpareServers           15
        MaxSpareServers            50
        MaxRequestWorkers          7500 # 預設才 256
        MaxConnectionsPerChild     0
</IfModule>


總之,ServerLimit 跟 MaxRequestWorkers 就看當下的機器資訊,例如記憶體等等。

透過 Web server 執行的環境調整,機器的負載度自然可以提升,接著 Auto Scaling 的機制就可用啦!原先在 m3.medium 的機器是單核,而在 m3.large 開始就是多核心了!效能就能更往上衝囉。很妙地用系統預設的 prefork.conf 在 m3.medium 還混的不錯 :P 包含 CPU 會依照 requests 量變化,不像同樣的設定檔搬到多核心後就失效了,CPU 衝不起來,導致 Auto Scaling 也失效!

整體上,這次碰到 service 不穩的主因:

total requests 一直保持一個數量,而原先開 m3.medium x N ,想說機器提升成 m3.large 就把數量調整成一半,結果 web server 數量降低,再加上 prefork.conf 的設定,導致能服務的 requests 量也降低!而 Health check 無法正常被驗證,接著 AWS Scaling 會判斷機器出事要下線,甚至 requests 不導過去,頻頻出現:

503 Service Unavailable: Back-end server is at capacity

如今終於解掉了 :P Health check requests 也能被服務到,機器自然就不會被判斷成有問題,自然就解掉 503 Service Unavailable 現象。

最後,如果要追蹤網路流量,可以試試 nload 這個指令,看整體流量還滿方便的。

2015年4月8日 星期三

PHP CodeIgniter - 透過 Apache RewriteRule 限制 CGI 功能

基於一些開發需求,想要侷限網站的功能。剛好這個網站服務是用 PHP CodeIgniter 開發的,整套都是走 RewriteRule 來進行,例如一個 URL 位置,都一律導向到 PHP CodeIgniter Project 的 index.php?/path 來分析。

假設原本網站有 3 個主要網址,分別是 /api, /shopping, / 等,假設想要讓此網站只開啟 /api 時,這時就可以透過 Apache RewriteRule 來限制:

<VirtualHost *:80>
DocumentRoot /ci-project/
DirectoryIndex index.html index.php index.htm

# empty page
Alias /empty     /var/www/html/

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

<Directory /var/www/html/>
Options FollowSymLinks
AllowOverride None
DirectoryIndex index.html index.php index.htm
Require all granted
Satisfy Any
</Directory>

<Directory /ci-project>
Options FollowSymLinks
DirectoryIndex index.php
AllowOverride None
#AllowOverride All
Require all granted
Satisfy Any

<IfModule mod_rewrite.c>
RewriteEngine On
#LogLevel alert rewrite:trace6
RewriteBase /

# disable index.php with empty QUERY_STRING
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^index\.php$ /empty/ [L]

RewriteCond $1 !^(index\.php|images|css|js|favicon\.ico)
# enable /api only
RewriteCond $1 ^api.*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ./index.php?/$1 [L,QSA]
</IfModule>
</Directory>
</VirtualHost>


如此一來,只要使用者逛 / 位置,則會顯示 /var/www/html 的資料,而逛 /api 系列時,則是可以正常引導到 PHP CodeIgniter 相關程式碼來處理。

2014年6月25日 星期三

[Linux] Apache/GeoIP/mod_geoip: 依據 Client IP Country 回傳指定 Server Location @ Ubuntu 14.04、Apache 2.4.7

$ apt-cache show libapache2-mod-geoip
Package: libapache2-mod-geoip
Priority: optional
Section: universe/web
Installed-Size: 86
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Prach Pongpanich <prachpub@gmail.com>
Architecture: amd64
Version: 1.2.8-2
Depends: apache2-api-20120211, libc6 (>= 2.3.4), libgeoip1
Filename: pool/universe/liba/libapache2-mod-geoip/libapache2-mod-geoip_1.2.8-2_amd64.deb
Size: 18748
MD5sum: fc16528f6d8acabaf8d40c70fe47b1b2
SHA1: 457df303c09556297a8b1f6887fe7a901d8bd063
SHA256: 26eabfe728014a506186f2856a3149f00e7bfcb6db9226dbfe13976ab3b4d584
Description-en: GeoIP support for apache2
 This is an apache2 module for finding the country that a web request
 originated from. It uses the GeoIP library and database to perform
 the lookup. The module allows manipulation of client requests from within
 Apache based on the country of origin.
 .
 This module only works on Apache 2 servers.
Description-md5: e4085008663af571952df21045e8534a
Homepage: http://www.maxmind.com/app/mod_geoip
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu

$ sudo apt-get install libapache2-mod-geoip

$ ls -la /usr/share/GeoIP/
total 3852
-rw-r--r--   1 root root  827301 Apr  7 14:20 GeoIP.dat
-rw-r--r--   1 root root 3105495 Apr  7 14:21 GeoIPv6.dat


基本上安裝完就等同啟動 mod_geoip ,可以在 /etc/apache2/mods-enabled 看到 geoip.conf, geoip.load 蹤影。

編輯 Apache configure file:

<IfModule mod_geoip.c>
        GeoIPEnable On
        <IfModule mod_rewrite.c>
                RewriteEngine On
                RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CN$
                RewriteRule ^(.*)$ http://example.com.cn$1 [L]
        </IfModule>
</IfModule>


如此一來,當 Client IP 判斷是 CN 時,透過 Web Server 導向 CN 區的機器。

使用這招的目的是...大陸架設服務時,需要"備案",在備案還沒通過時,使用 domainname 連線過去的機器會被 ban 掉,這時候可以先稍微用已備案的或是 IP 來頂替了。

當備案成功後,就可以大方地使用 GeoDNS 的解法,讓使用者不必先連到指定機器再轉址。

最後,如果要留一些 debug 模式,可以多加上 hostname 的判斷,限定特定 hostname 才會依照使用者 IP 位置轉址。

<IfModule mod_geoip.c>
        GeoIPEnable On
        <IfModule mod_rewrite.c>
                RewriteEngine On
                RewriteCond %{HTTP_HOST} .
                RewriteCond %{HTTP_HOST} ^www\.example\.com$
                RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CN$
                RewriteRule ^(.*)$ http://www.example.com.cn$1 [L]
        </IfModule>
</IfModule>


參考資料:

2014年6月10日 星期二

[Linux] Apache Error Log: configuration error: couldn't perform authentication. AuthType not set!: / @ Ubuntu 12.04, Ubuntu 14.04

最近部署環境時,想要偷懶共用一個 apache 設定檔,由於 Ubuntu 14.04 預設是安裝 apache 2.4.7 而 Ubuntu 12.04 預設是安裝 Apache 2.2.2。

忘記是 apache 哪版開始,預設必須加上:

Order allow,deny
Allow from all



Require all granted

才能正常使用,然而這兩段剛好一個是 apache 2.2,另一個是 apache 2.4 使用,並且不相容,所幸,還有個解法...那就是 Satisfy Any 啦

<Directory /path/www>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None

        Order allow,deny
        allow from all

        Require all granted

        Satisfy Any
</Directory>

2014年6月3日 星期二

[Linux] Allow from localhost 失效 @ Ubuntu 14.04 / Apache 2.4.7

[Linux] Allow from localhost 失效 @ Ubuntu 14.04 / Apache 2.4.7

週末把某檯機器更新後,發現原先寫的 apache.conf 失效,主要是 Allow from localhost 這段:

<Directory /data/path>
AuthType Basic
AuthName "Password Required"
AuthUserFile /path/auth_pass

Order allow,deny
Allow from localhost
# Allow from DeviceIP


Satisfy any
</Directory>


直到我加上 DeviceIP 後才行。

$ wget -O /dev/null http://localhost/service/api
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:443... connected.
WARNING: no certificate subject alternative name matches
        requested host name ‘localhost’.
HTTP request sent, awaiting response... 401 Unauthorized

Username/Password Authentication Failed.


追了一下,發現是 iptables 的設定,把這條拿掉就行了:

iptables --table nat --append POSTROUTING --jump MASQUERADE

此筆記是用來記錄,iptables 的影響 Orz

2014年4月28日 星期一

[Linux] Apache/2.4.7 [authz_core:error] : client denied by server configuration @ Ubuntu 14.04

開始在 AWS 上試用 Ubuntu 14.04 了,結果安裝完碰到這問題 XD 說真的有好一陣子沒有用 apache web server ,為了方便 deploy 跟 server 管理,就又改用 apache 了

關鍵解法:
Require all granted
範例:

$ sudo apt-get install mysql-client php5 apache2
$ sudo mkdir -p /data/dev
$ sudo vim /etc/apache2/conf-available/dev.conf
Alias /dev /data/dev
<Directory /data/dev>
        Options FollowSymLinks
        DirectoryIndex index.php
        AllowOverride None

        Require all granted
</Directory>

$ sudo a2enconf service-dev
$ sudo service apache2 restart