HTTP/2というプロトコルを用いるとネットの通信が速くなる場合があるようで

HTTP/1.0

HTTPはブラウザ(Webクライアント)とWebサーバ間でデータをどのようにやり取りするかを取り決めたプロトコル

HTTPにもバージョンがあり、1つのリクエストに対して1つのレスポンスを返す、という形式の通信を取るのがHTTP/1.0(までのバージョン)。筆者がHTTPと聞いてイメージする通信はこれだった。

図に表すとこんな感じ。

 

f:id:rinda_1994:20210226104321p:plain

上図は、まずはHTMLを、次に画像を、最後にCSSを取得するためのリクエスト/レスポンスが順次生成されている流れとなる。

 

HTTP/1.1

HTTP/1.0ができた3年後、1999年にHTTP/1.1が生まれる。

もう22年も経つわけだが、現在も尚多くのサーバ-ブラウザ間で使用されているらしい。

 

HTTP/1.1ではHTTPパイプラインという機能が実現されており、ブラウザから同時に複数のリクエストを出すことができる。

図に表すとこんな感じ。

 

f:id:rinda_1994:20210226105338p:plain

 

しかしHTTPパイプラインには、「Webサーバはレスポンスをリクエストの順番通りに返さないといけない」というネックがある。上図で言うと、例えばindex.htmlが非常に重たいリソースだと、A.jpgとB.cssのレスポンスもその分遅れてしまう。

この欠点のため、HTTP/1.1を使用しているほとんどのブラウザでは、結局HTTP/1.0と同様にWebサーバに対してリクエストを1つずつ送る通信形態を取っている。

 

ちなみに上図ではTCPコネクションは1つのていで作成しているが、記事によってはリクエスト/レスポンスごとにコネクションを確立すると説明しているものもあった。この辺はちょっとよく分からないが・・・。

リソースをそれぞれ取得するごとにスリーハンドシェイクするのは悠長だし、おそらくは1ページ表示する上で必要なTCPコネクションは1度で良いのだとは思う。

 

HTTP/2とは

HTTP/2は複数のリクエスト/レスポンスを並行して処理することができるプロトコル

1つのコネクションの中でストリームという仮想的なコネクションを複数用意することができ、このストリームの中でリクエスト/レスポンスのやりとりを行う。HTMLのリクエスト/レスポンスはHTMLのストリームで処理され、CSSやJSも然り、という形。

 

そして各ストリームはそれぞれ独立した存在なので、結果複数のリクエスト/レスポンスを並列して処理することができる。

図にするとこんな感じ。各ストリームを同時に処理している。

 

f:id:rinda_1994:20210226112359p:plain

 

またストリームの優先制御が可能なので、HTTPパイプラインと違いどのレスポンスを優先して返すかを規定することができる。この規定はブラウザ側で行う。

 

例えばリソースの中でも画像などはWebサーバからのダウンロードが完了しきっていなくてもページで表示(レンダリング)され始めるようだが、優先制御を使えば、画像用ストリームの優先度を下げてHTMLなどの必須なリソースをなるべく速く取得するということも可能らしい。

 

HTML/2.0には他にも、リクエストされていないCSSなどのリソースをサーバーがクライアントに勝手に送信してくれる「サーバープッシュ」機能もある。これによりリクエストの数を減らせるので、ページが表示されるまでの合計通信時間を短縮できる場合があるようだ。

 

なんか便利なんだろうなとは思いつつ、このサーバープッシュで分からなかったことが1つあった。「Webサーバはどういう基準でリクエストを勝手にブラウザに返すのか」ということ。

おそらくはサーバ側で各リソースの依存関係を決めておいて、依存関係にあるリソースA・BのうちAにだけリクエストが来て、規定した時間Bにリクエストが来なかった場合はBのレスポンスも返す、という仕組みではないかなとは想像したけど、まあちょっとよく分からない。

 

そもそも並列処理できる上に、優先制御やサーバープッシュの機能もあるため、HTTP/2.0ではそれ以前のHTTPに比べて通信の速度が上がる場合も多いらしい。

 

