nginx-quicパッケージをquictlsで作り直した
以前作成したnginx-quicパッケージをquictls版OpenSSLを使うように作り直しました。https://github.com/ryoh/nginx-quic.spec
基本的なコードなどは変わりませんが、以前はBoringSSLでしか対応ができなかったのが、quictls版OpenSSLでも対応できるようになったため、cmakeが必要なくなりビルドが容易になりました。(併せてnginxも最新版に更新)
またOpenSSL 3.0に変えたため kTLS(Kernel TLS)が使えるようになりました。最大で30%程度性能改善がするようです。nginx.conf 周りも更新しているので一応そのまま使えれる状態にしています。
そのほかzstdモジュールにも対応してほしいissueが来ていたので対応しています。が、どうなんでしょうかね。
最後にSPECファイルの抜粋となります。 ビルド方法はOpenSSLをスタティックリンクする方法と同じで違いは特にありません。 nginx-quicのビルドオプションもそのまま使用できます。
%global nginx_quic_commit cd8018bc81a5 %global quictls_version 3.0.2 Name: nginx-quic Version: 1.21.6 Release: 4%{?dist}.quictls%{quictls_version} Summary: A high performance web server and reverse proxy Group: System Environment/Daemons License: BSD URL: https://nginx.org/ Source0: https://hg.nginx.org/nginx-quic/archive/%{nginx_quic_commit}.tar.gz#/nginx-quic-%{nginx_quic_commit}.tar.gz Source100: https://github.com/quictls/openssl/archive/openssl-%{quictls_version}+quic.tar.gz %description nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. %prep %setup -q -n %{name}-%{nginx_quic_commit} pushd .. MODULE="quictls" %{__rm} -rf ${MODULE} %{__mkdir} ${MODULE} cd ${MODULE} %{__tar} -xf %{SOURCE100} --strip 1 popd %build ./auto/configure \ --with-debug \ --with-openssl=../quictls \ --with-openssl-opt="enable-ktls" \ --with-http_v3_module \ --with-stream_quic_module \ %make_build %install [[ -d %{buildroot} ]] && rm -rf "%{buildroot}" %{__mkdir} -p "%{buildroot}" %make_install INSTALLDIRS=vendor unlink %{buildroot}/etc/nginx/koi-utf unlink %{buildroot}/etc/nginx/koi-win unlink %{buildroot}/etc/nginx/win-utf %files %defattr(-,root,root) /usr/sbin/nginx %config(noreplace) /etc/nginx/nginx.conf %config(noreplace) /etc/nginx/mime.types %config(noreplace) /etc/nginx/fastcgi_params %config(noreplace) /etc/nginx/scgi_params %config(noreplace) /etc/nginx/uwsgi_params %changelog
RPMパッケージは以前と同じCoprで公開中です。https://copr.fedorainfracloud.org/coprs/ryoh/nginx-quic/
QUIC対応版nginxが出ていたのでビルドとRPMパッケージを作成した。
先月くらいにnginxのQUIC preview版が出ていましたので今更ながら試してみました。
coprで作ったのでお試しください。(既存のnginxを上書きするのでご注意ください。)
https://copr.fedorainfracloud.org/coprs/ryoh/nginx-quic/
まずnginxをビルドしなければいけませんが、そのあたりはこちらの方の記事の通りに行うだけでできました。
今回は他の環境でも使いやすいようRPMパッケージを作成します。
RPMパッケージ作成についてですが、基本は記事の通りBoringSSLとnginx-quicを使ってビルドするだけです。
ただ、パッケージを作るタイミングでファイルの状態が変わると安定性がないため、HEADからではなくハッシュ値からファイルを取得します。
nginxもBoringSSLもMercurialなので下記のような形でファイルを取得します。
https://hg.nginx.org/nginx-quic/archive/コミットのハッシュ値.tar.gz
ここ以外はあまり変わらず、こんな感じでSPECファイルを作成してRPMパッケージを作るだけです。
(詳細は下記僕のレポジトリをご参照ください。)
https://github.com/ryoh/nginx-quic.spec
Name: nginx-quic Version: 1.19.1 Release: 0%{?dist} Summary: A high performance web server and reverse proxy Group: System Environment/Daemons License: BSD URL: https://nginx.org/ Source0: https://hg.nginx.org/nginx-quic/archive/e533a352d118.tar.gz Source100: https://boringssl.googlesource.com/boringssl/+archive/54858b63c1d886f6c8d903d4a4f594f1485de189.tar.gz %description nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. %prep %setup -q -n %{name}-e533a352d118 pushd .. %{__rm} -rf boringssl %{__mkdir} boringssl cd boringssl %{__tar} -xf %{SOURCE100} popd %build pushd ../boringssl mkdir build cd build cmake3 -GNinja .. ninja cd .. mkdir -p .openssl/lib cd .openssl ln -s ../include . cd .. cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib popd ./auto/configure \ --with-debug \ --with-cc-opt="-I../boringssl/include" \ --with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto" \ --with-http_v3_module \ %make_build %install [[ -d %{buildroot} ]] && rm -rf "%{buildroot}" %{__mkdir} -p "%{buildroot}" %make_install INSTALLDIRS=vendor unlink %{buildroot}/etc/nginx/koi-utf unlink %{buildroot}/etc/nginx/koi-win unlink %{buildroot}/etc/nginx/win-utf %files %defattr(-,root,root) /usr/sbin/nginx %config(noreplace) /etc/nginx/nginx.conf %config(noreplace) /etc/nginx/mime.types %config(noreplace) /etc/nginx/fastcgi_params %config(noreplace) /etc/nginx/scgi_params %config(noreplace) /etc/nginx/uwsgi_params %changelog
あとはこのパッケージに対してファイルを取得して、RPMパッケージをビルドするだけです。
spectool -g -R SPECS/nginx-quic.spec rpmbuild -ba SPECS/nginx-quic.spec
作成したRPMパッケージを他の環境などに持っていきyumコマンドでインストールすれば利用可能です。
yum install RPMS/x86_64/nginx-quic-1.19.1-1.el7.rpm
SRPMをCOPRというサービスに持っていけば、簡易な自分のレポジトリができます。(UbuntuのPPAのような)
https://copr.fedorainfracloud.org/coprs/ryoh/nginx-quic/
yum copr enable ryoh/nginx-quic yum install nginx-quic
最近だとDockerで作ったほうが簡単そうですが、Redhat, CentOSに限ればこういう配布方法もあるよ、という話でした。
Zabbix API で Rust をお試し
公式ドキュメントなどでなんとなく見てたけど、 実際に作ったほうが使い方わかるので、Zabbix API を叩くツールを作りながら勉強
やること
Zabbix API ドキュメント見ると
"user.login"メソッドで認証しトークンを取得してからじゃないと
各種操作ができないようなので、とりあえず以下までを目標とします。
- ZABBIXサーバーにログインする
- ホスト一覧を取得
Zabbix APIはJSON RPCでやり取りするため、JSONとHTTPリクエストが扱えるcrateを使います。
JSONはserde、HTTPリクエストはreqwestが代表的だったのでそれを使用。
Cargo.tomlはこんな感じ
[dependencies] reqwest = { version = "0.10", features = ["json"] } tokio = { version = "0.2", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"
実装
ユーザーログイン
とりあえずログインするまでだったらこんな感じですね。
use serde_json::json; // reqwestが非同期のためasyncにしておく #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // ZABBIXサーバーのAPIエンドポイントの場所 let url = "http://my.zabbix.example.com/api_jsonrpc.php"; // ZABBIX側で作成したユーザー名 let user = "api"; // ZABBIX側で作成したユーザーのパスワード let password = "password"; // JSON-RPCリクエストオブジェクト(idは任意、authはなし) let request = json!({ jsonrpc: "2.0", method: "user.login", params: { "user": user, "password": password }, id: 1, auth: null }); // reqwest クライアントオブジェクトを生成(postでリクエストを送る必要があるため) let client = reqwest::Client::new(); // ZABBIXサーバーにJSON RPCリクエストをPOSTする。 // 正常に疎通できればレスポンスを取得できる(reqwestが標準だと非同期なためawaitで待つ) let response = client.post(url) .json(&request) .send() .await?; // レスポンスボディをJSON形式に直した状態で抽出(serdeでDeserializeできる型ならOK) let content: serde_json::Value = response.json().await?; // レスポンスの値を表示 // sample: // { // "jsonrpc": "2.0", // "result": "0424bd59b807674191e7d77572075f33", // "id": 1 // } println!("{:#?}", content); // --- 本来はレスポンスのidが一致するか、エラーが無かったか確認する --- Ok(()) }
実際にはこのあと content の中のトークンをリクエストのauthにセットして送ることで、各種情報の取得やホストなど監視設定の作成を行うことになる。
次にZABBIXに登録されているホストの一覧を出しましょう。
ホスト一覧の取得
ZABBIXのホスト一覧メソッドは"host.get"となっている。
リクエストの形式はこんな形。
{ "jsonrpc": "2.0", "method": "host.get", "params": { "output": [ "hostid", "host" ], "selectGroups": "extend", "selectInterfaces": "extend", "search": { "host": "server" } }, "auth": "038e1d7b1735c6a5436ee9eae095879e", "id": 2 }
paramsは抽出条件や出力内容をを指定するパラメータ。結構細かく指定できるので詳細は公式ドキュメントを見てもらったほうが良い。
上の場合だと、名前に"server"を含むホストのHostIdとホスト名すべてを取得し、
割り当てられているホストグループとインターフェースを合わせて出力するという内容になる。
さて、コードにすると以下の感じになる。(始めのトークン取得まではそのままなので以降を記載する)
use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let url = "http://my.zabbix.example.com/api_jsonrpc.php"; let client = reqwest::Client::new(); // ・・・先程の、"user.login"処理を行い、トークンを取得する。・・・ // トークンを取得 let token = content["result"].as_str().expect("Can not parse token"); // "host.get"のリクエストを作成 let request = json!({ "jsonrpc": "2.0", "method": "host.get", "params": { "output": [ "hostid", "host" ], "selectGroups": "extend", "selectInterfaces": "extend", "search": { "host": "server" } }, "auth": token, "id": 2 }); // POSTの送信からレスポンス取得、JSON型への変換を一律で行う方法。 let content: serde_json::Value = client.post(url) .json(&request) .send() .await? .json() .await?; // 抽出結果を取得と表示 let hosts = content.as_array().expect("Can not parse array"); println!("{:#}", hosts); Ok(()) }
一応これでcargo runとかで確認可能
このあとはもう少しシンプルに作るために処理をまとめたり型作ったりする予定
同期・非同期のreqwestの使い方
この記事の目的
Zabbix APIを叩く簡単なCLIツールを作ろうと思ったけど、リクエスト作るだけで結構苦労したので次使うときのためにメモ。
※reqwest 0.10.4 を対象
参考
導入
Cargo.tomlの[dependences]にcrateを追加
[dependences] reqwest = { version = "0.10", features = ["json"] } tokio = { version = "0.2", features = ["full"] }
ブロッキングで接続する場合は以下の内容にする
[dependences] reqwest = { version = "0.10", features = ["blocking", "json"] }
GET
基本的な書き方(デフォルト非同期)
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let resp = reqwest::get("https://rust-lang.org") .await? .text() .await?; println!("{:#?}", resp); Ok(()) }
ブロッキングでの書き方
fn main() -> Result<(), Box<dyn std::error::Error>> { let resp = reqwest::blocking::get("https://rust-lang.org").text()?; println!("{:#?}", resp); Ok(()) }
POST
まずはClientを作成してからPOST
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let data = "example data"; let client = reqwest::Client::new(); let resp = client.post("http://example.com/") .body(&data) .send()? .await?; let result = resp.text().await?; println!("{:#?}", result); Ok(()) }
fn main() -> Result<(), Box<dyn std::error::Error>> { let data = "example data"; let client = reqwest::blocking::Client::new(); let resp = client.post("http://example.com/").body(&data).send()?; let result = resp.text()?; println!("{:#?}", result); Ok(()) }
とりあえずここまで
Unity 独自クラスをScritableObjectで編集できるようにする。
ValueObjectライクにクラスを使いたかったので、フィールドを独自クラスにしたかった。
だけど、独自クラスだとインスペクタから値を変えれなかった。 調べると"[Serializable]"を使えばできるようなのでメモ。
下記のように独自クラスに"[System.Serializable]"を割り当てて さらに中のフィールドに"[SerializeField]"かpublicにすれば独自クラスもインスペクタから編集できるようになる。
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class MyClass { [SerializeField] private int id = 0; [SerializeField] private string name = ""; public int Id { get; } public int Name { get; } public MyClass(MyClass object) { Id = object.Id; Name = object.Name; } }
Unity UIを等間隔に配置する。
以下の動画で勉強してたけどUIを等間隔で配置する方法わからなくなったのでメモ
Horizontal Layout Group とりあえずこれを使うことというのは覚えた。 詳細はほかサイトで確認。