佐藤のメモ帳

DevelopersIOなどの「やってみた系記事」、チュートリアルなどをやってみるただ備忘録です。

Bevyゲーム開発記録 その1 画像を表示する

TL;DR

f:id:xianliang2032:20210913230325p:plain

詳細

  • Struct bevy::prelude::Commands
    • コマンドを使用することで、エンティティの出現やコンポーネントの生成削除、リソースの管理ができる。
  • Struct bevy::prelude::AssetServer
    • ファイルシステムからアセットを取得する
    • アセットはAssetsで管理される。
    • サンプルでは、AssetServer#load()にファイルパスを指定して Handlerを取得している。
      • このHandlerでアセットを追跡することができる。
      • デフォルトではsrcフォルダと同階層のassetsフォルダからのパスを指定するようだ。
  • Struct bevy::prelude::OrthographicCameraBundle
    • 正射影カメラ
    • 2Dゲームやタクティクスゲームのような視点を表現
  • Handlerを指定したSpriteBundleをコマンドに渡すと、画像が表示される。
    • 画像は指定がなければ、(0, 0)の位置、つまりど真ん中に表示される。

参考

error: the option `Z` is only accepted on the nightly compiler

TL;DR

安定版では使用できないオプション。 以下で解決した。

rustup install nightly
rustup default nightly

問題

Bevyのチュートリアルで高速コンパイルを試そうとした。

.cargo/config.tomlこれをコピーし、ビルドしたら以下のエラーが発生した。

Caused by:
  process didn't exit successfully: `rustc - --crate-name ___ --print=file-names -C link-arg=-fuse-ld=/usr/local/bin/zld -Zshare-generics=y --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg` (exit status: 1)
  --- stderr
  error: the option `Z` is only accepted on the nightly compiler

環境

  • macOS Big Sur
  • cargo 1.55.0 (32da73ab1 2021-08-23)

解決

stackoverflow.com

Zオプションは安定板コンパイラでは使用できない。
ナイトリー版に入れ替えたら(cargo 1.56.0-nightly (18751dd3f 2021-09-01))ビルドが通った。

rustup install nightly
rustup default nightly

cURLでAPI GatewayにGETリクエストを投げるためにはXオプション指定が必要

結論

cURLAPI GatewayにGETリクエストを投げる場合、Xオプションで使用メソッドを明示的に指定する必要がある。
何故オプションを省略するとエラーになるかは不明。

背景

API Gatewayを試そうと、cURLでリクエストを投げたら失敗した。
意外な原因だったため記録する。

環境

詳細

API Gatewayに設定したリソースにGETリクエストをcURLで投げたところ、HTTPステータスコード403が返され、エラーになった。
APIキーの生成、使用量プランの設定(対象のステージとAPIキーの紐付け)、curlコマンドに設定されているAPIキーが正しいか、パスが正しいかなど調べたが特に誤っているものはなかった。

投げたコマンドは以下

satoukensuke@MacBook-Pro ~ % curl -H 'x-api-key:XXXXX' https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hoge -I
HTTP/2 403 
date: Tue, 31 Aug 2021 14:08:13 GMT
content-type: application/json
content-length: 0
x-amzn-requestid: 7abe8008-6295-450a-a364-dfefc553029b
x-amzn-errortype: MissingAuthenticationTokenException
x-amz-apigw-id: E72oMHlqtjMFgcQ=

レスポンスヘッダにx-amzn-errortype: MissingAuthenticationTokenExceptionが設定されていた。
公式ドキュメントによるとリクエストに認証トークンが設定されていないリソースパスが誤っていることが原因みたいである。
しかし、上記cURLコマンドでは認証ヘッダに正しい認証トークンを設定し、存在するリソースパスを指定している。

1日放置後、再度調査、確認をした。
ふと、Xオプションでメソッドを指定したらどうなるだろうと試したらエラーにならず、成功した。

satoukensuke@MacBook-Pro ~ % curl -X GET -H 'x-api-key:XXXXX' https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hoge -I 
HTTP/2 200 
date: Tue, 31 Aug 2021 14:06:10 GMT
content-type: application/json
content-length: 0
x-amzn-requestid: 10274e95-3101-4085-abd7-e2645481d03a
access-control-allow-origin: *
x-amz-apigw-id: E72U9F6wtjMFmvQ=

vオプションで詳細を出力してみた。
どちらもGETで投げ、200が返されており、時間やリクエストIDなどの可変項目を除いて出力が異なる点はなかった。

エラーありコマンド