だがそれが見込めないケースもあるよう。

例えば表示すべきリソースが少ない場合などでは、そもそもサーバへのリクエストの数が少ないので並行処理できてあまり意味がなくなる。 

 

まとめていないまとめ

インターネットの通信を速くするのっていろんなやり方があるんだなと感じた。

HTTP/2については、言い方変かもだけど、大通信(コネクション)の中に小通信(ストリーム)が複数ある、みたいな認識を持った。

 

参考

普及が進む「HTTP/2」の仕組みとメリットとは | さくらのナレッジ

HTTP/2の特徴 HTTP/1.1との違いについて | REDBOX Labo

【図解】HTTP/2って?HTTP/1.1との違いと導入メリット・課題まとめ | カゴヤのサーバー研究室

Docker環境でbyebugを使用するための方法

Railsデバッグをしようと思い少しできるまでに時間がかかったので、備忘録として記録。

 

該当のコントローラにbyebugを記入し、"byebug ファイル名"でデバッグ用画面を開くところまではいけた。

しかしnやsで実行をしようとすると uninitialized constant ApplicationController というエラーが出た。

 

「ApplicationControllerという初期化されていない定数があります」ってどういうこと・・・そもそもApplicationControllerって定数だったっけ・・・などと思いつつそのエラーメッセージで調べるも、有力な情報は出てこず。

 

このエラーメッセージから離れてbyebugについて調べていると、どうやらDocker環境でbyebugを使用するには追加設定が必要であることがわかった。具体的には、docker-compose.ymlに以下の設定を追記する。

 

# docker-compose.yml
services:
  web:
    stdin_open: true  #追加箇所
    tty: true #追加箇所

 

この後"docker-compose up --build -d"でDockerを再ビルドしたところ、Docker環境でも正常にbyebugを使えるようになった。

stdin_openが標準入力に関するステータス、ttyが標準出力を自端末にアタッチするかのステータスで、これらをtrueにすることでコンテナ内の標準出力とDockerを起動しているターミナルの標準出力が接続されるらしい。

要はDockerの出力結果がターミナルにも表示されるようになるということだが・・・標準入力・出力については正直よくわかっていない。なかなか手強そうな概念だった。以下の記事が良さそうだったので、今度時間のある時に読み込んでみよう(せんやつ)。

 

qiita.com

 

 

で、本題からは逸れるが、なぜかデバッグ用画面でこちらが入力している文字が表示されない。

正直打ち込む内容は"n"とか"s"とか"p 変数名"くらいの文字なので別に画面に表示されなくてもなんとかなるのだが、やはり不便だと感じはじめ、pry-byebugでは同じ事象が発生しないのであればpry-byebugに乗り換えようと思う。

 

参考

Docker環境でByebugを使う方法 - logicoffee プログラミング勉強日記

Docker環境でByebugを使う方法 | ゆみしん夫婦のブログ

 

インターネット向け通信にプロキシはどのように関わるのか(Webexの特殊な例付き)

プロキシって?

家庭などのPCでインターネットに接続する際はあまり関係のない話だが、いち企業がインターネットに通信をしたいとなるとプロキシ(サーバ)を設置することは多い。

プロキシとは、端末からインターネット網の間に、通信の中継役として設置されるサーバのこと。

プロキシを設置すると例えば以下のいいことがある。

  • 一度アクセスしたサイトへの再アクセスが速くなる
    これまでにWebサーバから受信したWebサイトの情報をプロキシ自身のHDDに一時保存(≒キャッシュ)することで、次そのサイトにアクセスする際は、Webサーバまで行かずともプロキシが情報を持っているので、通信の高速化を図ることができる
  • 特定のURLをアクセス禁止にできる
    有害とされるWebサイトやアドレスをリスト化し、それに該当する通信は全て遮断などすることで、セキュリティを脅かすコンテンツにそもそもアクセスできないようにできる

メリットは他にもあるが一旦はこんな感じ。

 

