第4のWEBサーバ「LiteSpeed」はNginxより高速か、centOS7に環境構築し動作検証

レンタルサーバについて情報を物色していたところ、[某サーバ会社](https://mixhost.jp/)などが**LiteSpeed**なるWEBサーバを使用していることがわかり、この高速性が売りだというLiteSpeedに興味を持ったので、Webシステム構築でも実務的な使用に耐えうるか動作テスト、そしてNginxとの対照実験を行うためにcentOS7にインストールしてみることにしました。

Litespeed自体は2015年頃から存在していたみたいで、第4のWEBサーバ（Apache、IIS、Nginx、LiteSpeed）と呼ばれていたみたいです。ところが、意外にもWEB上の情報は少なく、しかもブログサイトでの用例がほぼWordPress用となっていました（海外サイトではけっこう情報が豊富だったので、海外サイトからもかなり参考にしています）。なお、LiteSpeedは有償版のEnterpriseと無償版のOpenLiteSpeedがあり、テストに用いたのは後者となります。

[LiteSpeed公式サイト](https://www.litespeedtech.com/)

# １：OpenLiteSpeedのインストール
正直、インストールだけならyumコマンドを使えるので全く難しくないです。このページあたりを参考に、リポジトリを取得して実践してみました。ただ、時間が経過している関係か、このサイトでは`service`コマンドで再起動、常駐処理をしていますが、普通に`systemctl`コマンドで対応できます。

- [LiteSpeed Web Server インストールメモ（CentOS）](https://blog.apar.jp/linux/10041/)

```
#yum -y groupinstall base development network-tools
#yum -y install epel-release  //使用リポジトリはepelのようです
#rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el7.noarch.rpm  //rpmのダウンロード
#yum -y install openlitespeed
#systemctl start lsws  //再起動
#systemctl enable lsws   //lswsの常駐
```

これで、インストールは完了です。そして、この状態で**PHP5.6～7.3まで一通り使える**ようになります。いやあ、Nginxと比べるとすごく簡単だなぁ…と思ったのはここまでで、実はここからの設定がかなり面倒です。

# ２：設定
GUI（Webコンソール）から色々行えるようです。そして、今回の目的としてApacheと同様に`/var/www/html`からアクセスできるように設定します。なお、参考ページはファイアウォール設定も行っていますが、今回は設定はしません（要はファイアウォールを設定しなくても、WEBコンソールにアクセスは可能です）。

## ２－１：IDとパスワードの設定
LiteSpeedは**lsws** (**L**ight **S**peed **W**eb **S**erver)というディレクトリに設定されるようで、まずはwebコンソールログイン用にユーザー名とパスワードを設定しておきます（今回はテストなので、適当なIDとパスワードを設定しています）

```
#/usr/local/lsws/admin/misc/admpass.sh
User name [admin]: hogehoge    //ユーザー名
Password: fugafuga  //pw名
Retype password: fugafuga
```
## ２－２：WEBコンソールによる設定
この状態でWEBコンソール画面にアクセスします。
**192.168.xx.xx:7080**
ここにアクセスするとログイン画面が現れるので、ユーザー名とパスワードを入力していよいよ設定開始です。

![login_top.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/874eb0bf-edd6-4372-df11-9ffa9b2bb6c2.jpeg)

### イ：ポート設定
LiteSpeedはデフォルトで8088番を使用しているようなので、以下のルートから80に変更します。

先程のページに設定手順が載っています（デフォルトでは言語が英語になっているので、右上の言語設定から日本語に変更してください）

- [LiteSpeed Web Server インストールメモ（CentOS）](https://blog.apar.jp/linux/10041/)

1. 左側ナビからリスナーを選択
2. リスナーのリストからdefaultをクリック
3. アドレス設定から、右上の編集アイコンをクリック
4. ポートを8088から80に変更してから、右上の保存アイコンをクリック
5. 右上の再起動アイコン（緑色の転回矢印）をクリック 

この状態で一旦保存します。
### ロ：PHPバージョンの変更
さて、この状態で以下のページにアクセスします。

**192.168.xx.xx/phpinfo.php**

~~晴れてPHP情報がずらずら…と表示されますが、あろうことか未だ**PHP5.6がデフォルト**になっています。そこでPHP7.2に変更します。以下のサイトによれば、次の設定を変更するだけで大丈夫のようです。~~
※追記。最新のバージョンはPHP7.3がデフォルトとなっているので、この作業は不要です。

[LiteSpeed Web Server での WordPress 設定メモ（CentOS）](https://blog.apar.jp/linux/10079/)

　1. 左側ナビからサーバー設定を選択
　2. 上のタブから外部アプリを選択
　3. 外部アプリケーションのリスト右側にある、編集コマンドをクリック
　4.  LiteSpeed SAPI アプリ中ぐらいにあるコマンドに**$SERVER_ROOT/lsphpXX/bin/lsphp**(XXは任意のPHPバージョン。7.2なら72)と入力
　5.  保存してから再起動

これでもう一度**phpinfo.php**ページにアクセス（リロード）して、バージョンが変更されていれば、当該バージョン適用となります。
![phpinfo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/c26aeb09-24a6-6f43-dc3d-e45e42c51864.jpeg)


## ２－３：ドキュメントルートの変更（設定ファイルから）
ここがかなり厄介でした。そして、WEB上にも回答らしきものが見つからなかったので苦労しましたが、現状の手がかりをヒントに修正を加えます。

### phpinfo.phpの場所を探す
現在、phpinfo.phpはドキュメントルートから表示されているので、それならばこのphpinfo.phpが格納されている場所を`find`コマンドで探します。

```
#find / -type f -name 'phpinfo.php'
```

すると、どうやらphpinfoファイルの場所は

**/usr/local/lsWs/Example/html/phpinfo.php**

となっているようです。ならば、今度はWEBコンソールからこのドキュメントルートを変更できないかWEBコンソールを一通り調べていると、ナビのバーチャルホスト→基本の項目に、設定ファイルのアドレスが記載されていました。
![host.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/c178e7b4-a2e6-6d0f-3f3b-b0d3e41209ee.jpeg)


**conf/vhosts/Example/vhconf.conf**

どうやらこれが設定ファイルのようなので、今度はターミナルから直接編集に行きます。

```
#vi /usr/local/lsws/conf/vhosts/Example/vhconf.conf
```

すると、ファイルの先頭にドキュメントルートを設定するパスがありましたので、以下のように編集します。

```conf:vhconf.conf
;docRoot $VH_ROOT/html/
docRoot /var/www/html/
```

あとは`systemctl`コマンドで再起動してから、以下のテストページを作成します。

```
#cd /var/www/html
#vi test.php
```
test.phpの中身はなんでもいいです。

```php:test.php
<?php
    echo "hello,world";

```

これでもう一度ブラウザでアクセスしてみましょう。
**192.168.xx.xx/test.php**

test.phpが反映され、hello,worldと表示されると思います。これでひとまずは準備完了です。
![helloworld.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/f2d1d401-1712-c00a-8d82-b6024802e2f5.jpeg)


## ２－４：php.iniの設定をする
デフォルト設定だとphp.iniの`display_errors`設定がOffになっているので、デバッグしやすいようにこれをOnにします。そのためには先程設定したphp.iniの場所を探す必要があるので、またfindコマンドで探索します。

```
#find / -type f -name 'php.ini'
/*検索結果*/
/usr/local/lsws/lsphp72/etc/php.ini
…
```

すると、**/usr/local/lsws/lsphpxx/etc/php.ini**に存在していることがわかったので、中からdisplay_erros=Offを探し出して、display_errors=Onにしてから、lswsを再起動します。

```
#vi /usr/local/lsws/lsphpxx/etc/php.ini
//以下を書き換える
display_errors = On
error_reporting = E_ALL   //後の部分を削除する
#systemctl restart lsws
#systemct restart php-fpm
```

わざと、phpinfoを未定義の関数に書き換え再表示してみると、こんなエラーが表示されました。なにか昔見たような古い表示ですが、これも最新のバージョンでは表示が標準となっていました。
![errors.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/efd6d8c4-1620-8e2c-7f21-fe3e0e3fc0e4.jpeg)

※反映されなかった場合はphp-fpmも再起動してください。

# ３：動作テスト
ジェネレータを使って、1から100000まで出力し、そのベンチマークをとってみました。

```PHP:test.php
<?php
	function generator(){
		$d  =1;
		while($d < 100000){
			$d =  $d+1;
			yield $d;
		}
	}
	$c = "";
	$generator = generator();
	$starttime = microtime(true);
	$c = function($c){ return $c;};
	foreach($generator as $cnt){
	    echo "{$cnt}:{$c(number_format(microtime(true) - $starttime,2))}秒<br>";
	}
```

結果

```
99992:1.74秒
99993:1.74秒
99994:1.74秒
99995:1.74秒
99996:1.74秒
99997:1.74秒
99998:1.74秒
99999:1.74秒
100000:1.74秒
```

確かにかなり速い気はします。ちなみに**1000000**でも試してみたら、16.83秒と出ました（ブラウザが全表示するのに**1分ほど**かかるのですが、ブラウザの出力よりは遥かに速いことがわかります）。

```
1000000:16.83秒
```

##Nginxとの比較テスト
でも、これだとNginxより高速性に優れているのか判りませんので、同一環境にNginxもインストールして、同じくベンチマークをとってみました。

すると、100000だとNginxはなんと**0.28秒**と驚きのスピードを示し、処理の高速性だとNginxの圧勝に思えたのですが、1000000にしてみると、数値こそは2.56秒と速いものの、ブラウザへのレンダリング処理がなかなか追いつかず、全部表示するのに**5分以上**かかったり、取得できずに**メモリオーバー**を起こしたりしてしまいました。

したがって、現時点ではLiteSpeedが優れているのは処理の高速性というよりは、**高負荷にも一定の速度を保つ、安定性と耐久性**ではないかとみています。

# 4 データベース接続
PHPはDBに接続してこそ本領発揮、ということでmariaDBに接続し、phpMyAdminを設定してみることにしました。なお、以下のインストール手順はNginxなど他のサーバで設定するときにも使えると思います。

## phpMyAdminのインストール
phpMyAdminのインストール
ここは一応、公式サイトにインストール方法が載っています。
[Download and Extract phpMyAdmin](https://openlitespeed.org/kb/phpmyadmin-on-openlitespeed/)

それに従い、以下の手順を踏みます。

### 4-1: 必要なライブラリのインストール
公式サイトでは、これだけ入れるように指示しています（XXは任意のPHPのバージョン。72ならlsphp72-hoge）となる。

```
#yum install -y lsphpXX lsphpXX-mysqlnd lsphpXX-common lsphpXX-gd lsphpXX-pdo lsphpXX-process lsphpXX-mbstring lsphpXX-mcrypt lsphpXX-opcache lsphpXX-bcmath lsphpXX-xml lsphpXX-soap lsphpXX-json
```

### 4-2: phpMyAdminのインストールとリンク設定
公式サイトと少し手順が異なるのは、ドキュメントルートを変更しているためで、**シンボリックリンク**を貼っておきます(なお、この時点では4.9.1を使用していますが適宜変更してください)

```
#cd /usr/local/lsws/Example/html
#wget https://files.phpmyadmin.net/phpMyAdmin/4.9.1/phpMyAdmin-4.9.1-all-languages.zip
#unzip phpMyAdmin-4.9.1-all-languages.zip
#mv phpMyAdmin-4.9.1-all-languages phpmyadmin
#ln -s /usr/local/lsws/Example/html/phpmyadmin /var/www/html/　　　 //シンボリックリンクを貼る
```

### 4-3: セッション設定
では、これで使用可能に…なりません。Nginxと同じように**セッション設定**が必要です。

```
#vi /usr/local/lsws/lsphpxx/etc/php.ini
#-: ;session.save_path = "/tmp" //別のリンクになっている場合も
#+: session.save_path = "/var/lib/lsphp/session"    //このように書き換える
#cd /var/lib/lsphp
#chmod -R 777 session
```

これでブラウザを確認してください。ログイン画面が出れば一旦は成功です。

**192.168.11.xx/phpmyadmin/index.php**![phpmyadmin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272191/22a10743-cf86-7636-ba2d-8533a2fbd52a.jpeg)

### 4-4: ログインとコンフィグ設定
当然、phpmyadminでログインするためにはmysqlないしはmariaDBのアカウント作成が必須ですので、事前に作成しておいてください。

さて、晴れてログインしてみようとするとこんなエラーに遭遇することがあります。

**mysqli_real_connect(): (HY000/2002): No such file or directory**

これについては大方コンフィグファイルの問題なので、そこに絞ってページを巡回していると、ドンピシャのページがありました。
[（前略）phpMyAdminを設置したけど、ログインできない](https://codosr.com/archives/116)

やはり、**config.inc.php**の問題だったようで、しかもこのサイトによると、lswsの初期設定ではconfig.sample.inc.phpとなっているようで、設定を適用するにはリネームする必要があるみたいです。

```
# cd /usr/local/lsws/Example/html
# less phpmyadmin/config.sample.inc.php //存在するか確認
# mv phpmyadmin/config.sample.inc.php phpmyadmin/config.inc.php //コンフィグファイルのリネーム
# vi phpmyadmin/config.sample.php

 -:$cfg['Servers'][$i]['host'] = 'localhost';
 +:$cfg['Servers'][$i]['host'] = '127.0.0.1';
```

これでホストを明示的に書き換えると、上記のエラーは出なくなり、アクセスできるようになりました（もし、**connetction refused**などと他のエラーが出るようでしたら、mysqlサーバーをきちんと起動させているかを確認してください）。

```
# systemctl start mariadb  //DBサーバの起動
```

## テストしてみる
テーブルに乱数を発生させ、そのベンチマークをとってみることにしました。

```PHP:PHP
    Const HOSTNAME = "192.168.11.xx";
    Const DBNAME = "dbtest";
    Const USER = "hogehoge";
    Const PASS = "fugafuga";

    function db_con(){
        $c = 'constant';
        $con = "mysql:host={$c('HOSTNAME')};dbname={$c('DBNAME')};charset=utf8";
        $user= USER;
        $pass= PASS;

        //db接続が成功した場合、PDOオブジェクトが生成される。
        try{
                $dbh = new PDO($con,$user,$pass);
                array(PDO::ATTR_EMULATE_PREPARES => false);
        }catch(PDOException $e){
                $dbh = $e->getMessage();
                echo "データベース接続エラーです";
                exit;
        }
        return $dbh;
    }

	$dbh = db_con();
	var_dump($dbh -> errorinfo());
	var_dump($dbh);
	$sql = "select * from random";
	$sth = $dbh -> query($sql);
	function generator(){
		$d  =1;
		while($d < 10000){
			$d =  $d+1;
			yield $d;
		}
	}
	$c = "";
	$generator = generator();
	$ar_char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        //任意の乱数発生
	foreach($generator as $x){
		$char = "";
		while(strlen($char) < 8){
			$idx_rand = rand(0,51);
			$char .= $ar_char[$idx_rand];
		}
		$sql = "insert into random values({$x},'{$char}')";
		$stmt = $dbh -> prepare($sql);
		$stmt -> execute();
	}
	$starttime = microtime(true);
	$c = function($c){ return $c;};
	$rows = [];
	$cnt = 0;
	while($row = $sth -> fetch(PDO::FETCH_ASSOC ) ){
	    echo "{$cnt}:{$c(number_format(microtime(true) - $starttime,8))}秒<br>";
		if(isset($row)){
			$rows[] = $row;
			$cnt++;
		}
	}



```

結果です。1万件ぐらいなら気にならないぐらい高速です。

```
9981:0.08978200秒
9982:0.08978486秒
9983:0.08978891秒
9984:0.08980179秒
9985:0.08980584秒
9986:0.08980989秒
9987:0.08981299秒
9988:0.08981681秒
9989:0.08981991秒
9990:0.08982277秒
9991:0.08982682秒
9992:0.08982992秒
9993:0.08983779秒
9994:0.08984184秒
9995:0.08984590秒
9996:0.08984900秒
9997:0.08985186秒
9998:0.09192491秒
9999:0.09195995秒
```

10万件でもテストしてみました（生成に時間がかかりますが…）。

```
99990:0.89134216秒
99991:0.89134502秒
99992:0.90450811秒
99993:0.90453506秒
99994:0.90453911秒
99995:0.90454221秒
99996:0.90463805秒
99997:0.90464401秒
99998:0.90464711秒
```

処理時間はおよそ20秒弱でした。

では、この同じテストをNginxでも試してみたのですが…およそ2分後

**An error occurred**

このようにサーバーがダウンしてしまいました。なお、一度テーブルを生成した後、単なるループ処理に関してはかなり高速な反面、レンダリングに時間がかかっており、所要時間は同じぐらいでした。

```
99991:0.52503991秒
99992:0.53174686秒
99993:0.53177786秒
99994:0.53178096秒
99995:0.53178477秒
99996:0.53179097秒
99997:0.53179383秒
99998:0.53179693秒
99999:0.53180099秒
100000:0.53180480秒
```

これをどう捉えるかです。とりあえず自分は現段階で、このように使い分ければいいのではないかと思っています。

- 画面が固定化されたwebシステム内のデータ処理　→　処理が高速な**Nginx**
- メディア表示が主となるwebページ → ブラウザへのレンダリング、サーバが安定している**Litespeed**

## 画像表示テスト
この結果は、結論だけ言うとNginxでもLiteSpeedでもそこまで相違ありませんでしたが、LiteSpeedの方に軍配が上がりました。10万枚の画像を表示させるループ文を実行したところ、マイクロタイムは確かにNginxの方が半分のスコアで表示されるのですが、実際、ブラウザの読み込みの終了タイムは、LiteSpeedが17秒、Nginxが22秒ぐらいとなりました。

実際は、そこまで画像を処理しないのであまり気にすることはないとは思いますが、これが映像処理の場合は大きく差が出そうな気がします（未検証なのでいずれやってみたいところですが）。



以下、記述中。