AWSを用いてrailsアプリをデプロイするプロセスを頑張って噛み砕いてみるvol.3

## 近況報告
体調管理の話
　私は体調管理の一環として２月から食事時間を制限しています。具体的には，1日のうち，食事しない時間を１４時間程度連続でとる，それだけです。理由は，毎度運動している消化器官を休ませることで身体のストレスを軽減させ，消化のパフォーマンスをあげるためです。詳しくは某メンタリストのyoutubeをどうぞ。いつか体調管理の項でも作って書いていこうと思います。

# 今回の目標
・インフラ整備での各アクションの言語化
・コードを単に打っているだけでは理解しきれないし，他に応用できないので言語化して整理
・AWSでアカウント作成，ほか諸々の準備は割愛してターミナルでの操作をメインに

## 大まかな流れ
・アプリケーションサーバーの仕組み
・Webサーバーの準備
・Githubからクローンを受け取る

## 事前準備
[vol.1](https://qiita.com/aaabb6211/items/6194fa53f29061dc5444)
[vol.2](https://qiita.com/aaabb6211/items/2f8c5034b791767dee7a)

### アプリケーションサーバーの仕組み
vol2まででアプリケーションをEC2の土地に勧請*することができました。次はアプリケーションを起動の準備を行います。

ローカル環境でrailsの起動は，以下の「rails s」で済みました。しかし，本番環境ではもう少しステップを踏みます。

```
$rails s
=> Booting Puma
=> Rails 5.0.7.2 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.0 (ruby 2.3.1-p112), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```
勧請* ー 神仏の分霊を他の地域に受け入れること。ここではGithubにある母体からEC2に機能そのままにクローンしたことです。


ここで，サーバーの構造を確認しましょう。⇨[参考](https://qiita.com/takahiro1127/items/fcb81753eaf381b4b33c)
◆**webサーバー**
HTTPをもとに、HTMLや画像の情報を返してくれるもの、イメージ的には静的なwebサイトで提供されるもの(HTML,CSS,Javascriptなど)が、このwebサーバーで返される。
◆**アプリケーションサーバー**
送られてきたリクエストに対して、rubyやphpなどを実行して、処理をした結果を静的な要素に変換してwebサーバーに返すためのもの。

　ユーザーはリクエストした内容をwebサーバーを通してでしか得ることができません（今のこの画面もwebサーバーが表示しています）。というのもrubyもGOも処理を行う言語であって，HTMLのように表面を作成する言語ではないからです。つまり，**webサーバーはアプリケーションサーバーを内包している**と考えられます（厳密には違うっぽい）。

railsなら，
viewの情報をもとにリクエストを行い
⇨Webサーバーはアプリケーションサーバーに何をやるべきか指示（HTTPメソッド）
⇨アプリケーションコントローラーはその指示から処理を実行
⇨処理結果をViewでWebサーバーに返す

内包されていますね。

　これは本番環境でもローカル環境でも同じ構造なのですが，ローカル環境に関しては，本番環境のような何十万単位のアクセスはなく，webサーバーにかかる負荷が小さいので，**railsのポテンシャルだけで情報を捌くことができてしまいます**。railsは[rack](https://railsguides.jp/rails_on_rack.html)によってもとから小さなwebサーバーがアプリケーションサーバーを覆っているからです。

　たしかにrackだけで本番環境で運営できますが，たとえば新幹線と自転車，どちらが同じ時間で多くの人を東京から大阪に運べるかと言えば，新幹線ですよね。アプリケーションを公開するのは多くの人に利用してもうためなので，多くの人が不便なく利用できるように負荷に強いwebサーバーを用意します。

###Webサーバーの準備
　webサーバーにはNginxを利用していきます（搭載については後述）。Nginxは、フリーかつオープンソースなWebサーバであり処理性能・高い並行性・メモリ使用量の小ささに焦点を当てて開発されています。ただ，Nginxはrailsを直接つなぐことができないのでつなぎ役として，ここでwebサーバー**「Unicorn」**が登場します。

　実際UnicornもWebサーバとしても起動するので、UnicornとRackだけでRailsを動かすことも可能です。しかし、大量のリクエストの負荷には耐えきれないのでwebサーバーと組み合わせましょう。Unicornのドキュメントでもnginxと組み合わせることを推奨しているため、Unicornを選ぶ際にwebサーバも自然とNginxを選ぶことになります。

Unicornを使うメリット
　（＊）プロセスがmaster1つと複数個のworkerに別れていて、masterがソースコードを保持しており、実際に動くのはmasterのプロセスのコピーを持ったworkerプロセス群である。Nginxがつなぐのはmasterのみなので、masterは各workerにロードバランサーのような形で負荷分散をしながらリクエストを送ることができる。余談ですが，masterを止めればworkerも自動的に落ちます。

プロセス
　プロセスとは、PC(サーバ)上で動く全てのプログラムの実行時の単位です。プログラムが動いている数だけ、プロセスが存在しています。例えばテキストエディタを起動する時、テキストエディタ用のプロセスが生み出されます。１つのプログラムに対してプロセスが多いほど処理の速度は早くなります。

gemfile経由でインストールします。

``` gemfile.
group :production do ←本番環境のみ適用
  gem 'unicorn', '5.4.1'
end
```
config以下にunicorn.rbを作成し編集

```unicorn.rb
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)

#アプリケーションサーバの性能（ワーカープロセスの数）を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定（ユニコーンでこの中のファイルを動かしますよー）
working_directory app_path

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"

#ポート番号を指定
listen 3000

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"

#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60

#以下解読できませんでした，今後の課題とします

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
```
これでUnicornの設定は一通り済みました。

＊任意
以下の記述をコメントアウト⇨JSの「｀」を用いた記述に対応していないため。

```environments/production.rb
~省略~
# config.assets.js_compressor = :uglifier
~省略~
```
###Githubからクローンを受け取る

```EC2.
$ sudo mkdir /var/www/
$ sudo chown ec2-user /var/www/ ←ec2userに権限変更。githubに認証を受けているため
$ cd /var/www/
$ git clone https://github.com/user name/クローンしたいリポジトリ.git

Cloning into '***'...
remote: Enumerating objects: 599, done.
remote: Total 599 (delta 0), reused 0 (delta 0), pack-reused 599
Receiving objects: 100% (599/599), 19.8 MiB | 9.1 MiB/s, done.
```
chownってchange ownerの略かな（適当）
これでアプリケーションサーバー内に自分のポートフォリオを呼び込むことができました。

注意
・Unicorn導入はクローンする前でも問題ないです。
・もしユニコーンの設定をGithubにpushせずクローンした場合はwwwフォルダに移動して「rm -rf リポジトリ名」で削除して作り直しましょう。

##終わりに
　カリキュラムを初めて見たときは呪文の羅列で何をしているのかわからなかったけど，改めて見てみると理解できる点が多くありますね。テック受講生は，まず理解できなくてもいいから大枠だけ捉えていつか見直した時に理解しようと努めると理解が進むと思います。

次回，railsを本番環境で起動します。

少しでも参考になったらLGTM，アドバイスもお待ちしています！