日報 2018年7月8日 - LightningNetworkを動かしてみる
雑な日報を始めてみます
なんか記事にするまでもない雑多なあれこれを、だからといって放っておくと1ヶ月後に「あれ、この1ヶ月なにやってたんだっけ?」となりがちなんで雑でも記録に残すことにしました。
LightningNetwork
LightningNetworkはbitcoinのレイヤー2技術
lndはLightningNetworkの実装の一つ
これにそってローカル環境にdocker-composeでlightning networkクラスタを作ってみた
github.com
lightning networkはバックエンドにbitcoinノードが必要でこのlndのチュートリアルではbtcdが採用されている。別にbitcoindでもいいみたい。
aliceとbobのlndノードを立ててchannelをつないで送金できた。
次にチュートリアルにはないけど直接channelが開いていないノード間での送信、multihop paymentと言うらしい、をやってみるがだめだった。
alice <--> bob <--> jon の状態でaliceからjonに支払いたいんだけど経路が見つからないというエラーが返ってくる
{ "payment_error": "unable to find a path to destination", "payment_preimage": "", "payment_route": null }
色々調べたけど解決できず。
そもそもlightningnetworkの基礎知識がないのかと思い、これを読んだ。
LND Overview and Developer Guide
まぁ基礎的なことしか書かれてなくてmultihopのルーティングがどうやっているのかは不明。
paymentしたいdestinationとのルートが存在するかどうか確認する方法がある気がするのでまた今度調べる @todo
Flareというルーティングアルゴリズムについての記事を見つけた。
Flare: Lightning Networkルーティングアルゴリズム - United Bitcoiners
まぁ何言っているかわからないのでこれもおいおい調べる @todo
ルーティングアルゴリズムの性能次第で以下のようなものも実現できます。
- 1取引あたり0.1円未満
- 全世界で1秒間に1000万取引以上
- トランザクション手数料が0.000001%未満
自分はLNのマイクロペイメントに着目していたけどたしかにLNの場合はオンチェーンと違ってノードが増えれば増えるほど処理のキャパが上がるよな〜と。
オンチェーンの場合は増すのはセキュリティだけどレイヤー2になると分散の強みを得るの面白い
grep -A
このオプションは知らなかった
grep -A 1 word
でwordにヒットした行とその次の1行をアウトプット
grep -10 word
でヒットした行の前後10行もアウトプット
リンク
- btcdのAPIドキュメント btcd/json_rpc_api.md at master · btcsuite/btcd
- lndのAPIドキュメント LND gRPC API Reference
所感
雑やな〜・・でも雑じゃないと続かないんで・・
PHPのsessionファイルの生成場所、中身、有効期限など
PHPでセッションを開始すると$_SESSIONに値を出し入れできますが実態はsessionファイルに物理的に書き込まれています。*1
中身見たことなかったのでちょっと調べました。
sessionファイルの場所
生成場所の優先順位
sess_v4vqefhjjllja1bqsabekihpc4
みたいな感じでsess_xxxxxxxxxxxxxx
という名前のファイル名で保存されます。
sessionファイルの中身
試しにこれを実行すると
<?php session_start(); $_SESSION['hoge'] = 'hoge'; $_SESSION['huga'] = 'huga';
自分の環境だと/tmp/sess_v4vqefhjjllja1bqsabekihpc4
が生成されました。中身をみると
cat /tmp/sess_v4vqefhjjllja1bqsabekihpc4 // 結果 hoge|s:4:"hoge";huga|s:4:"huga";
ぱっと見配列をserialize()
したものっぽいですが微妙に違います。
session_encode
という関数を使ってエンコードしているようです。
PHP: session_encode - Manual
デフォルトのアンシリアライズの方法は PHP が内部的に実装しているものであり、 unserialize() とは違います。 シリアライズの方法は、session.serialize_handler で設定できます。
phpinfoを確認するとsession.serialize_handlerにはphp
と設定されていました。これがデフォルト値です。試しにphp_serialize
に変えてphpを再起動してsessionファイルを確認してみると
cat /tmp/sess_v4vqefhjjllja1bqsabekihpc4 // 結果 a:2:{s:4:"hoge";s:4:"hoge";s:4:"huga";s:4:"huga";}
とまぁおなじみのシリアライズされた文字列になりました。ハンドラがデフォルトのphp
だと$_SESSIONの中で数値のインデックスや特殊文字 (| や !) を含む文字列のインデックスが使えません。
sessionファイル名とセッションID
リクエストヘッダーを見るとv4vqefhjjllja1bqsabekihpc4
というセッションIDを送っています。
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip, deflate, sdch Accept-Language:ja,en-US;q=0.8,en;q=0.6,de;q=0.4,fr;q=0.2,ko;q=0.2 Cache-Control:max-age=0 Connection:keep-alive Cookie:PHPSESSID=v4vqefhjjllja1bqsabekihpc4 // ←! Host:local.example.com Upgrade-Insecure-Requests:1
クライアントから送信されたセッションIDとsessionファイルの関連付けをどうやっているのかというとそのままセッションIDに接頭辞としてsess_
をつけているだけだけでした。セッションIDをそのままファイル名に使っているというのはなにやら不安な気持ちになりますね。
session_regenerate_id ()
を実行するとセッションIDが新しく変わるので新しいsess_xxxxxx
が生成され、クライアントに新しいセッションIDを返します。
有効期限
セッションスタート時にgcが走ります。
sessionファイルのうち生成からsession.gc_maxlifetime
秒経っているファイルが対象で、session.gc_divisor
分のsession.gc_probability
の確率で削除が実行されます。
*1:デフォルトでは。
phpenvで複数バージョンのPHPを同時に利用する
1つのvagrantで複数のPHPを同時に利用できるようにします。この記事では5.6.23と7.0.0を共存させます。
CentOS6.5でapache2.4.6+PHP-FPMの構成です。
phpenv,php-buildはインストールされている前提で始めます。
起動スクリプトの用意とListenするポートの設定
php5.6.23のインストール
$ phpenv install 5.6.23 [Info]: Loaded extension plugin [Info]: Loaded apc Plugin. [Info]: Loaded composer Plugin. [Info]: Loaded github Plugin. [Info]: Loaded uprofiler Plugin. [Info]: Loaded xdebug Plugin. [Info]: Loaded xhprof Plugin. [Info]: php.ini-production gets used as php.ini [Info]: Building 5.6.23 into /home/vagrant/.phpenv/versions/5.6.23 [Downloading]: https://secure.php.net/distributions/php-5.6.23.tar.bz2 [Preparing]: /tmp/php-build/source/5.6.23 [Compiling]: /tmp/php-build/source/5.6.23 [xdebug]: Installing version 2.3.3 [xdebug]: Compiling xdebug in /tmp/php-build/source/xdebug-2.3.3 [xdebug]: Installing xdebug configuration in /home/vagrant/.phpenv/versions/5.6.23/etc/conf.d/xdebug.ini [xdebug]: Cleaning up. [Info]: Enabling Opcache... [Info]: Done [Info]: The Log File is not empty, but the Build did not fail. Maybe just warnings got logged. You can review the log in /tmp/php-build.5.6.23.20160911071038.log [Success]: Built 5.6.23 successfully. // 設定ファイルを作成 $ cp /home/vagrant/.phpenv/versions/5.6.23/etc/php-fpm.conf.default /home/vagrant/.phpenv/versions/5.6.23/etc/php-fpm.conf
サービスに追加
// 起動スクリプトを移動 sudo cp /tmp/php-build/source/5.6.23/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm-5.6.23 // 実行権限付与 sudo chmod 775 /etc/init.d/php-fpm-5.6.23 // システム起動時に自動起動するように設定 sudo chkconfig php-fpm-5.6.23 on // 確認 sudo chkconfig --list | grep php-fpm php-fpm-5.6.23 0:off 1:off 2:on 3:on 4:on 5:on 6:off
ポートを変更
FPMはデフォルトで9000番のポートをリッスンするようになっていますが、複数バージョンのPHPを共存させる場合はこのポート番号をずらして運用します。
vi /home/vagrant/.phpenv/versions/5.6.23/etc/php-fpm.conf listen = 127.0.0.1:9000 ↓ listen = 127.0.0.1:9001
同じことをPHP7.0.0で繰り返します。ポートは9002にします。
vi /home/vagrant/.phpenv/versions/7.0.0/etc/php-fpm.conf listen = 127.0.0.1:9000 ↓ listen = 127.0.0.1:9002
注)etc/php-fpm.confにlistenの記述がない場合は、etc/conf.d/www.confにあると思うのでそちらを変更してください。
vhostsの設定
あとはvhostsの設定でドメインごとにfcgiに投げるポート番号を対応させればOKです。
- local.php5 → 9001番ポート
- local.php7 → 9002番ポート
## PHP5.6.23 <VirtualHost *:80> ServerName local.php5 #DocumentRoot /var/www/html/php5 <FilesMatch \.php$> SetHandler application/x-httpd-php </FilesMatch> ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9001/var/www/html/php5/$1 <Directory "/var/www/html/php5"> AllowOverride All Options -Indexes +FollowSymLinks Require all granted </Directory> </VirtualHost> ## PHP7.0.0 <VirtualHost *:80> ServerName local.php7 <FilesMatch \.php$> SetHandler application/x-httpd-php </FilesMatch> ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9002/var/www/html/php7/$1 <Directory "/var/www/html/php7"> AllowOverride All Options -Indexes +FollowSymLinks Require all granted </Directory> </VirtualHost>
ブラウザから見てみる
それぞれのパブリックにphpinfo()スクリプトを置いて、
あとがき
個人的なポイントとしては起動スクリプトにバージョン名を入れてわかりやすくしたところですかね。あと試してないですがunixソケットで通信する場合はphp-fpm.sockをphp-fpm-なんとか.conf
で複数つくれば良いのかなぁ。それはまた今度。
ajaxのエラー(500 internal server error)の解決方法
ajax通信処理でこの画像のように500 (Internal Server Error)
と表示さる場合、js側ではなくサーバープログラムが間違っています。
どういうエラーなのか確かめるにはデベロッパーツールのNetworkタブを確認します。サーバーからレスポンスを受け取った以降のすべての通信内容がNetworkに表示されます。
エラーで返ってきた通信(ここはではajax.php)をクリックして右に出てくるパネルのPreviewタブを見るとエラー内容を確認できます。
500エラーで返ってきているのにPreviewタブに何も表示されない場合は、サーバー側でエラーを出力させない設定になっている可能性があります。
その場合は該当のPHP処理の先頭で
<?php ini_set('display_errors',1);
と記述してみてください。
エラー内容を確認して原因が明らかな場合はそこを修正しておしまい。ただどこがバグの原因かわからない場合はデバッグしてく必要があります。
ひとつはprintデバッグです。printやvar_dumpを挟んでデバッグします。直後にexitかdieさせればprint内容もNetworkタブのPreviewタブで確認できます。
もう一つデバッガーです。ajaxリクエストもステップ実行が可能なのでそれで確認していきます。
以上、ajaxエラーの原因突き止め方法でした。
余談)google search consoleで検索ワード見てると「ajax 500 internal server error」とかでこのブログが表示されている回数が多かったのでちょっと書いてみました。
Ansible+Vagrant(ansible_localプロビジョナ)でPHPのローカル開発環境を作る
注意
この記事ではVagrant1.8から導入されたansible_localプロビジョナを使用していますが、現在インストールされるansibleのバージョンが上がってしまいVagrant側がまだそれに対応していません。 issueにも上がっていますので近々対応されるかも・・?
なので現状うごきません・・!
進展があったら追記していきます。
追記(2016/06/18)
追記時点でVagrantのバージョン1.8.4が公開されており、このバージョンでは上記の不具合は解消されております。
使い方
git clone git@github.com:egapool/centos66-ansible.git cd centos66-ansible vi Vagrantfile // プライベートIPとsynced_folderを各自の環境に合わせて編集
vhosts.confに記載する内容のベースとなる情報(ドメインとパブリックディレクトリのパス)を予め与えると自動でvhostsに記述されます。 下の例のようにapache_vhosts_sslに記載するとSSL自己証明書の自動生成も行います。
(略) - role: apache apache_vhosts: - {servername: "local.example.com", documentroot: "/var/www/html/example/public"} apache_vhosts_ssl: - {servername: "local.sslexample.com", documentroot: "/var/www/html/sslexample/public"} (略)
準備が整ったら
vagrant up
基本的にはvagrant up
するだけですむようにしています。
デフォルトで以下の構成が構築されます。
Ansible
Ansibleとは構成管理ツールの一つです。類似のツールにchef,puppetなどがあります。構成管理ツールとはサーバーにインストールするミドルウェアや設定ファイルの内容などをテキスト(Ansibleではplaybookと呼びます)に書き起こし、それを元に状態を再現することを簡単にするためのツールです。これによって、大規模なサーバー管理が簡単になったり、サーバーに入り内容を確認しなくてもどんな状態かわかるなどのメリットがあります。
必要なもの
Ansibleを使用するにあたってローカルPC(ホスト側)にはVagrant以外なにも必要ありません。Ansibleすらインストールする必要がありません(後述します)。
事前知識
Ansibleの基本はこのチュートリアルをこなせば一通り学べると思います。1時間もかかりませんのでこれからAnsibleをやってみたいという方は是非チャレンジしてみてください。
Ansible チュートリアル | Ansible Tutorial in Japanese
こちらの書籍はAnsibleを使う上で必要十分な知識が載っています。値段もお買い得なのでおすすめです。
Amazon.co.jp: 入門Ansible eBook: 若山史郎: Kindleストア
また、playbookはYAMLで書きます。YAMLの文法はとても簡単なので一瞬で習得できます。こちらをオススメします。
Rubyist Magazine - プログラマーのための YAML 入門 (初級編)
ansible_localプロビジョナについて
Vagrant1.8からansible_localプロビジョナが追加されました。このプロビジョナを使うと、ゲストOSの方にansibleをインストールさせてから、ゲストOSがローカルに対してplaybookを実行します。今回はこれを使います。
roleついて
roleとはミドルウェアをインストールするひとまとまりの単位です。例えば「httpdのrole」や「phpのrole」など。一つのrole内でソフトウェアのインストールから設定ファイルの編集、再起動などを行わせます。roleはそれぞれ独立しています。
roleのディレクトリ配置(apacheの例)
└apache/ ├ defaults/ # roleで使う変数のデフォルト設定を置くディレクトリ │ └ main.yml ├ handlers/ # ハンドラータスクを置くディレクトリ │ └ main.yml ├ tasks/ # タスク用ディレクトリ。roleを実行するとこのmain.ymlが呼ばれる │ └ main.yml ├ templates/ # 設定ファイルなどのテンプレートを置くディレクトリ ├ meta/ │ └ main.yml # メタ情報を置くディレクトリ └ vars/ └ main.yml # 変数を置くディレクトリ
playbook全体のディレクトリ配置
playbook/ ├ hosts # インベントリファイル。今回はローカル開発環境ということでほぼ必要なし ├ site.yml # playbookの起点になる処理 └ roles/ # 各roleを配置する ├ commaon/ ├ repositries/ ├ git/ ├ apache/ ├ phpenv/ ├ mysql/ └ redis/
site.ymlについて
--- - hosts: localhost # hostsは何か指定しないといけない connection: local # localに対してplaybookを実行させる become: yes # コマンドをsudoユーザーで実行するかどうか roles: - role: common # 各ロールディレクトリのtasks/main.ymlを実行する - role: repositries ・ ・
apache
httpでもhttpsでもplaybook実行時にservernameとdocumentrootの組を配列で指定すると指定した分だけdocumentrootディレクトリの作成と対応するvhostの設定が記述されます。 また、httpsの場合はservernameごとに秘密鍵とサーバ証明書を生成します。
SSLの仕組みと各種必要なファイルの説明はこのポストが詳しいです。
オレオレ証明書をopensslで作る(詳細版) - ろば電子が詰まっている
apacheロールでは以下のモジュールをepel-httpd24レポジトリを使ってインストール。
- httpd24-httpd
- Apache HTTP server(2.4)
- httpd24-httpd-devel
- httpd24-mod_ssl
- opensslに対するインターフェース
- openssl
git
ソールからビルド。
git/defaults/mains.yml
でダウンロードするソースのバージョンを指定します。
phpenv
- CHHを使用
- php-fpmを使用
- PHPの各バージョンをビルドすると
/tmp/php-build/source/5.6.xx/sapi/fpm/init.d.php-fpm
に起動スクリプトが吐き出されるので/etc/init.d/
へコピーして、そのあとchkconfigに登録します
mysql
repositries
各種リポジトリをyumでインストールします。また、すべてのサードパーティ製リポジトリのenabledを0にします。
repositries roleはtask/main.yml以外使用しません。インストールするリポジトリを変数ファイルに切り出しても良いかなと思いましたがそんなにころころ変わるものでもないのでひとまずこれでいきます。