日進日歩で日々進捗

非情報系学生による技術の備忘録。進捗出していきたい

システムコール SELECT(2)について

### SystemCall SELECT(2)とは
端的にいうと、ある特定のプロセスがブロッキングすることなく、多数のI/Oストリーム(ファイルディスクリプタ)を監視することを可能にするシステムコールである。


### どこで使われているの?有名なアプリケーションは?
Webエンジニアの人であれば、多くの人が使ったことがある(少なくとも知っているであろう)nginxや、RDBMSのpostgresなどでも使われています。

通常、webサーバーでは多数のリクエストを処理しますが、その際各ソケットに対して、プロセスを割り当てた場合、メモリの使用量やコンテキストスイッチの負荷が大きくなってしまいます。
そこで、1プロセスで、複数のファイルI/Oを管理する仕組みが導入されました。それが、select(2)です。
ただ、selectにも課題はあり、1プロセスで多くのソケット(File Descriptor)を監視できる一方、そのプロセスには原則1つのプロセスしか割り当てられないので、負荷の高い処理が要求された場合、その処理がCPU時間を占有してしまい、結果としてそれぞれのsocketに対するレスポンスが遅くなってしまいます。


### epoll(7)やpoll(2)との違いは??
T.B.C .

CloudFrontとAnsibleで自動でサクッとRuby on Railsの本番環境を作ってみる

CloudFrontとAnsibleで自動でサクッとRuby on Railsの本番環境を作ってみる

タイトルの通りですが、CloudFrontとAnsibleを使ってRuby on Railsの本番環境を作ってみましょう。
なぜ、Ruby onRailsなのかというと、比較的初学者がRailsの学習を行なっていることが多く、本記事の対象読者とマッチしていると考えているからです。
別にDeep Learningの実行基盤であってもいいのですが、ansibleの使い方さえマスターしてしまえば、動かすアプリケーションは関係ないと考えているので、今回はRailsの本番環境での構築を行います。

Ansibleで構築を目指すインフラ構成

オンプレミスでも良いのですが、今回はAWSクラウド環境を使ってRuby on Railsの実行環境を構築します。具体的に使うミドルウェアは下記の通りです。

unicornRailsを動かすRack準拠のアプリケーションサーバ、nginxはアプリケーションサーバー手前に配置するリバースプロキシ、redisは軽量データをメモリ上にキャッシュしておくインメモリストレージとして利用します。

AWSインフタ構成

図はあとで掲載します。
VPCにPublic SubnetとPrivate Subnetを用意し、Public SubnetをAnsible クライアント兼踏み台サーバーとして使います。

なぜAnsibleクライアントをAWSのEC2に配置するのか

初学者のころ、Ansible関係の記事ではほとんどAnsibleを操作するためのサーバーをEC2上に構成している例で、不思議に思ったことがあったのですが、
別にLocal環境であっても構いません。つまり、今この記事をみているMac環境でAnsibileを動かして、EC2のサーバー上に本番環境を構築することもできます。
ただ、これは勉強目的であれば構わないのですが、実際に商用として動かすマシンとしてはセキュリティ的に問題があります。
具体的には、アプリケーションの実行プロセスが動いているマシンは、任意のIPアドレスからアクセスできるようなネットワーク環境におくことは脆弱性に繋がるので、
基本的には外部のリクエストを受け付ける踏み台サーバーを用意し、その踏み台サーバーからのアクセス以外を弾くというようなポリシーでの運用がデファクトとなっているからです。
このあたりの考え方は、踏み台サーバー関係で検索すれば出てくると思います。

Ansibleとは

名前は聞いたことがある人も多いとは思いますが、Chefなどと同様インフラの構成管理ツールになります。
例えばアプリケーションを開発するとき、ミドルウェアやライブラリをインストールする環境構築をまず行うと思いますが、構成管理とはこの環境構築のことを指します。

このAnsibleを導入することの大きなメリットは、これらの作業を自動化できることになります。
では、自動化すると具体的に何が良いことになるのでしょうか。