satoukensuke@MacBook-Pro ~ % curl -H 'x-api-key:XXXXX' https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hoge -v
.
.
. TLSハンドシェイクに関するログ
.
.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fbf7d80e800)
> GET /dev/hoge HTTP/2
> Host: xxx.execute-api.ap-northeast-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
> x-api-key:XXXXX
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< date: Tue, 31 Aug 2021 14:45:56 GMT
< content-type: application/json
< content-length: 0
< x-amzn-requestid: 7e365f1f-1cdb-44cf-91b6-a5eb5506a5f4
< access-control-allow-origin: *
< x-amz-apigw-id: E78JxE3UNjMF64Q=
< 
* Connection #0 to host xxx.execute-api.ap-northeast-1.amazonaws.com left intact
* Closing connection 0

エラーなしコマンド

satoukensuke@MacBook-Pro ~ % curl -X GET -H 'x-api-key:XXXXX' https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hoge -v   
Note: Unnecessary use of -X or --request, GET is already inferred.
.
.
. TLSハンドシェイクに関するログ
.
.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fa32300e800)
> GET /dev/hoge HTTP/2
> Host: xxx.execute-api.ap-northeast-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
> x-api-key:XXXXX
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< date: Tue, 31 Aug 2021 14:48:26 GMT
< content-type: application/json
< content-length: 0
< x-amzn-requestid: 66241212-4277-4964-9cc3-9c8f22d32604
< access-control-allow-origin: *
< x-amz-apigw-id: E78hJEf1NjMFTdg=
< 
* Connection #0 to host xxx.execute-api.ap-northeast-1.amazonaws.com left intact
* Closing connection 0

gRPCチュートリアルのクライアント側をFlaskで動かす

はじめに

前回の記事から少しソースを改良した。 クライアント側にFlaskを導入し、ブラウザからのリクエストに応じてレスポンスをするよう修正した。

イメージは以下の通り。

f:id:xianliang2032:20210829002008j:plain
全体図

ソース

github.com

実施

docker-compose up実施後、サーバ用コンテナに乗り込み、greeter_server.pyを実行。

satoukensuke@MacBook-Pro ~ % docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                                       NAMES
b082024290ec   grpc-test_client   "/entrypoint.sh /sta…"   56 minutes ago   Up 56 minutes   80/tcp, 443/tcp, 0.0.0.0:50050->50050/tcp   grpc-test_client_1
a4d3818cbe16   grpc-test_server   "python3"                2 days ago       Up 56 minutes   0.0.0.0:50051->50051/tcp                    grpc-test_server_1
satoukensuke@MacBook-Pro ~ % docker exec -it grpc-test_server_1 /bin/bash
root@SERVER:/service/server# python greeter_server.py

クライアント用コンテナに乗り込み、greeter_client.pyを実行。 Flaskが起動されたことを確認。

satoukensuke@MacBook-Pro ~ % docker exec -it grpc-test_client_1 /bin/bash
root@CLIENT:/service/client# python greeter_client.py
 * Serving Flask app "greeter_client" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:50050/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 240-189-845

