OSS PHP SDKを使ってSwooleで機能を掘り下げる

**Swoole**はPHPの非同期・並列リクエストのための高性能なネットワーク通信エンジンです。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/swoole-based-simple-http-server-with-oss-sdk_347088)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/97250e97-d561-6f7f-abef-27747cf0646e.png)

#序章
Swooleは、最近ではコーダーの世界で新たな "最高の言語 "として定着しています。

公式に説明されているように、PHPの非同期・並列リクエストのための高性能なネットワーク通信エンジンです。そのコンパイルは、PHPの非同期マルチスレッドサーバ、非同期TCP/UDPネットワーククライアント、非同期MySQLを提供するC言語を純粋に利用しています。さらに、非同期Redis、データベース接続プール、AsyncTask、メッセージキュー、ミリ秒タイマー、非同期ファイルの読み書き、非同期DNSクエリ機能を使用しています。HTTP/WebSocket サーバ/クライアント、HTTP 2.0 サーバと入れ子になっています。

Swoole 2.0はGo言語などのコアーチンをサポートしており、完全に同期化されたコードを使用して非同期プログラムを実装することができます。PHPのコードは、追加のキーワードを必要としません。さらに、ボトムレイヤーは、非同期処理を実装するためのコルーチンを自動的にスケジュールします。この記事では、[OSS PHP SDK](https://www.alibabacloud.com/blog/swoole-based-simple-http-server-with-oss-sdk_347088)を使用してAlibaba Cloud上でSwooleを使用する方法を発見します。

#Swooleのメリット
その利点を見てみましょう。

- 純粋にC言語でコンパイルされており、非常に強力なパフォーマンスを発揮。
- シンプルで使いやすく、開発効率が高い。
- イベントドリブンでノンブロッキングの非同期処理。
- 数百万件の同時TCP接続に対応。
- TCP/UDP/UnixSockに対応。
- サーバ/クライアント。
- 非同期/同期/コルーチンに対応。
- マルチプロセッシング/マルチスレッド対応。
- CPUアフィニティ/デーモンプロセス対応。
- IPv4/IPv6ネットワーク対応。



#アプリケーションシナリオ
Swooleをより深く理解するために、Swooleのユースケースを見てみましょう。

現在、プログラム開発者は、C++やJavaなどの複雑なプログラミング言語の代わりに、Swooleを利用してネットワークサーバプログラムを実装しています。いくつかのモバイルインターネット、モノのインターネット、オンラインゲーム、モバイルゲームなどで利用されています。PHPとSwooleを組み合わせることで、開発効率を大幅に向上させることができます。

公式に提供されているPHPネットワークフレームワークは、HTTP、FastCGI、WebSocket、FTP、SMTP、RPCなどのネットワークプロトコルをサポートしており、Swooleをベースに拡張・開発されています。

Swooleのユーザーはどこにでもいて、アメリカ、イギリス、フランス、インド、その他の国に広がっています。テンセント、百度、アリババ、YY言語など、中国の有名なインターネット企業もこの製品を使用しています。

ここでは、[OSS PHP SDK](https://www.alibabacloud.com/help/ja/doc-detail/32099.htm)を使ってSwooleの機能を掘り下げてみましょう。


###1. Swooleを設置
最初のステップとして、Swooleをシステムにインストールする必要があります。PHP7とPECLがインストールされている場合は、以下のコマンドを直接使用することができます。
`pecl install swoole`

次に、php -info | grep php.ini を使用して特定のロードされた設定ファイルを探します。
環境によって異なるかもしれませんが、私たちの環境では /etc/php/7.0/cli/php.ini です。
次に、以下のように実行します。
vim /etc/php/7.0/cli/php.ini

次に、追加します。
拡張子 = "swoole.so"

あるいは、Swooleをコンパイルしてシステムにインストールしても良いでしょう。ただし、以下のスクリーンショットのようなテキストが表示されるまでは、これを行う必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/ec5b9e38-7ab9-1301-e4f0-fad25016163e.png)



###2. OSS PHP SDKを使用
[OSS PHP SDK](https://www.alibabacloud.com/help/ja/doc-detail/32099.htm)でSwooleを使用するためには、PHP SDKのセットアップが成功し、準備ができていることを確認する必要があります。手順は以下の通りです。

- git clone [https://github.com/aliyun/aliyun-oss-php-sdk.git](https://github.com/aliyun/aliyun-oss-php-sdk?spm=a2c65.11461447.0.0.7dbb27aeTf0qSH&file=aliyun-oss-php-sdk.git) # OSS PHP SDKのコードアドレスからコードをダウンロードします。
- cd aliyun-oss-php-sdk/を実行します。
- 設定サンプル/Config.php #.
- サンプルプログラムを実行します。
- curl 127.0.0.1:9503を実行します。
- 画面に「Hello Swoole」と表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/05f1847e-a952-4c8c-325b-939098f375d0.png)

表示されたら、SwooleとOSS PHP SDKを一緒に使う準備ができました。

###3. Nginxをリバースプロキシに設定
上記の手順を踏めば、Swoole経由でOSSにアクセスできるようになります。しかし、サーバー側では、フロントエンドプロキシとしてnginxを使用するのが一般的です。そして、nginxリバースプロキシサーバを経由して、起動したSwooleサーバにアクセスします。

具体的な手順は以下の通りです（すでにnginxをインストールしている場合は省略しても構いません）。

- wget [http://nginx.org/download/nginx-1.11.3.tar.gz](http://nginx.org/download/nginx-1.11.3.tar.gz?spm=a2c65.11461447.0.0.7dbb27aeR2P3yG&file=nginx-1.11.3.tar.gz) から最新版をダウンロードします。
- 次に、tar -zxvf ngin-1.11.3.tar.gzで解凍します。
- 次に、cd nginx-1.11.3 のコマンドを入力します。
- ./configure --prefix=/usr/local/nginx # で設定します。
- このステップで「pcre.h No such file or directory」というエラーが発生する場合がありますのでご注意ください。
- このエラーの詳細は[こちら](https://stackoverflow.com/questions/22555561/error-building-fatal-error-pcre-h-no-such-file-or-directory?spm=a2c65.11461447.0.0.7dbb27aeR2P3yG)をご覧ください。
- さらに、以下のコマンドで libpcre3-dev をインストールする必要があります。
- `sudo make install`
- sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
- 注意：「-c」は設定ファイルのパスを指定します。追加しないと、nginxは自動的にデフォルトのパスで設定ファイルを読み込みます。「h」でヘルプコマンドを見ることができます。
- `ps -ef | grep nginx`
- nginxの進捗状況はこちらで確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a1cafbab-751c-0114-8f97-a661e204be3d.png)


上記のスクリーンショットが画面に表示されていれば、nginxが正常に動作していることを示しています。

次に、nginxリバースプロキシ127.0.0.1:9503を使用して、/usr/local/nginx/conf/nginx.confを修正します。

以下のように実行します。

```
http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  logs/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    #gzip  on;
        upstream swoole{
                server 127.0.0.1:9503;
                keepalive 4;
        }
    server {
        listen       80;
        server_name  www.swoole.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            proxy_pass http://swoole;
            proxy_set_header Connection "";
            proxy_http_version 1.1;
            root   html;
            index  index.html index.htm;
        }
        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}
```

- 次に、設定を有効にするために nginx をリロードする必要があります。

- 次に、vim /etc/hosts に 127.0.0.1 www.swoole.com を追加します。

- 結果を確認するには、curl [www.swoole.com](http://www.swoole.com/?spm=a2c65.11461447.0.0.7dbb27aedv169l) またはブラウザでドメイン名を開き、「Hello Swoole」が表示されているかどうかを確認します。

###4. Swoole を使用した体験談
今までの手順を踏んでも「Hello Swoole」しか結果が出ない場合は、何かが足りないということになります。

先に進んで、何が足りないのかを確認してみましょう。./aliyun-oss-php-sdkディレクトリにsample.jpgファイルがありますので、参考にして使ってみてください。そのファイルをアップロードするためのサンプルコードは以下の通りです。

```
<?php
require_once __DIR__ . '/Common.php';

use OSS\OssClient;
use OSS\Core\OssException;

$bucket = Common::getBucketName();
$ossClient = Common::getOssClient();
if (is_null($ossClient)) exit(1);
//*******************************Simple use***************************************************************
$options = array(
    OssClient::OSS_FILE_DOWNLOAD => "example_download.jpg",
);

$ossClient->uploadFile($bucket, "example.jpg", "example.jpg");
$ossClient->getObject($bucket, "example.jpg", $options);
```

コマンドを実行した後に結果を確認する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/9bef9b56-1e92-e735-9e0f-bb944b256227.png)


OSSで最も簡単なファイルのアップロード/ダウンロード方法は以下の通りです。

上記の手順で、Swooleサーバ内の[OSS PHP SDK](https://www.alibabacloud.com/help/ja/doc-detail/32099.htm)を呼び出します。そして、そのサーバーをnginxプロキシとして使用します。次に、最もシンプルなOSSのアップロード/ダウンロードのコードを以下のように変更します。:

```
<?php
require_once __DIR__ . '/Common.php';

use OSS\OssClient;
use OSS\Core\OssException;

$bucket = Common::getBucketName();
$ossClient = Common::getOssClient();
if (is_null($ossClient)) exit(1);
//*******************************Simple use***************************************************************

$options = array(
    OssClient::OSS_FILE_DOWNLOAD => "example_download.jpg",
);

$serv = new swoole_http_server("127.0.0.1", 9503);

$serv->set(array(
        'worker_num' => 16,
        'daemonize' => true,
        'max_request' => 10000,
        'dispatch_mode' => 2,
        'debug_mode'=> 1,
        'log_file' => '/tmp/swoole_http_server.log',
));

$serv->on('Request', function($request, $response) use($ossClient, $bucket, $options){

        $ossClient->uploadFile($bucket, "example.jpg", "example.jpg");
        $ossClient->getObject($bucket, "example.jpg", $options);

        $response->end("Hello Swoole\n");
});

$serv->start();
```

- php sample/Swoole.php
- 今、コマンドを実行する必要があります: curl www.swoole.com。

長時間応答がなく、nginxがエラーを報告していませんか？
nginxのアクセスログを確認すると504エラーが出ています。Swooleで設定したswoole_http_server.logを開くと以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/69d1a17e-b108-3367-4e4b-2bbe6ad26aae.png)


遭遇する可能性のある問題は以下の2つです。

- 問題1：エラーは、OSS PHP SDKがこのexample.jpgファイルを見つけるのに失敗したことを示しています。しかし、example.jpgはローカルファイルです。なぜ、OSS PHP SDKはそれを見つけることができないのでしょうか？
- 問題2：このエラーが本当だとしても、なぜnginxが504エラーを報告するようになったのか？

さて、この2つの問題を解決するにはどうすればいいのか、疑問に思うかもしれません。

問題1は、Swooleのバグに起因する可能性があります。実際のテストでは、Swooleはカレントディレクトリではなく、ルートディレクトリの「/」から相対パスを計算しています。そうすると、ファイルの解決パスを書くことができます。

問題2については、Swooleのユーザーは、呼び出されたインターフェースによって投げられたエラーをカプセル化しなければなりません。つまり、この記事の場合のOSS PHP SDKが投げたエラーは、nginxに正しく識別させるためのものです。

#結論
Swoole のイベントベースのネットワーク層は、基礎となる epoll/kqueue の実装を利用して、数千の接続に対応します。リクエストの後、割り当てられたメモリは、レガシーのapache/php-fpmのように自分自身を解放しないため、パフォーマンスが大幅に向上します。Swoole を使用すると、より多くの制御が可能な強化されたウェブアプリケーションや、リアルタイムチャットサーバなどを作成することができます。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*