REST API構築方針
すでにApache2でメインサービスを運用しているので、REST APIのためにネットワーク設定を変更したくない。ということでApache2でSinatraを動かす。万が一性能面で問題があったらFFI越しにRustの関数を呼び出すつもり。
Sinatraは、Apache2が公開しているメインアプリと並列にREST APIを公開する。以下の形で呼び出せるようにする。
http://localhost:8080/main_app
http://localhost:8080/sinatra
参考資料
- [Installing Passenger + Apache on Ubuntu 18.04 LTS (with APT)]
(https://www.phusionpassenger.com/library/install/apache/install/oss/bionic/) - [Deploying an app to a sub-URI or subdirectory]
(https://www.phusionpassenger.com/library/deploy/apache/deploy/ruby/#deploying-an-app-to-a-sub-uri-or-subdirectory) - その他、同様の挑戦を行われた方々の記事(感謝!)
基本的なインストール
Vagrantで実験環境を構築する。インストール物は以下の通り。
- Apache2
- Ruby
- bundler
- Sinatra
- sinatra-contrib
- Passenger
メモリ1024MBでも動作するなら、本番サーバでの作業負荷も軽いはず。
vagrant ssh
するとエラーになることがあるので、インストール最初にsshの設定を行っている。
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
config.vm.synced_folder "./data", "/vagrant_data"
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
config.vm.provision "shell", inline: <<-SHELL
# To solve the issue of "vagrant@127.0.0.1: permission denied (publickey)."
sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config; \
sudo systemctl restart sshd;
apt-get update
# Installing Apache2
apt-get install -y apache2
# Installing Ruby & sinatra
apt-get install -y ruby
gem install bundler
gem install sinatra
gem install sinatra-contrib
# [Installing Passenger + Apache on Ubuntu 18.04 LTS (with APT)]
# (https://www.phusionpassenger.com/library/install/apache/install/oss/bionic/)
sudo apt-get install -y dirmngr gnupg
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
sudo apt-get install -y libapache2-mod-passenger
sudo a2enmod passenger
sudo a2enmod headers
sudo apache2ctl restart
SHELL
end
インストール物バージョン確認
vagrant ssh
でログインして確認する。パスワードはvagrant
。
Apache2
Apache2のバージョンによって、Apache2の設定(Require all granted
)を書くかどうかが決まる。
$ apache2 -v
Server version: Apache/2.4.29 (Ubuntu)
Server built: 2020-08-12T21:33:25
Ruby
Rubyのバージョンは、ここでは普通に使えることの確認も込めて行っている。
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]
Rubyの実行ファイルの場所をApache2の設定(PassengerRuby /usr/bin/ruby2.5
)に反映することになる。
Ruby Gems (bundler,sinatra,sinatra-contrib)
ここまでの作業でインストールされていたのは以下の通り。
$gem list
backports (3.18.2)
bigdecimal (default: 1.3.4)
bundler (2.1.4)
cmath (default: 1.0.0)
csv (default: 1.0.0)
date (default: 1.0.0)
dbm (default: 1.0.0)
did_you_mean (1.2.0)
etc (default: 1.0.0)
fcntl (default: 1.0.0)
fiddle (default: 1.0.0)
fileutils (default: 1.0.2)
gdbm (default: 2.0.0)
io-console (default: 0.4.6)
ipaddr (default: 1.2.0)
json (default: 2.1.0)
minitest (5.10.3)
multi_json (1.15.0)
mustermann (1.1.1)
net-telnet (0.1.1)
openssl (default: 2.1.1)
power_assert (0.2.7)
psych (default: 3.0.2)
rack (2.2.3, 1.6.4)
rack-protection (2.0.8.1)
rake (12.3.1)
rdoc (default: 6.0.1)
ruby2_keywords (0.0.2)
scanf (default: 1.0.0)
sdbm (default: 1.0.0)
sinatra (2.0.8.1)
sinatra-contrib (2.0.8.1)
stringio (default: 0.0.1)
strscan (default: 1.0.0)
test-unit (3.2.5)
tilt (2.0.10)
webrick (default: 1.4.2)
zlib (default: 1.0.0)
Passenger
Step 3: check installationを参考に、動作確認を行う。
$ sudo /usr/bin/passenger-config validate-install
What would you like to validate?
Use <space> to select.
If the menu doesn't display correctly, press '!'
. ● Passenger itself
○ Apache
-------------------------------------------------------------------------
* Checking whether this Passenger install is in PATH... ✓
* Checking whether there are no other Passenger installations... ✓
Everything looks good. :-)
Apache
をチェックしても認識されない。PassengerからApache2を認識する必要はないので問題ない。
メモリ使用状況を確認する。
$ sudo /usr/sbin/passenger-memory-stats
Version: 6.0.6
Date : 2020-09-03 00:07:00 +0000
--------- Apache processes ----------
PID PPID VMSize Private Name
-------------------------------------
4238 1 153.9 MB 0.5 MB /usr/sbin/apache2 -k start
4483 4238 1268.4 MB 0.7 MB /usr/sbin/apache2 -k start
4484 4238 1268.4 MB 0.6 MB /usr/sbin/apache2 -k start
### Processes: 3
### Total private dirty RSS: 1.78 MB
-------- Nginx processes --------
### Processes: 0
### Total private dirty RSS: 0.00 MB
---- Passenger processes -----
PID VMSize Private Name
------------------------------
4468 389.7 MB 2.3 MB Passenger watchdog
4471 946.3 MB 3.4 MB Passenger core
### Processes: 2
### Total private dirty RSS: 5.64 MB
PassengerがRubyを認識しているかを確認する。Determine the Ruby command that Passenger should useを参考にする。
$ passenger-config about ruby-command
passenger-config was invoked through the following Ruby interpreter:
Command: /usr/bin/ruby2.5
Version: ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]
To use in Apache: PassengerRuby /usr/bin/ruby2.5
To use in Nginx : passenger_ruby /usr/bin/ruby2.5
To use with Standalone: /usr/bin/ruby2.5 /usr/bin/passenger start
The following Ruby interpreter was found first in $PATH:
Command: /usr/bin/ruby
Version: ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]
To use in Apache: PassengerRuby /usr/bin/ruby
To use in Nginx : passenger_ruby /usr/bin/ruby
To use with Standalone: /usr/bin/ruby /usr/bin/passenger start
## Notes for RVM users
Do you want to know which command to use for a different Ruby interpreter? 'rvm use' that Ruby interpreter, then re-run 'passenger-config about ruby-command'.
/usr/bin/ruby2.5
はApache2に設定するので覚えておく。
Sinatraアプリケーション構成
SinatraアプリをApache2+Passenger構成で動作させるには、アプリケーション構成上の注意がある。アプリケーションのディレクトリにpublic、tmpのディレクトリが必要になる。中身は空でよい。
/home/vagrant/sinatra$ $ ls -al
total 32
drwxr-xr-x 4 vagrant vagrant 4096 Sep 3 00:59 .
drwxr-xr-x 7 vagrant vagrant 4096 Sep 3 00:46 ..
-rw-r--r-- 1 vagrant vagrant 79 Sep 3 00:50 Gemfile
-rw-r--r-- 1 vagrant vagrant 83 Sep 3 00:59 app.rb
-rw-r--r-- 1 vagrant vagrant 63 Sep 3 00:31 config.ru
drwxr-xr-x 2 vagrant vagrant 4096 Sep 3 00:31 public
drwxr-xr-x 2 vagrant vagrant 4096 Sep 3 00:31 tmp
source 'https://rubygems.org/'
gem 'sinatra'
gem 'sinatra-contrib'
gem 'rack'
Bundler.require
get '/' do
"I did it my way"
end
require File.absolute_path("app.rb")
run Sinatra::Application
bundlerを実行し、アプリケーションの依存関係を設定する。
~/sinatra$ bundler install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Using backports 3.18.2
Following files may not be writable, so sudo is needed:
/usr/local/bin
/var/lib/gems/2.5.0
/var/lib/gems/2.5.0/build_info
/var/lib/gems/2.5.0/cache
/var/lib/gems/2.5.0/doc
/var/lib/gems/2.5.0/extensions
/var/lib/gems/2.5.0/gems
/var/lib/gems/2.5.0/specifications
Using bundler 2.1.4
Using multi_json 1.15.0
Using ruby2_keywords 0.0.2
Using mustermann 1.1.1
Using rack 2.2.3
Using rack-protection 2.0.8.1
Using tilt 2.0.10
Using sinatra 2.0.8.1
Using sinatra-contrib 2.0.8.1
Bundle complete! 3 Gemfile dependencies, 10 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Gemfile.lockができていればOK。
GEM
remote: https://rubygems.org/
specs:
backports (3.18.2)
multi_json (1.15.0)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
rack (2.2.3)
rack-protection (2.0.8.1)
rack
ruby2_keywords (0.0.2)
sinatra (2.0.8.1)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.8.1)
tilt (~> 2.0)
sinatra-contrib (2.0.8.1)
backports (>= 2.8.2)
multi_json
mustermann (~> 1.0)
rack-protection (= 2.0.8.1)
sinatra (= 2.0.8.1)
tilt (~> 2.0)
tilt (2.0.10)
PLATFORMS
ruby
DEPENDENCIES
rack
sinatra
sinatra-contrib
BUNDLED WITH
2.1.4
Apache2が認識するディレクトリをリンクする。
$ sudo ln -s /home/vagrant/sinatra sinatra
$ ls -l
total 4
drwxr-xr-x 2 root root 4096 Sep 2 23:30 html
lrwxrwxrwx 1 root root 21 Sep 3 00:35 sinatra -> /home/vagrant/sinatra
/etc/apache2/mods-available/passenger.confの設定
[Deploying an app to a sub-URI or subdirectory]
(https://www.phusionpassenger.com/library/deploy/apache/deploy/ruby/#deploying-an-app-to-a-sub-uri-or-subdirectory)を参考に、設定ファイルを編集する。
### Begin
から### End
までは、Passengerのインストールの際に記述されているので、そのあとの設定を追記する。設定項目はPassengerのバージョンによって違ってくるので、バージョンの違うPassengerを使う際は注意。
PassengerRuby
に、rubyの実行ファイルの場所を指定する。
Apache2のバージョンが2.4以上の場合、Require all granted
を記述する。
ひとつだけ、RackBaseURI
と書く場所があるのだが、これが正しい。
### Begin automatically installed Phusion Passenger config snippet ###
<IfModule mod_passenger.c>
PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
PassengerDefaultRuby /usr/bin/passenger_free_ruby
</IfModule>
### End automatically installed Phusion Passenger config snippet ###
PassengerRuby /usr/bin/ruby2.5
RackBaseURI /sinatra
Alias /sinatra /var/www/sinatra/public
<Location /sinatra>
PassengerBaseURI /sinatra
PassengerAppRoot /var/www/sinatra
</Location>
<Directory /var/www/sinatra/public>
Allow from all
Options -MultiViews
Require all granted
</Directory>
Apache2再起動
$ sudo service apache2 restart
念のため、状態を確認する。
$ sudo service apache2 status
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Drop-In: /lib/systemd/system/apache2.service.d
└─apache2-systemd.conf
Active: active (running) since Thu 2020-09-03 00:25:40 UTC; 47s ago
Process: 4811 ExecStop=/usr/sbin/apachectl stop (code=exited, status=0/SUCCESS)
Process: 4817 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
Main PID: 2595 (code=exited, status=0/SUCCESS)
Tasks: 73 (limit: 1152)
CGroup: /system.slice/apache2.service
├─4871 /usr/sbin/apache2 -k start
├─4874 Passenger watchdog
├─4878 Passenger core
├─4892 /usr/sbin/apache2 -k start
└─4893 /usr/sbin/apache2 -k start
Sep 03 00:25:40 ubuntu-bionic systemd[1]: Starting The Apache HTTP Server...
Sep 03 00:25:40 ubuntu-bionic apachectl[4817]: AH00558: apache2: Could not reliably determine the server's fully qualified d
Sep 03 00:25:40 ubuntu-bionic systemd[1]: Started The Apache HTTP Server.
Passengerも起動している。
動作確認
Passengerのエラー画面すら出ないときは、そもそもPassengerまでたどり着いていない。Apache2自体の設定ミスの可能性がある。エラーが出た時は、/var/log/apache2/error.log
を確認する。
課題
勉強不足により、解決していない項目は以下の通り。
- Bundlerを分かってない。
gem install sinatra
しなくていいのでは。 - Sinatraがauto reloadしない。Gemfileに'sinatra-contrib'を書いただけではダメか。
- Sinatraアプリの配置。公開サービスのセキュリティは慎重に。
- Sinatraアプリの認証処理。
- Sinatra(Ruby)からFFI越しにRustの関数を呼ぶ方法。