apache cgi-bin として pythonスクリプト を実行する

業務でpythonのcgiを使う機会があり、調べた結果を備忘録として。

# 環境
- CentOS7.4
- Apache2.4.6
- Python 2.7.5
- Python 3.6.5

# インストール方法
## mod_python
1.事前準備

```sh
yum install httpd httpd-devel python-devel
yum groupinstall "Development Tools"
```

2.ダウンロード

```sh
wget http://dist.modpython.org/dist/mod_python-3.5.0.tgz
```

3.コンパイル

```sh
tar zxfv mod_python-3.5.0.tg
cd mod_python-3.5.0
./configure -with-apxs=/usr/bin/apxs
```

4.ファイル編集

```sh
 vi dist/version.sh
　　===================
　　　#!/bin/sh
　　　MPV_PATH="`dirname $0`/../src/include/mp_version.h"
　　　MAJ=`awk '/MP_VERSION_MAJOR/ {print $3}' $MPV_PATH`
　　　MIN=`awk '/MP_VERSION_MINOR/ {print $3}' $MPV_PATH`
　　　PCH=`awk '/MP_VERSION_PATCH/ {print $3}' $MPV_PATH`
　　　#GIT=`git describe --always`
　　　#echo $MAJ.$MIN.$PCH-$GIT
　　　echo $MAJ.$MIN.$PCH-
　　===================
```

5.インストール

```sh
make
make install
```

## mod_wsgi
1.インストール

```sh
yum install -y python36u-mod_wsgi
```

# Apacheの設定例
## mod_cgi

```apache
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options FollowSymLinks ExecCGI
    Require all granted
    AddHandler cgi-script .py
</Directory>
```

## mod_python

```apache
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>

LoadModule python_module modules/mod_python.so
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Require all granted
    AddHandler mod_python .py
    PythonHandler hello
    PythonDebug On
</Directory>
```

## mod_wsgi

```apache
LoadModule wsgi_module modules/mod_wsgi_python3.6.so

WSGIScriptAlias / /var/www/wsgi-bin/
WSGIPythonPath /var/www/wsgi-bin/
<Directory "/var/www/wsgi-bin/">
    AllowOverride None
    Require all granted
    AddHandler wsgi-script .py
</Directory>
```

# プログラムの作成方法
## mod_cgi
一般的なpythonのプログラムでいいと思います

## mod_python
- プログラム名
  - hello.py（PythonHandlerに合わせる)
- 実行時の呼び出しメソッド
 - `def handler(req):`
- レスポンスの指定例
 - `req.contet_type = "application/json"` ← Content-Type
 - `req.write("Hello World")` ← リクエストボディ
- 戻り値例
 - `apache.OK` ← HTTPステータス

## mod_wsgi
- 実行時の呼び出しメソッド
 - `def application(environ, start_response): `
- レスポンスの指定例
 - `start_response('200 OK', [('Content-type', 'text/html')]) `← HTTPステータス、HTTPヘッダ
- 戻り値例
 - `return [b''Hello World]`  ← リクエストボディのバイナリ

# 処理速度
`ab -n 1000 -c 100 https://localhost/cgi-bin/XXX`で計測
## mod_cgi

```
Server Software:        Apache
Server Hostname:        localhost
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /cgi-bin/test.py
Document Length:        1578 bytes

Concurrency Level:      100
Time taken for tests:   11.488 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1734938 bytes
HTML transferred:       1578000 bytes
Requests per second:    87.04 [#/sec] (mean)
Time per request:       1148.847 [ms] (mean)
Time per request:       11.488 [ms] (mean, across all concurrent requests)
Transfer rate:          147.48 [Kbytes/sec] received

Connection Times (ms)
             min  mean[+/-sd] median   max
Connect:        2   24  37.0     12     249
Processing:   247 1091 156.7   1073    1707
Waiting:      143 1001 142.9    997    1655
Total:        253 1115 176.7   1088    1864
```

## mod_python

```
Server Software:        Apache
Server Hostname:        localhost
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /cgi-bin/hello.py
Document Length:        1577 bytes

Concurrency Level:      1000
Time taken for tests:   0.992 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1697000 bytes
HTML transferred:       1577000 bytes
Requests per second:    1007.75 [#/sec] (mean)
Time per request:       992.311 [ms] (mean)
Time per request:       0.992 [ms] (mean, across all concurrent requests)
Transfer rate:          1670.07 [Kbytes/sec] received

Connection Times (ms)
             min  mean[+/-sd] median   max
Connect:        5  220 152.3    156     632
Processing:    10   71  14.1     75     156
Waiting:        7   27   9.8     25     135
Total:        148  291 154.4    229     708
```

## mod_wsgi

```
Server Software:        Apache
Server Hostname:        localhost
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /hello
Document Length:        1577 bytes

Concurrency Level:      1000
Time taken for tests:   1.608 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1729000 bytes
HTML transferred:       1577000 bytes
Requests per second:    621.76 [#/sec] (mean)
Time per request:       1608.325 [ms] (mean)
Time per request:       1.608 [ms] (mean, across all concurrent requests)
Transfer rate:          1049.84 [Kbytes/sec] received

Connection Times (ms)
             min  mean[+/-sd] median   max
Connect:        6  516 248.1    412    1399
Processing:   145  338  73.0    355     468
Waiting:        2  107  40.8     95     293
Total:        160  854 246.4    824    1580
```


# 参考
- mod_pythonの公式ドキュメント
 - https://mod-python-doc-ja.readthedocs.io/ja/latest/contents.html
- mod_wsgiの公式ドキュメント
 - https://modwsgi.readthedocs.io/en/develop/index.html