プロキシを経由した場合の端末からインターネットまでの通信

プロキシ経由のインターネット通信は図に表すとこんな感じ。

 

f:id:rinda_1994:20210219203509p:plain


①〜④がどのような通信なのかを、上図で各機器に振っているIPも交えて説明する。

 

①PC→プロキシサーバ

ブラウザでプロキシ用の設定を行っている場合は、PCからのパケットの宛先IPはWebサーバではなくプロキシサーバとなる。

送信元IP:172.10.1.1 宛先IP:10.1.1.1 

 

②プロキシサーバ→DNSサーバ

パケットの中にあるHTTPリクエストデータの中には「最終的な目的地であるWebサーバのドメイン」が入っている。で、そのドメインをWebサーバのグローバルIPに名前解決するため、プロキシサーバはDNSサーバにパケットを投げる。

送信元IP:10.1.1.1 宛先IP:10.2.1.1  

 

DNSサーバ→プロキシサーバ

DNSサーバはドメインから名前解決をし、WebサーバのIPをプロキシサーバに教える。

送信元IP:10.2.1.1 宛先IP:10.1.1.1

 

④プロキシサーバ→Webサーバ

Webサーバに向けてパケットを飛ばす。

送信元IP:10.1.1.1 宛先IP:143.100.25.2

 

Webexアプリの通信の場合

という感じでプロキシ周りの通信は通常上図の流れになるのだが、今日たまたまWebexアプリの通信について調べている中で、少し仕様の異なる話に出会った。

一応説明しておくと、Webexはオンラインミーティング用のアプリ。

 

Webexアプリの通信は図に表すとこんな感じらしい。

 

f:id:rinda_1994:20210305205158p:plain
 

 

この図ではDNSサーバは省略している。


ざっくり言うと、まずPCは通信①を走らせ、自身のローカルIPやグローバルIPCiscoクラウドにあるサーバに伝える。そして参加者全員のPCがサーバに自身の情報を伝えて会議の準備ができ次第、映像音声データを届ける用途で通信②が走る。

 

通信①と②の特徴はそれぞれ以下のように説明できる。

 

通信①
  • オンラインミーティングを始めるまでの準備のための通信
  • プロキシを経由する
  • アプリケーション層はHTTPSトランスポート層TCP

 

通信②
  • 映像音声データを届けるための通信
  • プロキシを経由しない
  • アプリケーション層はSRTP、トランスポート層UDP

 

要は同一アプリの通信だが、タイミングによってプロキシを経由するものとしないものがあるということ。

 

通信②はインターネットに出るにもかかわらずプロキシを経由しない。これは参考リンクにあるCiscoのページに書いてあったことだ。その理由については、はっきりとした理由を見つけられなかったので以下勝手な推測だが・・・

 

OSやブラウザのプロキシ設定を有効にすると、中にドメインの情報を含む通信はプロキシを経由してインターネットに出る仕組みになっているのだと思う。

で、ドメインを持つ通信のアプリケーション層はHTTP/HTTPSであるため、アプリケーション層がSRTPの通信②はドメインを持たない。なので通信②はプロキシを経由せずにインターネットに出ていくのではないかと考えている。

 

 

まとめていないまとめ

調べているとMicrosoftTeamsやGoogleMeetsなど、メジャーなWeb会議ツールは大体WebRTCという仕様に則って作られていて、上図のWebexの通信フローとおおよそ似た形式になっているようだった。調べてたら少し面白さを感じたので、またいつか時間があったらWebRTCでWeb会議アプリ作りたいと思う。

参考

【図解】httpプロキシサーバの仕組み(http GET/https CONNECTメソッド)や必要性・役割・メリットデメリット・DNSの名前解決の順序 | SEの道標

WEBプロキシとは? 仕組みや機能・メリットについて解説|セキュリティコラム|株式会社網屋

プロキシサーバとは

https://www.cisco.com/c/dam/m/ja_jp/solutions/webex/pdf/guide-to-using-webex-safely.pdf

 