環境構築くらい、自動化するまでもなく手動でやっても対した負担ではない、と思う方もいらっしゃるかもしれませんが、確かに1台のマシン、自分が普段開発用に使っているマシン1台のインストールでは対して手間は変わらないでしょう。
しかし、それが10台、20台..... 100台、 1000台となったらどうでしょう。
もうお分かりの通り、人間の手作業で行うことは不可能です。
そして、実際このように1000台以上のサーバーに対して同じ構成のミドルウェア・ライブラリをインストールすることは往々にしてあるのです。(大規模なサーバークラスタの構築など)

ansibleは、そのような大規模なインフラの構築をする際に、自動化する機能を提供してくれます。
また、大規模なサーバークラスタの導入以外のシチュエーションとして、新しく加入した開発メンバーの開発環境の構築等もansibleの文法でインフラ構成を記載したマニュフェストファイルを配布することで、簡単に開発環境のインストールを行うことができます。

Ansibleのメリット

Ansibleが提供する自動化のメリットとして、

  • 多くのマシンに同時に同じ環境をインストールすることができる
  • 人間の手が介在しないので、ライブラリのバージョンの間違いなどの人為的ミスが起こらない

などのメリットが挙げられます。


以下の項目は T.B.C

DockerとAnsibleの違いは?

Ansibleのインストール

CloudFrontでのAWS環境構築

Ansible Playbook構築

Webプログラマが理解したいHook(フック)とは

フックとは

フックは、プログラマの中にプログラマが独自の処理をインクルードできる処理のことである。
普段ライブラリを使っている側からしたら、当たり前のように使っている機能であるが、実装にどういう箇所で使われているか、その内部実装に関しても解説していきたいと思う。
(ライブラリを実装する側ではないと、作ることのない機能であるけど)

実際にフックが使われている場面

下記のような場面で実際にフックが使われている。Webエンジニアでもイメージがしやすいようにかいた。

・Vue.jsのインスタンスライフサイクルフック
railsのコールバック関数
wordpressのフック
・CPUの割り込み処理など
RDBMSのトリガー処理等


フック処理は、現在の情報科学の多くの文脈で登場するので、エンジニアは積極的に理解しておきたい概念だと個人的には思う。

フックメソッドを実装する代表的なデザインパターン

TemplateMethod




後日追記

Unicord, ASCII文字コードを勉強してみた

文字コードとは??

今回、PostgresQLの開発をするにあたり、文字コードの理解が曖昧と感じる場面が多くあったので、調べたことをまとめたいと思っています。

参考にした記事
gihyo.jp

よく耳にする文字コード

ASCII, UTF-8, Unicord, Shift-JISなどの言葉を耳にしたことがあるエンジニアは多いと思います。これらが文字コードになります。

一番最初にできた文字コードがASCIIコード

ASCIIコードは最初にできた文字コードで、これは7bitと先頭1bitをチェックサムに用いた合計1byteの文字コードで、これらはアルファベットを表すのに使われました。
しかしこれらのASCIIコードで表すことができるのは、2^7 = 128種類しかりません。これでは、英語に発音記号をつけるような欧州文字や漢字、日本語を表現することはできません。
そこで、後に2byteの文字コードが誕生しました。
そこで、日本語に対応する文字コードや、欧州文字、漢字に対応する文字コードが誕生します。

Unicordが国際対応した文字コード

これらの2byte文字コードの誕生によって、多くの国の文字が表現できるようになりましたが、そこで問題になるのが互換性の問題です。
同じバイト列でも文字コードが違うとまったく違う文字列に複合されてしまうので、互換性が非常に大事になってきます。
ここで、国際的な文字コードの規格として誕生したのが、Unicordです。これによって、世界的に文字コードを統一して扱えるようになりました。

PostgreSQLをソースコードからビルドして起動する

PostgreSQLの開発をするにあたって、Ubuntu18.04 LTSで環境構築した手順をまとめます。

qiita.com

こちらのQiitaを参考にしました。

ソースコードのインストール

