サーバ - REST API
概要
REST APIは、HTTPプロトコルを使用して、クライアントとサーバ間でリソースのやり取りを行うインターフェースである。
主なHTTPメソッド (GET、POST、PUT、DELETE) を使用して、リソースの取得、作成、更新、削除等の操作を実現する。
サーバの実装において、Linuxディストリビューションに必要なプログラム言語とフレームワークをインストールする。
一般的な選択肢としては、PythonのFlaskやDjango、Node.jsのExpress、RubyのRails、JavaのSpring Boot等がある。
以下の例では、PythonのFlaskを使用した基本的なREST APIを構築している。
from flask import Flask, request, jsonify
app = Flask(__name__)
# データストアの代わりとなる簡単なディクショナリ
books = {}
@app.route('/api/books', methods=['GET'])
def get_books():
return jsonify(books)
@app.route('/api/books', methods=['POST'])
def add_book():
book = request.get_json()
books[len(books) + 1] = book
return jsonify({'message': 'Book added successfully'})
if __name__ == '__main__':
app.run(debug=True)
セキュリティでは、APIキーの実装、HTTPS通信の設定、入力データのバリデーション、SQLインジェクション対策等を行う必要がある。
また、認証・認可の仕組みとして、JWTトークンやOAuth2.0の実装も検討する必要がある。
パフォーマンスとスケーラビリティでは、キャッシュの実装 (例: Redis)、データベースの最適化 (インデックス設計等)、ロードバランサの設置が重要である。
また、コンテナ化 (Podman等) やオーケストレーション (Kubernetes) の導入も検討する。
APIのドキュメント化も重要な要素となる。
Swagger / OpenAPIを使用することにより、APIの仕様を明確に定義して、自動的にドキュメントを生成することができる。
これにより、他の開発者がAPIを理解および使用することが容易になる。
モニタリングとログ収集の設定において、PrometheusやGrafanaを使用してメトリクスを収集・可視化して、
ELKスタック (Elasticsearch、Logstash、Kibana) でログを収集・分析することにより、APIの健全性を監視することができる。
REST APIサーバを構築・運用する場合は、以下に示す事柄に注意する。
- 定期的なバックアップの実施
- セキュリティアップデートの適用
- アクセスログの監視
- レート制限の実装
- 適切なエラーハンドリング
- データベースの最適化
- APIドキュメントの作成と管理
サーバ環境のインストール
まず、システムを更新を行う。
# RHEL sudo dnf update # SUSE sudo zypper update # Raspberry Pi sudo apt update sudo apt upgrade
次に、Linuxサーバに必要な基本環境をインストールする。
# RHEL sudo dnf install curl wget git # SUSE sudo zypper install curl wget git # Raspberry Pi sudo apt install curl wget git build-essential
開発言語とフレームワークの選択
Python + FastAPIを使用する場合
Pythonと仮想環境をインストールする。
# RHEL sudo dnf install python3 python3-pip python3-virtualenv # SUSE sudo zypper install python3 python3-pip python3-virtualenv # Raspberry Pi sudo apt install python3 python3-pip python3-venv
Pythonと仮想環境の設定を行う。
これにより、プロジェクトごとに独立したPython環境を作成することができる。
python3 -m venv <作成する仮想環境のディレクトリ名>
Pythonの仮想環境をアクティベートする。
source venv/bin/activate
必要なPythonライブラリをインストールする。
pip install fastapi uvicorn sqlalchemy
※注意
venv/bin/activateスクリプトを~/.profileファイル等に設定することは非推奨である。
- activateスクリプトは相対パスで動作するため、フルパスで指定する必要がある。
- 常に特定の仮想環境がアクティブになってしまうため、他のプロジェクトで異なる仮想環境を使用する場合に問題が発生する。
- シェルのセッションごとに自動的にアクティベートすると、どの環境で作業しているのか理解しにくい。
代替案として、以下に示すような方法が推奨される。
以下に示すような方法ならば、必要な時のみ仮想環境をアクティベートすることが可能なため、柔軟な運用が可能になる。
特に、複数のプロジェクトを扱う場合は、2番目や3番目の方法が便利である。
# 方法 1
# エイリアスを設定する方法 (~/.profileファイル等に記述)
alias activate-myproject='source <activateスクリプトのパス>'
# 方法 2
# プロジェクトディレクトリに入った時のみ自動的にアクティベートする方法 (~/.profileファイル等に記述)
function cd()
{
builtin cd "$@"
# プロジェクトディレクトリに入った時のみ仮想環境をアクティベート
if [ -d "venv" ]; then
# 既に仮想環境がアクティブでない場合のみ
if [ -z "$VIRTUAL_ENV" ]; then
source venv/bin/activate
fi
fi
}
# 方法 3
# direnvのような専用ツールを使用する方法
# プロジェクトディレクトリの.envrcファイルに記述
layout python3 # Pythonの仮想環境を自動的に管理
Node.js + Expressを使用する場合
Node.jsをインストールする。
Node.jsの詳細なインストール手順は、インストール_-_Yarnを参照すること。
プロジェクトディレクトリを作成する。
mkdir <任意のディレクトリ 例: ~/my-api> cd <作成したディレクトリ 例: ~/my-api>
プロジェクトに必要なJavaScriptライブラリをインストールする。
npm init npm install express body-parser cors
データベースの設定
PostgreSQLを使用する場合
PostgreSQLをインストールする。
# RHEL sudo dnf install postgresql libpq5 # SUSE sudo zypper install postgresql libpq5 # Raspberry Pi sudo apt install postgresql postgresql-contrib
データベースを作成する。
sudo -u postgres createdb <任意のデータベース名> sudo -u postgres createuser <任意のデータベースユーザ名>
MariaDBを使用する場合
MariaDBのインストール
MariaDBをインストールする。
# RHEL sudo dnf install # SUSE sudo zypper install # Raspberry Pi sudo apt install mariadb-server mariadb-client
MariaDBのセキュリティを設定する。
- rootパスワードの設定
- anonymousユーザの削除
- リモートrootログインの禁止
- テストデータベースの削除
- 権限テーブルの再読み込み
sudo mysql_secure_installation
MariaDBへログインして、データベースの作成、ユーザの作成、権限の設定を行う。
sudo mysql -u root -p # データベースとユーザの作成 CREATE DATABASE <<任意のデータベース名>; CREATE USER '<任意のデータベースユーザ名>'@'localhost' IDENTIFIED BY '<データベースユーザのパスワード>'; # 権限の設定 GRANT ALL PRIVILEGES ON <<任意のデータベース名>.* TO '<任意のデータベースユーザ名>'@'localhost'; # 設定を反映 FLUSH PRIVILEGES;
MariaDB向けPythonドライバをインストールする。
pip install mysql-connector-python sqlalchemy mysqlclient # または pip3 install mysql-connector-python sqlalchemy mysqlclient
必要な場合は、MariaDBのパフォーマンスの最適化を行う。
[mysqld]
# バッファプールサイズ (利用可能メモリの50-70[%]程度)
innodb_buffer_pool_size = 1G
# クエリキャッシュ
query_cache_type = 1
query_cache_size = 128M
# 接続数の設定
max_connections = 150
# スレッドキャッシュ
thread_cache_size = 8
# テーブルオープンキャッシュ
table_open_cache = 2000
# InnoDBの設定
innodb_file_per_table = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 16M
バックアップ設定
バックアップスクリプトを作成する。
#!/usr/bin/env sh
BACKUP_DIR="<任意のバックアップディレクトリ 例: /var/backups/mysql>"
BACKUP_FILE="<任意のバックアップファイル名 例: myapi_db>"
DATE=$(date +%Y%m%d_%H%M%S) # 日付を付加する場合
BACKUP_FILE="$BACKUP_DIR/$BACKUP_FILE_$DATE.sql" # バックアップファイルのパス
# バックアップの作成
# 例: mysqldump -u myapi_user myapi_db > $BACKUP_FILE
mysqldump -u <データベースユーザ名> <データベース名> > $BACKUP_FILE
# 圧縮
gzip $BACKUP_FILE
# 30日以上前のバックアップを削除 (オプション)
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
MariaDBのメンテナンス
定期的な実行が推奨されるメンテナンスを行う。
-- テーブルの分析
ANALYZE TABLE items;
-- テーブルの最適化
OPTIMIZE TABLE items;
-- インデックスの使用状況確認
SHOW INDEX FROM items;
-- スロークエリの確認
SHOW VARIABLES LIKE '%slow%';
SHOW VARIABLES LIKE '%long%';
APIの基本的な実装
Python + FastAPIを使用する場合
以下に示すソースコードはサーバサイドであり、APIサーバ内部で動作する部分である。
したがって、クライアントが直接触れる部分ではなく、APIサーバの内部実装として機能する。
クライアントは以下に示すソースコードを意識することなく、定義されたAPIエンドポイントを通じてデータの操作を行うことが可能となる。
PostgresSQLを使用する場合
# main.pyファイル
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
@app.get("/items")
async def read_items():
return {"items": []}
@app.post("/items")
async def create_item(item: Item):
return item
MariaDBを使用する場合
以下の例では、APIサーバがMariaDBと通信するための設定を行う。
- データベースへの接続設定
- コネクションプールの管理
- セッション管理の設定
# database.py
# SQLAlchemyを使用したデータベース接続設定
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "mysql+mysqlconnector://myapi_user:your_password@localhost/myapi_db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
pool_size=5,
max_overflow=10,
pool_timeout=30,
pool_recycle=1800
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
以下の例では、データベースのテーブル構造をPythonのクラスとして定義している。
- データベーステーブルの構造定義
- SQLAlchemyによるORMマッピング
- テーブルのカラム定義とその制約
# models.py
# モデルの定義例
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func
from database import Base
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
description = Column(String(500))
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
これらをREST APIサーバとして使用する場合、以下に示すような構成となる。
# main.py (APIエンドポイントの定義)
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from . import models, database
app = FastAPI()
# データベースセッションの依存性注入 (DIコンテナ)
def get_db():
db = database.SessionLocal()
try:
yield db
finally:
db.close()
# APIエンドポイント例
@app.post("/items/")
def create_item(name: str, description: str, db: Session = Depends(get_db)):
db_item = models.Item(name=name, description=description)
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
REST APIサーバの情報を取得する場合は、クライアントからREST APIエンドポイントに対してHTTPリクエストを送信する。
# クライアントからのAPIリクエスト例
curl -X POST "http://your-server/items/" \
-H "Content-Type: application/json" \
-d '{"name": "テスト項目", "description": "説明文"}'
HTTPS対応
Let's Encryptを使用する場合
Certbotをインストールする。
# RHEL sudo dnf install ca-certificates python3-certbot # SUSE sudo zypper install python3-certbot python3-certbot-nginx # Raspberry Pi sudo apt install certbot python3-certbot-nginx
SSL証明書を取得する。
sudo certbot --nginx -d <ドメイン名 例: example.com>
リバースプロキシの設定
Nginxを使用する場合
# /etc/nginx/sites-available/myapiファイル
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Systemdサービスファイルの作成
# /etc/systemd/system/<任意のサービス名>.serviceファイル
[Unit]
Description=<サービスファイルの説明>
After=network.target
[Service]
User=<実行する任意のユーザ名>
WorkingDirectory=<REST APIのプロジェクトディレクトリ 例: /home/<ユーザ名>/my-api>
ExecStart=/<uvicorn実行ファイルのパス> main:app --host <ホスト名またはIPアドレス> --port <ポート番号>
# 例: ExecStart=/home/myapi_user/my-api/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
ファイヤーウォールの設定
Firewalldの場合
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload
UFWの場合
sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable
監視とログ管理
PrometheusのGithubにアクセスして、Prometheusをインストールする。
ダウンロードしたファイルを解凍する。
tar xf prometheus-<バージョン>.tar.gz
Grafanaをインストールする。
sudo apt install apt-transport-https sudo apt install software-properties-common sudo wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
MariaDBを使用している場合は、MySQLエクスポータ (Prometheus向け) をインストールする。
sudo apt install prometheus-mysqld-exporter
MySQLエクスポータ (Prometheus向け) の設定ファイルを作成する。
sudo vi /etc/default/prometheus-mysqld-exporter
# /etc/default/prometheus-mysqld-exporterファイル # 例: DATA_SOURCE_NAME="myapi_user:your_password@(localhost:3306)/" DATA_SOURCE_NAME="<データベースユーザ名>:<データベースユーザのパスワード>@(localhost:<MariaDBのポート番号>)/"
CI/CD環境の構築
GitLabを使用する場合
# .gitlab-ci.ymlファイル
stages:
- test
- deploy
test:
stage: test
script:
- pip install -r requirements.txt
- pytest
deploy:
stage: deploy
script:
- ssh user@yourserver 'cd /path/to/api && git pull && systemctl restart myapi'
only:
- master