IPv6による通信がIPv4よりも速いことが多い理由

IPv6の通信がIPv4よりも速いと言われる所以を2点整理した。

正確でない情報もあるかと思うので、発見した方はご指摘いただけると幸いです。

IPoEによるインターネット通信がPPPoEよりも通信が速い

PPPoEおよびIPoEとは、家庭や企業からインターネットに接続するまでの通信方式のこと。PPPoEはIPv4およびIPv6に対応しているが、現在一般的に用いられてるのはIPv4版。一方でIPoEはIPv6のみに対応している。

 

結論を言うと、PPPoEを用いたIPv4通信よりも、IPoEを用いたIPv6通信の方が速いことが多いらしい。以下でもう少し詳細に説明する。

 

PPPoEは、ユーザの持つCPEルータからNGN網(NTTの回線)にある網終端装置までトンネルを張り、その後はISP(インターネットサービスプロバイダ)のネットワークを経てインターネット網に接続する方式。 本筋ではないので、CPEルータ、トンネルとはどういうものか、などの説明はここでは省略する。

 

図に表すとこんな感じ。

 

f:id:rinda_1994:20210216191443p:plain

どうやら上図にも描いている「網終端装置」とやらがポイントらしく・・・。PPPoEの場合は必ずここを通過するので、ここが混み合っていると通信が遅くなる。

 

対してIPoEはこの網終端装着を通過しない通信方式。

流れとしては、CPEルータからPPPoEで張ったようなトンネルなしでNGN網を通過したのち、VNEネットワークの入り口にあるホームゲートウェイを経由し、VNEネットワークを通ってインターネットまで出る。
VNEネットワークはISPが他事業社から借りているIPv6ネットワークで、正確ではないが、PPPoEの図で出てきた「ISPネットワークのIPoE版」というイメージ。

 

図に表すとこんな感じ。

 

f:id:rinda_1994:20210218103804p:plain


IPoEの場合は以下の理由でPPPoEよりもインターネット通信がスムーズになっている。

  • NGN網とVNEネットワークの間にあるホームゲートウェイが複数存在し、NGN網を通過してきたパケットがそれぞれのホームゲートウェイに分散されるため、輻輳が起こりづらい
  • ゲートウェイルータの通信容量が網終端装置よりもかなり大きい(こちらのスライド3枚目にて、見方が正しければ通信容量は10倍)
  • 単純にIPoEユーザの数がまだ少ないため、ホームゲートウェイに集まるパケットの絶対量が少ない

 

というような感じで、インターネットに関しては、PPPoEを用いたIPv4通信よりもIPoEを用いたIPv6通信の方が速い場合が多いらしい。

 

※「IPv6通信」というよりも「IPoE通信」が速い場合が多いという話なので、厳密に言うとIPv6であれば必ずしも速度が保証されるわけではない。例えばPPPoEを用いたIPv6通信は従来の速度とおそらくあまり変わらないはず

 

ルータでの処理速度がIPv6の方が速い

ルータによる処理速度はIPv4パケットよりもIPv6パケットの方が速いことから、インターネットに届くまで・返ってきてからの通信時間もより短縮される。

ルータの処理速度がIPv4よりもIPv6の方が速い理由は以下の2つ。

 

  • ルータがチェックすべきヘッダが限定されたため
    IPv6ヘッダの中身は基本ヘッダと拡張ヘッダに分けられるが、拡張ヘッダはオプションという形で必要な場合のみ追加することとなっている。そのためIPv4パケットでは必ずルータが処理する必要のあった項目もIPv6パケットでは基本的にスルーでよいのでルータの処理が速い
  • ヘッダチェックサムフィールドが省略されているため
    IPv4ヘッダには、ヘッダ内の情報が前のルーティングポイントで送信された時と比べて変わっていないかを調べるヘッダチェックサムというフィールドがあるが、IPv6ヘッダではこの項目は省略されている。このフィールドはルータを通過するごとに値が変わるためルータに負荷をかけていたが、省略されたためルータの処理が減っている

 