PostgreSQL: Downloads
こちらのサイトより、適宜自分の環境のソースコードをダウンロードできます。
自分は、Ubuntu18.04でpostgreSQLの18.04の環境構築を行いましたが、適宜自分の構築したいバージョンに置き換えて実行してください。

$ mkdir ~/src && cd ~/src
$ wget "http://ftp.postgresql.org/pub/source/v9.4.0/postgresql-9.4.0.tar.gz"
$ tar xvzf postgresql-9.4.0.tar.gz
$ cd postgresql-9.4.0
$ ./configure
$ make
$ make check
$ sudo make install


./configureで様々なオプションを設定することができますが、今回はデフォルトの設定のままで行います。

ブラウザのHTTPリクエストからレスポンス取得までのHTTPパケットの流れ詳解

Webエンジニアやインフラ系のエンジニアであれば当たり前だと思いますが、HTTPリクエストを送ってからレスポンスを取得するまでの流れをパケットレベルでの理解は、なかなか怪しいと思ったので、このさい復習してみることにしました。

大前提

普段自分が利用しているインターネットのパケットがどういう風に流れているかを理解することは、大前提大事だと思います。
イーサネットやIPパケットのフォーマットも、発表されてからもう30年も立っている歴史の長い技術ですし、今後もこれらの技術を前提に新しい技術が作られることを踏まえると、理解することは当然意味があると思います。
また、普段アプリケーションばかり書いているエンジニアもここら辺のことは、理解せずに普段仕事をしている人も多いと思います、、

使用した環境・ツール

HTTPリクエストのパケット解析: レイヤー2(EtherNet ||)

EtherNet ||のフレームは以下の5つで構成されています。

f:id:low_programing:20191014204215g:plain
https://www.infraexpert.com/study/ethernet4.html

ethernetでは、Ethernetペイロードと呼ばれるデータの部分の大きさの最大値が決まっており、(これをMTU(Maximum Transmission UNit)という)、通常46バイト~1500バイトになっています。
これ以上のデータを送る場合、通常はIPのレイヤーでデータが分割されて、データが送信されることになります。

イーサネットフレームのFCSとは?

FCS(Frame Check Sequence)とは、イーサネットレイヤーのチェックサム機構になります。通常、宛先/送信元 MACアドレスEthernetペイロード、タイプに対してチェックサムの計算が行われます。このデータに対する同様の計算を、受信側、送信側のNICで行うことで、データが正しく送受信できているかを保証することになります。

IPレイヤーだけでなく、イーサネットのレイヤーでもチェックサムの機構あるんですね。
ちなみに、このチェックサムの演算、およびFCSヘッダーの付加はNICドライバ内で行なっています。
ちなみに、ここら辺はNICドライバの内部実装になるので、ネットワークエンジニアでもほとんど扱うことはないかと思います。

MACアドレスとは?

HTTPリクエストのパケット解析: レイヤー3 (IP)

IP ヘッダーは以下のようなヘッダー群で構築されています。

f:id:low_programing:20191014205849g:plain
https://www.infraexpert.com/study/tcpip1.html

IPヘッダー

4bitのフィールドで、ここではIPパケットのバージョンを示しています。
通常、IPv4が使われるので、この値は0100担っています。一部、IPv6の通信では、0110になっています。

IPヘッダー長

IPv4では、この値は5になっています。IPヘッダーの長さは、20byteで、この数字は32bit単位で表記されているので、20 * 8 / 32 = 5となります。・

IPフラグメンテーションとは?

IPフラグメンテーションとはどのようなものでしょうか。
これは先ほど書いたMTUが密接に関わってきます。

HTTPリクエストのパケット解析: レイヤー5 (アプリケーションレイヤー)

[後日追記します]

なぜRailsのWebアプリにunicornが必要なのか

Railsを開発、デプロイする際に、unicornだのpumaだのwebrickだのpassengerだの、、
HTTPサーバーであることは理解しているものの、なぜこれが必要なのか理解していない人も多いのではないでしょうか。
私自身も理解が深いわけではありませんが、現在の段階で自分の理解をまとめてみたいと思います。かなり殴り書きです。