ブラウザからクライアントにアクセス(http://localhost:50050/test?name=you)し、期待したレスポンス(Json形式)が表示されるのを確認した。

f:id:xianliang2032:20210829002704p:plain

gRCPサンプルの実行環境をDockerに移行

はじめに

前回の記事Next Actionだった、gRCPサンプルの実行環境をDockerに変更を行なった。

ソース

github.com

実施

前回の記事ではgRCPサンプルgreeter_server.py, greeter_client.pyをローカル環境で実行していた。 今回はdocker-compose upでそれぞれのDocker環境を用意するようにした。

MacBook-Pro:grpc-test satoukensuke$ docker-compose up
Building server
Step 1/8 : FROM python:3.9.6
3.9.6: Pulling from library/python
4c25b3090c26: Pull complete
1acf565088aa: Pull complete
b95c0dd0dc0d: Pull complete
5cf06daf6561: Pull complete
942374d5c114: Pull complete
64c0f10e4cfa: Pull complete
76571888410b: Pull complete
5e88ca15437b: Pull complete
0ab5ec771994: Pull complete
Digest: sha256:8f642902ba368481c9aca0a100f08daf93793c6fa14d3002253ea3cd210383a7
Status: Downloaded newer image for python:3.9.6
 ---> 1e76b28bfd4e
Step 2/8 : RUN mkdir /service
 ---> Running in 6180a22573cb
Removing intermediate container 6180a22573cb
 ---> 6d58e02c9b7f
Step 3/8 : COPY protobufs/ /service/protobufs/
 ---> 71feba714fdb
Step 4/8 : COPY server/ /service/server/
 ---> 2e6df3c0c61a
Step 5/8 : EXPOSE 50051
 ---> Running in 0bf536a955c8
Removing intermediate container 0bf536a955c8
 ---> b479f119e6c6
Step 6/8 : WORKDIR /service/server/
 ---> Running in a3cbfded4a25
Removing intermediate container a3cbfded4a25
 ---> 2218b025f77b
Step 7/8 : RUN pip install -r requirements.txt
 ---> Running in 7a25d264e921
Collecting grpcio==1.39.0
  Downloading grpcio-1.39.0-cp39-cp39-manylinux2014_x86_64.whl (4.3 MB)
Collecting grpcio-tools==1.39.0
  Downloading grpcio_tools-1.39.0-cp39-cp39-manylinux2014_x86_64.whl (2.5 MB)
Collecting protobuf==3.17.3
  Downloading protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl (1.0 MB)
Collecting six>=1.5.2
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Requirement already satisfied: setuptools in /usr/local/lib/python3.9/site-packages (from grpcio-tools==1.39.0->-r requirements.txt (line 2)) (57.4.0)
Installing collected packages: six, protobuf, grpcio, grpcio-tools
Successfully installed grpcio-1.39.0 grpcio-tools-1.39.0 protobuf-3.17.3 six-1.16.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Removing intermediate container 7a25d264e921
 ---> acd83dc0df0c
Step 8/8 : RUN python -m grpc_tools.protoc -I ../protobufs --python_out=.            --grpc_python_out=. ../protobufs/helloworld.proto
 ---> Running in 3578fd3820ac
Removing intermediate container 3578fd3820ac
 ---> 8139333794d2

Successfully built 8139333794d2
Successfully tagged grpc-test_server:latest
WARNING: Image for service server was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Building client
Step 1/8 : FROM python:3.9.6
 ---> 1e76b28bfd4e
Step 2/8 : RUN mkdir /service
 ---> Using cache
 ---> 6d58e02c9b7f
Step 3/8 : COPY protobufs/ /service/protobufs/
 ---> Using cache
 ---> 71feba714fdb
Step 4/8 : COPY client/ /service/client
 ---> 0d9754f91b51
Step 5/8 : EXPOSE 50050
 ---> Running in 8dc638c154be
Removing intermediate container 8dc638c154be
 ---> a9ac09980164
Step 6/8 : WORKDIR /service/client
 ---> Running in fe0b3167571f
Removing intermediate container fe0b3167571f
 ---> db37ff46721b
Step 7/8 : RUN pip install -r requirements.txt
 ---> Running in fbf3083c440d
Collecting grpcio==1.39.0
  Downloading grpcio-1.39.0-cp39-cp39-manylinux2014_x86_64.whl (4.3 MB)
Collecting grpcio-tools==1.39.0
  Downloading grpcio_tools-1.39.0-cp39-cp39-manylinux2014_x86_64.whl (2.5 MB)
Collecting protobuf==3.17.3
  Downloading protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl (1.0 MB)
Collecting six>=1.5.2
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Requirement already satisfied: setuptools in /usr/local/lib/python3.9/site-packages (from grpcio-tools==1.39.0->-r requirements.txt (line 2)) (57.4.0)
Installing collected packages: six, protobuf, grpcio, grpcio-tools
Successfully installed grpcio-1.39.0 grpcio-tools-1.39.0 protobuf-3.17.3 six-1.16.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Removing intermediate container fbf3083c440d
 ---> 47c38bd90bc0
Step 8/8 : RUN python -m grpc_tools.protoc -I ../protobufs --python_out=.            --grpc_python_out=. ../protobufs/helloworld.proto
 ---> Running in 41b34a563bde
Removing intermediate container 41b34a563bde
 ---> 598956e4f281

Successfully built 598956e4f281
Successfully tagged grpc-test_client:latest
WARNING: Image for service client was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating grpc-test_server_1 ... done
Creating grpc-test_client_1 ... done
Attaching to grpc-test_server_1, grpc-test_client_1
server_1  | Python 3.9.6 (default, Aug 17 2021, 15:37:33) 
server_1  | [GCC 10.2.1 20210110] on linux
server_1  | Type "help", "copyright", "credits" or "license" for more information.
client_1  | Python 3.9.6 (default, Aug 17 2021, 15:37:33) 
client_1  | [GCC 10.2.1 20210110] on linux
client_1  | Type "help", "copyright", "credits" or "license" for more information.

サーバ用コンテナに乗り込み、greeter_server.pyを実行。

MacBook-Pro:~ satoukensuke$ docker ps
CONTAINER ID   IMAGE              COMMAND     CREATED          STATUS          PORTS                      NAMES
0e70af7f1bb9   grpc-test_server   "python3"   16 minutes ago   Up 16 minutes   0.0.0.0:50051->50051/tcp   grpc-test_server_1
c9484035278e   grpc-test_client   "python3"   16 minutes ago   Up 16 minutes   0.0.0.0:50050->50050/tcp   grpc-test_client_1
MacBook-Pro:~ satoukensuke$ docker exec -it grpc-test_server_1 /bin/bash
root@SERVER:/service/server# python greeter_server.py 

クライアント用コンテナに乗り込み、greeter_client.pyを実行。 サンプルと同じ結果が返却され、gRPCで通信できていることを確認できた。

MacBook-Pro:~ satoukensuke$ docker exec -it grpc-test_client_1 /bin/bash
root@CLIENT:/service/client# python greeter_client.py 
Greeter client received: Hello, you!

gRPC Quick startをやってみる

はじめに

以下のチュートリアルに従い、gRPCのサンプルを実行してみる。

grpc.io

事前に以下を読むべし。

qiita.com

環境

実施

gRPCインストール

(venv) satoukensuke@MacBook-Pro Desktop % python -m pip install grpcio
Requirement already satisfied: grpcio in ./venv/lib/python3.9/site-packages (1.39.0)
Requirement already satisfied: six>=1.5.2 in ./venv/lib/python3.9/site-packages (from grpcio) (1.16.0)

gRPCツールインストール

gRPCツールには、protcol bufferコンパイラprotoc.protoからサーバ、クライアントコードを生成する機能が含まれている。

(venv) satoukensuke@MacBook-Pro Desktop % python -m pip install grpcio-tools
Requirement already satisfied: grpcio-tools in ./venv/lib/python3.9/site-packages (1.39.0)
Requirement already satisfied: setuptools in ./venv/lib/python3.9/site-packages (from grpcio-tools) (57.4.0)
Requirement already satisfied: grpcio>=1.39.0 in ./venv/lib/python3.9/site-packages (from grpcio-tools) (1.39.0)
Requirement already satisfied: protobuf<4.0dev,>=3.5.0.post1 in ./venv/lib/python3.9/site-packages (from grpcio-tools) (3.17.3)
Requirement already satisfied: six>=1.5.2 in ./venv/lib/python3.9/site-packages (from grpcio>=1.39.0->grpcio-tools) (1.16.0)

サンプルダウンロード

Githubリポジトリからcloneして、サンプルディレクトリに移動。

(venv) satoukensuke@MacBook-Pro Desktop % git clone -b v1.38.0 https://github.com/grpc/grpc
Cloning into 'grpc'...

略...

Updating files: 100% (9108/9108), done.
(venv) satoukensuke@MacBook-Pro Desktop % cd grpc/examples/python/helloworld 

サンプルの起動

gRPCのリクエストを受け取り、返却するサーバを起動する。

(venv) satoukensuke@MacBook-Pro helloworld % python greeter_server.py 

別ターミナルを開き、grpc/examples/python/helloworldに移動、gRPCリクエストをサーバに投げるクライアントを実行する。

(venv) satoukensuke@MacBook-Pro Desktop % cd grpc/examples/python/helloworld 
(venv) satoukensuke@MacBook-Pro helloworld % python greeter_client.py 
Greeter client received: Hello, you!

メモ

greeter_client.pyでは、nameパラメタに値youをポート50051に投げている。

def run():
    # NOTE(gRPC Python Team): .close() is possible on a channel and should be
    # used in circumstances in which the with statement does not fit the needs
    # of the code.
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
    print("Greeter client received: " + response.message)

greeter_server.pyでは、リクエスnameパラメタの値から文字列を生成している。
サンプルではHello, you!が生成される。
生成文字列は、最終的にレスポンスmessageとして返却している。

class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

図にするとこう。

f:id:xianliang2032:20210821004429p:plain

Next Action

  • サーバとクライアントをそれぞれdocker化
  • Flaskアプリケーションにする。アプリサーバはuWSGI
  • grpc-gatewayでブラウザから投げたHTTPリクエストのJsonをgRPCに変換(できる?少し曖昧)