まとめていないまとめ 

他にも理由を見つけたら追記します。

 

参考 

localhostとアプリケーションサーバとWebサーバと

久しぶりにRailsアプリを開こうとしてlocalhost:3000叩いたら、接続できませんと言われた。結局別のアプリで立ち上げてた、ポート番号8080のサーバをダウンさせた後にRailsのポート番号3000のサーバを計2度立ち上げたら、正常にアプリを開くことができた。

 

ローカルでサーバは普通に複数立てれるっぽいので、この解決法が何か今後の参考となるかはかなり微妙だけれど、解決するまでの過程でlocalhost、Webサーバ、アプリケーションサーバあたりの話を少し調べたので、備忘録として記録する。

 

localhostとは

localhostは自分自身(のPC)を表すホスト名のこと。IPで表すと127.0.0.1で、このIPは自分しかアクセスしないのでプライベートアドレス。

 

ブラウザのアドレスバーにlocalhost:XXXと打ち込むと、自PC内で立ち上げているアプリケーションサーバにアクセスすることができるよう。XXXはポート番号で、Railsアプリではよく3000番を使用するらしい。

ちなみにポート番号は、通信においてアプリケーション層に非カプセル化を行う際、どのアプリケーションに向けて通信を送ればよいかを識別するために用いられるもの。普通であればHTTPは80番、HTTPSは443番だけど、コード側でそこは変えることができる。

 

アプリケーションサーバとWebサーバ

Rails開発においてWebサーバとアプリケーションサーバというのは異なるものであるらしく・・・

 

Webサーバは「ユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムであり、場合によってはRailsアプリケーションにリクエストを投げる」もので、アプリケーションサーバは「Railsアプリケーションを動かしている」ものらしい。

 

開発環境ではWebサーバを使うことは少ないが、本番環境ではWebサーバを立てるのが一般的らしいので、今自分がPC内で立ち上げているRails用のサーバはおそらくアプリケーションサーバだと思う。

ただサーバ立ち上げのために使っているPumaというソフト、調べていると「Webサーバ」と説明されているページと「アプリケーションサーバ」と説明されているページに分かれており、ちょっとこの辺はよく分からない。アプリケーションサーバにWebサーバの機能を組み込める、みたいな話も調べる中で見たので、もしかするとそういう構成になっているのかもしれない。

 

Railsアプリにおける通信の遷移

ブラウザ

→Webサーバ(Nginxなど)

アプリケーションサーバ(Pumaなど)

→Rack

→アプリケーション(自分で書いたコード)にHTTPリクエストが届き、処理される

→行きと逆の順でブラウザまでHTTPレスポンスを届ける・・・

 

本番環境ではおそらく主にこういう通信になっていて、開発環境はここからWebサーバを引いた形になるのかなと。

 

まとめていないまとめ

Rackはボリュームある内容っぽかったので調べるのはまた今度に。

 

参考

127.0.0.1とlocalhostと0.0.0.0の違い - Qiita

Rails開発におけるwebサーバーとアプリケーションサーバーの違い(翻訳) - Qiita

PHP - localhost:8080の8080に意味はあるのでしょうか?|teratail

サーバーレスにおいてロジックとは何か

知り合いのエンジニアの方に教えていただいた、サーバーレスアーキテクチャの構成要素の1つである「ロジック」の内容を整理していきます。この記事で説明する「ロジック」は、一般的にサーバーレスの分野で語られるロジックとは異なる点もあるとのことなのでご了承ください。

ただ筆者の理解不足と知識不足でどう見ても間違ったことを言っている、という箇所もあると思われるので、気づいた方はご指摘いただけると幸いです・・・。

 

サーバーレスアーキテクチャとは

こちらの記事にも書きましたが、まずサーバーレスアーキテクチャとは、サーバーの存在を意識する必要のない構成のことを指すそうです。

 

具体的にどのような構成かというと・・・。

 

構成は大きく、フロントエンド、ロジック、バックエンドの3つの要素に分けられます。