疑問1: なぜ、nginxとunicornを同時に使うのか。片方じゃダメなのか

結論から言うと、nginxがあってもなくてもいいですが、unicorn及びRackに対応しているHTTPサーバーは必須、となります。
なぜかというと、Rails単体ではHTTPサーバーの機能を持っていないため、RackというRailsが対応している規格に対応したwebサーバ0がRailsと紐づいている必要性があるからです。
ではunicornなどのアプリケーションサーバーが必要な理由はそれで良いとして、なぜnginxが必要なのでしょうか。

Railsのよくある構成で使われているnginxはリバースプロキシである

今回はHTTPサーバーがunicornであると言う前提で、話を進めます。
よくある本番環境で動かしているRailsアプリケーションの基本的な構成は下記のようだと思います。

f:id:low_programing:20191010172133p:plain
https://medium.com/@yucunli/a-gentle-intro-to-deploy-rails-application-with-unicorn-c99fee29cb6e

一番手前にnginxがあり、その下にunicornがあり、さらにその下にRailsアプリケーションが動いていて、一番奥にBackendDB(psqlmysql, redis ... etc)があります。

この画像だと、Railsアプリどこにあるの??と思う人がいるかもしれませんが、unicornのworkerプロセスの中でRailsが動いているイメージです。
これを聞くと、あれ??じゃあunicornRailsが一体化しちゃってるじゃん!と思うかもですが、それが正しい認識です。

先ほども言ったようにRails自体は、HTTPサーバーの機能を持っておたず、ただのバックエンドのデータをいい感じにまとめて、データをよしなに加工するだけのアプリケーションなのです。そして、先ほど登場したRackと言うインターフェイスに対応したイベントから呼ばれる前提で設計されています。
よくRailsとはWebアプリケーションフレームワークと言われていますが、正確にはHTTPサーバーとしての機能は提供しておらず、あくまでHTTPリクエストが入ってきた前提で動くものです。

nginxの役割はリバースプロキシ

上の図のように、nginxが外側のリクエストを受け付けています。具体的には、TCP/IPプロトコルで入ってきたリクエストをUNIXドメインソケット通信(同一PC内での通信)に変換して、unicornに渡しています。
unicornはnginxから渡ってきたHTTPリクエスト情報rackのインターフェイスに変換して、Railsに渡しています。

じゃあ、なぜnginxが必要なの?と言う話ですが、これはnginxの特徴として、大量で軽量な処理をさばくのに、向いているアーキテクチャであるからです。
ノンブロッキングI/Oというアーキテクチャで実装されています。詳しくはググるとたくさん出てきますが、難しいです。

Railsアプリケーションは自体はRubyで実装されており、バイナリ形式で動くnginxと比較してもパフォーマンスが良いとはいえません。
なので、簡単な処理、例えばファイルシステムに保存されている画像形式のファイル(静的ファイル)をHTTPレスポンスとして返す、などの簡単な処理においては、railsに処理を渡さない方が、高速にレスポンスを返すことができるからです。

nginxが得意な領域はnginxが引き受けて、面倒な処理が入ってくるようなリクエストの場合だけrailsに渡す、と言うやり方が一番システムとしてパフォーマンスが出るわけです。

逆に、多くのリクエストを同時にさばけるようなパフォーマンスが求められていないような場合は、nginxは必要ありません。
ローカル開発環境では、nginxを起動せずにwebrickやpumaでRailsサーバーを立ち上げていると思いますが、それが理由です。

unicornの内部アーキテクチャ・実装、特徴など

unicornは、基本的にマルチプロセス、ブロッキングI/Oのアーキテクチャを採用しています。
つまり、各プロセスが担当する処理が終わるまでプロセスが解放されないため、大量にリクエストがきた場合、リクエストの待ち行列が増えることになり、パフォーマンスが悪化します。このアーキテクチャはWebサーバーのAppacheと同等のものです。

こちらの記事が大変参考になりました。
blog.willnet.in