userverは、C++で書かれたWebフレームワークです。非同期処理を簡単に書けるらしいです。
最初はDebian上で環境を作ろうとしたのですが、Debian 12ではcurlのバグがあり動作しない(トラブルシューティング参照)のでUbuntu 24.10が使えるWSL上で環境を作ることにしました。
WSL2(Ubuntu)の導入
BIOSでVT-xやAMD-Vを有効にしてから、公式のガイドに沿ってコマンドを入力します。MSの公式サポートがあるため非常に簡単です。
デフォルトではUbuntuがインストールされ、WSL側からWindowsへは/mnt/
以下から、WindowsからWSL側へは\\wsl$
からアクセスできます。しかし、Windows上から書き込むとパーミッション上で問題があるようなので今回はRemote Developmentを使います。
userverのインストール
まずはgit(WSLには元から入っている)とbuild-essentialをインストールします。
大体Configure, Build and Install通りですがpostgresを使うため1は以下のようにする必要があります。
$ git clone --depth 1 https://github.com/userver-framework/pg_service_template.git && \
git clone --depth 1 https://github.com/userver-framework/userver.git pg_service_template/third_party/userver && \
cd pg_service_template
ビルドが完了したら、ip addr
を実行してeth0のIPを記録しておきます。WSL上のUbuntuにはWindowsとは別にIPが割り振られていて、ループバックアドレスではアクセスできませんが、このアドレスを使うことでアクセスできます。
Remote Development
【WSL / WSL2】VSCode×WSLでWindows上にLinux開発環境を構築
この記事に従ってVSCodeをUbuntu側から起動します。Ubuntu側にもVSCodeがインストールされます。
一つ問題があり、パスの関係?でlaunch.jsonを使ったF5でのデバッグ立ち上げはできませんでした。VSCodeのターミナルに入力すると普通にビルドと起動が行えます。ちょっと面倒ですがビルドにあるようにシェルスクリプトを作るなどして対応しましょう。
また、次回以降はWindows側からVSCodeを開いても同様に扱えます。
PostgreSQLのインストール
userverのservice templateをビルドすると勝手にPostgreSQLの開発パッケージが入りますが、サーバー本体は入りません。aptでパッケージをインストールしてからUbuntu公式のPostgreSQLセットアップページを見て設定しましょう。WSLの場合、Windows側からデータベースを覗きたい時があると思うのでサブネットを20ぐらいに設定してhost接続を許可してあげます。
設定が終わったらsudo -u postgres psql
でサーバーにアクセスし、CREATE DATABASE userver_test;
でデータベースを作成します。
ユーザーもCREATE USER userver WITH PASSWORD 'userver_password';
で作成し、GRANT ALL ON DATABASE userver_test TO userver;
でデータベースへの権限を与えます。
…と思ったのですが、Amazonの解説通りにやった方が安全な気がします。
sudo -u postgres psql -d userver_test
でデータベースに入り、新しいスキーマをCREATE SCHEMA hello_schema;
で作成し、CREATE TABLE hello_schema.users (name text, count int);
でテーブルを作成します。
…で、多分GRANT ALL ON SCHEMA hello_schema TO userver;
とGRANT ALL ON hello_schema.users TO userver;
が必要です。
設定したらservice templateのconfigs/config_vars.yaml
の中にあるデータベースURIを事前の値で編集してください。
ビルド
これもConfigure, Build and Installに書いてある通りビルドとサービスのスタートを行えばいいのですが、途中にトラブルシューティング部のようなロケール絡みのエラーが発生する場合があります。その詳細を表示させるためにbuild-release
ではなくbuild-debug
としたほうがいいと思います。
make build-debug && \
make service-start-debug
このコマンドをrun.sh
などにまとめておくと便利です。
リクエストを試してみる
pg_service_templateは/v1/hello
にnameをパラメーターとして文字列を送ると、データベースを読み書きして1回目と2回目で違う応答が返ってくるというものです。
ただし、/v1/hello
はPOSTのみ受け付けるのに値はURLパラメーターで渡さなければなりません。つまり、POSTで/v1/hello?name=uservertest
にリクエストを投げたりします(なんで?)。まあ実際にはJSONなどを投げるのでサンプルでは簡略化したということでしょうか…。
追加の開発
Writing your first HTTP serverの通りにヘッダーとソースファイルを作り、CMakeLists.txtにその場所を追記し、static_config.yamlにAPIのパスを追加すれば機能を追加できるはずです。
static_config.yamlに書くパスは可変にもできます。/test/{username}
というようにして、コード側でrequest.GetPathArg("username")
とすることでパスのusernameの部分が取得できます。
デプロイ
build_release下にバイナリがあるので、それを使います。起動時にconfigを要求されるのでProduction configs and best practicesにあるように設定のYAMLファイルを作って指定するとサーバーが立ち上がります。
トラブルシューティング
「エラー:ロケール名”en_US.UTF-8″は不正です」、”invalid locale name en_US.UTF-8″と出る
en_US.UTF-8
のロケールがインストールされていないので、sudo dpkg-reconfigure locales
からen_US.UTF-8
にチェックを入れてインストールしましょう。デフォルトのロケールを変える必要はありません。
curlのバージョンが~と出る
Debian 12ではHTTP/2の実装にバグのあるバージョンのlibcurlしか提供されていないので、大人しくUbuntu 24.10に乗り換えましょう。
config_vars.yamlにデータベースを指定したのにうまく接続できない
(デバッグ環境では?)テスト用のPostgreSQLがDocker上で動いていて、そこに接続するようになっています。config_vars.testing.yaml等の設定を変更することもできますが、うまくいかない場合があるのでテスト用途では内部のPostgreSQLサーバーを使うのがいいと思います。
debian用メモ
依存パッケージ
sudo apt install ccache cmake git libbenchmark-dev libboost-filesystem1.81-dev libboost-iostreams1.81-dev libboost-locale1.81-dev \
libboost-program-options1.81-dev libboost-regex1.81-dev libboost-stacktrace1.81-dev libboost1.81-dev libbson-dev libc-ares-dev \
libcctz-dev libcrypto++-dev libcurl4-openssl-dev libev-dev libfmt-dev libgmock-dev libgrpc-dev libgrpc++-dev libgrpc++1.51 libgtest-dev \
libhiredis-dev libjemalloc-dev libkrb5-dev libldap2-dev librdkafka-dev librocksdb-dev libmongoc-dev libnghttp2-dev libpq-dev libpugixml-dev \
libprotoc-dev libssl-dev libsasl2-dev libyaml-cpp-dev netbase ninja-build postgresql-15 postgresql-server-dev-15 protobuf-compiler-grpc python3-dev \
python3-jinja2 python3-protobuf python3-venv python3-voluptuous python3-yaml redis-server zlib1g-dev