フロントエンドはWebアプリケーションで直接ユーザーの目に触れる部分を指します。例えばメールを送信するアプリで考えると、テキストを入力するスペースや送信ボタン、文字の大きさを変えるボタンなど、ユーザーが直接見て操作できる部分は全てフロントエンドに該当します。

それに対してバックエンドとは、Webサーバーやデータベース、およびその辺りで行われる処理のことを指します。

 

ロジックとは

上記のフロントとバックエンドは一般的にもよく聞く概念だと思われます。

ではロジックとはどういったものなのでしょうか。

ロジックとは、フロントからバックエンドまでの処理(機能)を1つのライブラリにまとめたものになります。ここにはフロントからバックエンドまでのデータ通信もその役割に含まれます。

なので例えば、「テキストを暗号化してサーバに送る」というロジックがあったとすると、①テキストを暗号化する機能、②暗号化されたテキストをサーバに送信する機能、③実際にフロントの端末からサーバに向けてデータ通信をする機能の3つが1つのライブラリにまとめられているイメージになります。

 

本来であればバックエンドに通信するまでに行う処理はフロント側のコードで書くものなのですが・・・

 

このようにその処理をロジックという要素に分離することで、フロント側のエンジニアはサービスの見た目に注力したコードを書けるようになります。

厳密にいうと見た目以外にも、ロジックに向けての入力値とバックエンドからの戻り値は意識したコードにする必要がありますが、従来のアーキテクチャと比較すると役割分担をはっきりさせることができるというわけです。

 

またロジックはJSで書かれたコードです。ブラウザからWebサーバにHTTPリクエストを投げた際に、HTMLやフロント用のJSなどと一緒に取得されます。そしてフロントとロジックの接点となるボタンをユーザがブラウザで押すと、ロジックのコードが走り出して色々処理してくれるという流れです。

 

またこれは本筋ではないですが、1つ1つの機能を実現するためにそれぞれ別に作成したJSのコードを1つのライブラリにまとめる処理のことをwebpackと呼ぶとのことです。

 

通信しないロジック

ロジックはフロントからバックエンドまでの処理をまとめたものだと説明しましたが、中には例外的にバックエンドに通信をしに行かないロジックもあります。

例えば、ログインのためメールアドレスを入力する際に、アドレスが特定の形にはまっていない場合などはバックエンドにアクセスしに行く必要がないため、通信をせずにブラウザに「正しいアドレスを入力してください」などと表示をする流れになります。

 

 

CRCとは何か

CRCとは

Cyclic Redundancy Checkの略。あるネットワーク機器から別のネットワーク機器に通信する際、送信データに誤りを検出する符号を付加することで、データの伝送誤りを検出する方法。 

伝送途中のデータはノイズなどが入って破損するケースもあるため、CRCのような方法を用いて受信側の機器でデータの正常性を確認するらしい。

CRCの手順

  1. 送信側の機器で、送信するデータに対して特定の数値を用いて割り算を行う(この割り算とは、2進数で構成されているデータを、同じく2進数で構成されている特定の数で割るということ)。
  2. 割り算した余りの数値を誤りを検出する符号としてデータに付加する。これにより送信データは特定の数値で割り切れる数値となる。
  3. 受信側の機器で、受け取ったデータに対し送信側と同じ特定の数を用いて割り算を行う
  4. 結果が割り切れていればデータは正常に伝送されたと判断されるが、そうでない場合はデータは正常に伝送されなかったと判断され、破棄されたのち送信側の機器にデータの再送を要求する。

FCSとは

Frame Check Sequenceの略。イーサネットフレームに入っている、受信したデータに誤りがないかどうかをチェックするためのフィールド。

上記の手順2でいう「割り算した余りの数値」がこのFCSに入っている。多分。

 

参考

UNIXサーバ CRC(Cyclic Redundancy Check:巡回冗長検査):用語解説 - 富士通

FCS(フレームチェックシーケンス)とは - IT用語辞典 e-Words