Dockerは完全なPHP-RPC-Golang環境を配備する
phpがrpcを介してgolangにアクセスする環境をdockerに完全に基づいて配置します.
基本アーキテクチャ
PHPのLaravelフレームワークを使用して、ユーザー登録Restful Apiを実現します.アドレスは次のとおりです.
返される情報は、ユーザIdおよびJWT tokenである.
Golangは2つのサービスを実現するために使用され、1つはユーザー情報サービスであり、1つはログイン統計サービスであり、PHPはgRPCを通じてGolangと通信する.
最終的な導入が完了すると、4つのdockerのcontainerがあります.それぞれ: Nginxサービス PHP-FPMサービス ユーザ情報サービス 登録統計サービス 詳細手順ローカル環境私のホームディレクトリは/home/anakin です.
wwwディレクトリに入りprotobufのコードをダウンロードし、その中の1つのツールを使用します.
www/demoディレクトリに入り、Laravelプロジェクトを作成します.
後でビジネスコードを書きます.
www/conf.dに入り、nginx-hostを作成します.confは、PHPを解析するためのサービスで、内容は以下の通りです.
そのうち、192.168.32.3131は、ホストのipアドレスです.www/phpiniに入りcustomを書くiniファイル、phpに必要な拡張子をロードします.内容は次のとおりです. PHPを運転するcontainer
Dockerfileを作成します.内容は次のとおりです.
イメージの作成:
実行:
Laravelプロジェクトコードを保持するディレクトリをマッピングしました. Nginxを実行するcontainer
さっきホストファイルを保存したディレクトリをマッピングしました rpcサービスを準備するまずユーザ情報サービスのuserrpcを記述する.protoファイル、内容は以下の通り:
統計サービス用のtraceを作成する.protoファイル、内容は以下の通りです.
PHPのクライアントコードを生成する:
golangサービス・エンド・コードを生成するには、次の手順に従います.
traceの類似. golangサービス開発 GOPATHの下にuserディレクトリを作成し、userの下にuserrpcディレクトリを作成し、生成したばかりのuserrpcを作成します.pb.goはuserrpcディレクトリに格納されます.userディレクトリの下にmainを記述する.go、内容は以下の通りです.
コンパイル
新しいディレクトリを作成し、コンパイルしたUserRpcServiceファイルを入れ、golangのDockerfileを作成します.内容は次のとおりです.
このディレクトリをホストのある場所に配置し、ディレクトリに入り、imageを作成する操作を実行します.
サービスの実行:
traceサービスはこの手順と全く同じで、復唱しません. phpサービス を開発
www/demoディレクトリに入り、上で生成したrpcクライアントコードをLaravlプロジェクトに追加し、まず生成したGPBMetadataディレクトリをwww/demoディレクトリにコピーし、次に生成したApp下のUserRpcディレクトリをwww/demo/appディレクトリにコピーする.
www/demoディレクトリの下のcomposerを開きます.json、classmapの下に行を追加します.
次に、
www/demo/routes/webを編集します.phpファイル、次の行を追加します.
www/demo/configディレクトリの下にconstantsを作成する.phpファイル、内容は以下の通りです.
UserControllerをapp/Http/Clontrollersディレクトリの下に作成します.phpファイル、内容は以下の通りです.
今、POSTホストipの80ポートにアクセスできるかどうか見てみましょう.何の手順も漏れていないことを願っています.
基本アーキテクチャ
PHPのLaravelフレームワークを使用して、ユーザー登録Restful Apiを実現します.アドレスは次のとおりです.
POST /user/login
返される情報は、ユーザIdおよびJWT tokenである.
Golangは2つのサービスを実現するために使用され、1つはユーザー情報サービスであり、1つはログイン統計サービスであり、PHPはgRPCを通じてGolangと通信する.
最終的な導入が完了すると、4つのdockerのcontainerがあります.それぞれ:
apt install protobuf
apt install composer
mkdir -p www/demo
mkdir www/conf.d
mkdir www/phpini
wwwディレクトリに入りprotobufのコードをダウンロードし、その中の1つのツールを使用します.
git clone https://github.com/grpc/grpc.git
www/demoディレクトリに入り、Laravelプロジェクトを作成します.
composer create-project laravel/laravel demo
composer require grpc/grpc
後でビジネスコードを書きます.
www/conf.dに入り、nginx-hostを作成します.confは、PHPを解析するためのサービスで、内容は以下の通りです.
server {
listen 80;
server_name 192.168.32.131;
set $root_path '/var/www/html/public';
root $root_path;
index index.php index.html index.htm;
try_files $uri $uri/ @rewrite;
location @rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location ~ \.php {
fastcgi_pass 192.168.32.131:9000;
# fastcgi_pass unix:///run/php/php7.2-fpm.sock;
fastcgi_index /index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
root $root_path;
}
location ~ /\.ht {
deny all;
}
error_log /tmp/error.anakin.com.log error;
}
そのうち、192.168.32.3131は、ホストのipアドレスです.www/phpiniに入りcustomを書くiniファイル、phpに必要な拡張子をロードします.内容は次のとおりです.
extension=grpc.so
extension=protobuf.so
mkdir www/phpdocker
cd www/phpdocker
Dockerfileを作成します.内容は次のとおりです.
FROM php:7.2-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
procps \
&& docker-php-ext-install -j$(nproc) iconv \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install zip \
&& pecl install grpc\
&& pecl install protobuf
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& composer config -g repo.packagist composer https://packagist.phpcomposer.com
イメージの作成:
docker build . -t php-fpm:v1.0
実行:
docker run -d -p 9000:9000 -v /home/anakin/www/demo:/var/www/html -v /home/anakin/www/phpini:/usr/local/etc/php/conf.d --name php-fpm php72:v1.0
Laravelプロジェクトコードを保持するディレクトリをマッピングしました.
docker run -d --name nginx -p 80:80 -v /home/anakin/www/demo:/var/www/html -v /home/anakin/www/conf.d:/etc/nginx/conf.d --link php-fpm:php-fpm nginx
さっきホストファイルを保存したディレクトリをマッピングしました
syntax = "proto3";
package App.UserRpc;
service User{
rpc UserLogin(LoginInfo) returns (UserInfo) {}
}
message LoginInfo{
string loginname= 1;
string password= 2;
}
message UserInfo{
int32 code= 1;
string err_msg= 2;
string token= 3;
int32 userid= 4;
string username= 5;
}
統計サービス用のtraceを作成する.protoファイル、内容は以下の通りです.
syntax = "proto3";
package App.Trace;
service Trace{
rpc Event(EventInfo) returns (TraceResult) {}
}
message EventInfo{
string eventtype= 1;
int32 userid= 2;
int32 timestamp= 3;
}
message TraceResult{
bool succ= 1;
}
PHPのクライアントコードを生成する:
protoc --php_out=./ --grpc_out=./ --plugin=protoc-gen-grpc=/home/aaa/grpc/bins/opt/grpc_php_plugin userrpc.proto
golangサービス・エンド・コードを生成するには、次の手順に従います.
protoc --go_out=./ userrpc.proto
traceの類似.
package main
import (
"context"
pb "github.com/anakin/user/userrpc"
"github.com/dgrijalva/jwt-go"
"google.golang.org/grpc"
"log"
"net"
"time"
)
const (
port = ":50052"
)
type User struct {
}
func (u *User) UserLogin(ctx context.Context, req *pb.LoginInfo) (*pb.UserInfo, error) {
log.Printf("received login_name:%v;password:%v", req.Loginname, req.Password)
//mock data
userId:=123
userName := "anakin"
//make jwt token
claim := jwt.MapClaims{
"id": userId,
"username": userName,
"nbf": time.Now().Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256,claim)
tokenString,err := token.SignedString([]byte("token.secret"))
if err !=nil{
log.Printf("signed error")
}
return &pb.UserInfo{Code: 200, ErrMsg: "sss", Userid: 1, Token: tokenString, Username: "anakin"}, nil
}
func main() {
listener, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen:%v", err)
}
s := grpc.NewServer()
pb.RegisterUserServer(s, &User{})
s.Serve(listener)
}
コンパイル
GOOS=linux GOARCH=amd64 go build -o UserRpcService
新しいディレクトリを作成し、コンパイルしたUserRpcServiceファイルを入れ、golangのDockerfileを作成します.内容は次のとおりです.
FROM golang
WORKDIR /go/src/
COPY . .
EXPOSE 50051
CMD ["/go/src/UserRpcService"]
このディレクトリをホストのある場所に配置し、ディレクトリに入り、imageを作成する操作を実行します.
docker build . -t userrpc:v1.0
サービスの実行:
docker run -p 50051:50051 -d userrpc:v1.0
traceサービスはこの手順と全く同じで、復唱しません.
www/demoディレクトリに入り、上で生成したrpcクライアントコードをLaravlプロジェクトに追加し、まず生成したGPBMetadataディレクトリをwww/demoディレクトリにコピーし、次に生成したApp下のUserRpcディレクトリをwww/demo/appディレクトリにコピーする.
www/demoディレクトリの下のcomposerを開きます.json、classmapの下に行を追加します.
GPBMetadata
次に、
composer dump-autoload
www/demo/routes/webを編集します.phpファイル、次の行を追加します.
Route::post('user/login','UserController@login');
www/demo/configディレクトリの下にconstantsを作成する.phpファイル、内容は以下の通りです.
"192.168.32.131:50051",
"TRACE_RPC_SERVICE"=>"192.168.32.131:50052",
];
UserControllerをapp/Http/Clontrollersディレクトリの下に作成します.phpファイル、内容は以下の通りです.
input("loginname");
$password = (string)$request->input("password");
if($loginname == "" || $password == ""){
return response()->json(["code"=>400,"msg"=>"param error","data"=>[]]);
}
$user_rpc_service= Config::get('constants.USER_RPC_SERVICE');
$userrpc = new \App\UserRpc\UserClient($user_rpc_service,[
'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);
$request = new \App\UserRpc\LoginInfo();
$request->setLoginname($loginname);
$request->setPassword($password);
list($recv,$status) = $userrpc->UserLogin($request)->wait();
$code = $recv->getCode();
$msg = $recv->getErrMsg();
$token = $recv->getToken();
$user_id = $recv->getUserid();
$username = $recv->getUsername();
if(200 !=$code){
return response()->json(["code"=>$code,"msg"=>$msg,"data"=>[]]);
}
$trace_rpc_service = Config::get('constants.TRACE_RPC_SERVICE');
$tracerpc = new \App\Trace\TraceClient($trace_rpc_service,[
'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);
$info = new \App\Trace\EventInfo();
$info->setEventtype("user_login");
$info->setUserid("1");
$info->setTimestamp(time());
list($recv,$status) = $tracerpc->Event($info)->wait();
$trace_succ = $recv->getSucc();
$trace_res = $trace_succ == 1 ? "succ" : "fail";
Log::info("trace result:".$trace_res);
return response()->json(["code"=>200,"data"=>["token"=>$token,"userid" =>$user_id,"username"=>$username]]);
}
}
今、POSTホストipの80ポートにアクセスできるかどうか見てみましょう.何の手順も漏れていないことを願っています.