【保存版】Sinatraで作る高速なRubyアプリケーション入門 〜設計から本番運用まで完全解説

Sinatraとは?軽量Rubyフレームワークの特徴を解説

Sinatraが生まれた背景とその哲学

Sinatraは2007年にBlake Mizeranyによって開発された軽量なRubyウェブアプリケーションフレームワークです。「最小限の労力で最大限の成果を」という哲学のもと、必要最小限の機能だけを提供し、開発者に大きな自由度を与えることを重視しています。

Sinatraの核となる設計思想は以下の通りです:

  • シンプルさの追求:必要な機能だけを含み、余分な抽象化を避ける
  • 明示的な設計:規約より設定を重視し、コードの意図を明確にする
  • 柔軟性:開発者が自由に技術選択できる環境を提供する
  • 学習コストの最小化:シンプルなAPIで、短時間での習得を可能にする

RailsとSinatraの違いを徹底比較

RailsとSinatraは、それぞれ異なる用途に適した特徴を持っています。

比較項目SinatraRuby on Rails
設計思想最小限の機能提供フルスタック・オールインワン
学習曲線緩やか比較的急
プロジェクトサイズ小〜中規模中〜大規模
規約明示的な設定Convention over Configuration
初期構築時間数分10分程度
ディレクトリ構造自由規約に従った構造
機能の追加必要に応じて手動ジェネレーターで自動生成

Sinatraが特に活躍するユースケース

Sinatraは以下のようなプロジェクトで特に威力を発揮します:

  1. マイクロサービス開発
  • 軽量で起動が高速
  • 必要最小限の機能で構築可能
  • スケーラビリティの確保が容易
  1. APIサーバーの構築
  • シンプルなルーティング設定
  • JSONレスポンスの容易な実装
  • 低いオーバーヘッド
  1. シンプルなWebアプリケーション
  • 静的サイトのサーバーサイド機能追加
  • プロトタイプの急速な開発
  • 単一機能のWebアプリケーション
  1. バックエンドサービス
  • WebHookの受信処理
  • バッチ処理のWeb API化
  • 内部向けツールの開発

これらのユースケースでは、Sinatraの「必要なものだけを含む」というアプローチが大きな利点となり、開発効率と実行性能の両面でメリットを発揮します。

Sinatraで始めるWebアプリケーション開発

開発環境のセットアップ方法

Sinatraの開発環境を整えるには、以下の手順に従います:

  1. Rubyのインストール(バージョン2.6.0以上推奨)
# rbenvを使用する場合
rbenv install 3.2.2
rbenv global 3.2.2

# or RVMを使用する場合
rvm install 3.2.2
rvm use 3.2.2
  1. Bundlerのインストール
gem install bundler
  1. プロジェクトの初期化
mkdir my_sinatra_app
cd my_sinatra_app
bundle init
  1. Gemfileの作成
# Gemfile
source 'https://rubygems.org'

gem 'sinatra'
gem 'sinatra-contrib'  # 開発に便利な拡張機能
gem 'puma'            # 推奨されるWebサーバー
gem 'slim'            # テンプレートエンジン(任意)
  1. 依存関係のインストール
bundle install

基本的なルーティングの書き方

Sinatraのルーティングは直感的で理解しやすい設計になっています:

# app.rb
require 'sinatra'
require 'sinatra/reloader' if development?

# GETリクエストの処理
get '/' do
  'Hello World!'
end

# パラメータの受け取り
get '/hello/:name' do
  "Hello #{params[:name]}!"
end

# POSTリクエストの処理
post '/submit' do
  # リクエストボディのパース
  data = JSON.parse(request.body.read)
  "Received: #{data['message']}"
end

# 複数のHTTPメソッドに対応
route ['GET', 'POST'], '/multi' do
  "Handled #{request.request_method} request"
end

# 条件付きルーティング
get '/admin', :agent => /Firefox/ do
  "Firefox からのアクセスです"
end

テンプレートエンジンの活用術

Sinatraは複数のテンプレートエンジンをサポートしています:

  1. ERBの使用例
# app.rb
get '/erb-example' do
  @title = "ERBのサンプル"
  erb :index
end

# views/index.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= @title %></title>
  </head>
  <body>
    <h1><%= @title %></h1>
    <% ['項目1', '項目2', '項目3'].each do |item| %>
      <p><%= item %></p>
    <% end %>
  </body>
</html>
  1. Slimの使用例
# app.rb
get '/slim-example' do
  @users = ['Alice', 'Bob', 'Charlie']
  slim :users
end

# views/users.slim
doctype html
html
  head
    title ユーザー一覧
  body
    h1 ユーザー一覧
    ul
      - @users.each do |user|
        li = user
  1. レイアウトの活用
# views/layout.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= @title %></title>
    <%= yield_content :head %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

# views/page.erb
<% content_for :head do %>
  <link rel="stylesheet" href="/styles.css">
<% end %>

<div class="content">
  <%= yield %>
</div>

これらの基本機能を組み合わせることで、シンプルながらも柔軟なWebアプリケーションを構築することができます。

実践的なSinatraアプリケーション設計のベストプラクティス

モジュール化による保守性の向上

Sinatraアプリケーションを保守性の高い構造にするために、以下のようなモジュール化の手法を活用します:

  1. モジュラーアプリケーションの基本構造
# config.ru
require './app'
run App

# app.rb
require 'sinatra/base'
require_relative 'routes/users'
require_relative 'routes/posts'

class App < Sinatra::Base
  # 共通の設定
  configure do
    set :sessions, true
    set :root, File.dirname(__FILE__)
  end

  # ミドルウェアの設定
  use Rack::Session::Cookie

  # ルーティングの登録
  use UsersController
  use PostsController

  # エラーハンドリング
  error 404 do
    'ページが見つかりません'
  end
end

# routes/users.rb
class UsersController < Sinatra::Base
  get '/users' do
    @users = User.all
    erb :'users/index'
  end
end

# routes/posts.rb
class PostsController < Sinatra::Base
  get '/posts' do
    @posts = Post.all
    erb :'posts/index'
  end
end
  1. サービスクラスの活用
# services/user_service.rb
class UserService
  def self.create(params)
    user = User.new(params)
    UserMailer.welcome(user) if user.save
    user
  end
end

# routes/users.rb
post '/users' do
  @user = UserService.create(params[:user])
  redirect '/users'
end

効率的なデータベース連携の方法

Sinatraでのデータベース連携は、主にActiveRecordやSequelなどのORMを使用します:

  1. ActiveRecordの設定
# config/database.rb
require 'active_record'

ActiveRecord::Base.establish_connection(
  adapter: 'postgresql',
  host: ENV['DB_HOST'],
  database: ENV['DB_NAME'],
  username: ENV['DB_USER'],
  password: ENV['DB_PASSWORD']
)

# models/user.rb
class User < ActiveRecord::Base
  validates :email, presence: true, uniqueness: true
  has_many :posts

  # カスタムスコープ
  scope :active, -> { where(status: 'active') }
end
  1. コネクションプールの最適化
# config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count

before_fork do
  ActiveRecord::Base.connection_pool.disconnect!
end

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    config = ActiveRecord::Base.configurations[ENV['RACK_ENV']]
    config['pool'] = ENV['MAX_THREADS'] || 5
    ActiveRecord::Base.establish_connection(config)
  end
end

セキュリティ対策の実装方法

Sinatraアプリケーションのセキュリティを強化する主要な実装例:

  1. CSRF対策
# app.rb
require 'rack/protection'

class App < Sinatra::Base
  use Rack::Protection
  use Rack::Protection::FormToken

  # フォームにCSRFトークンを含める
  helpers do
    def csrf_token
      Rack::Protection::FormToken.token(env['rack.session'])
    end
  end
end

# views/form.erb
<form method="POST" action="/submit">
  <input type="hidden" name="csrf_token" value="<%= csrf_token %>">
  <!-- フォームの内容 -->
</form>
  1. セキュアなセッション管理
# config/initializers/session.rb
require 'securerandom'

configure do
  # セキュアなセッション設定
  use Rack::Session::Cookie,
    key: '_app_session',
    secret: ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) },
    expire_after: 30.days,
    secure: production?,
    httponly: true
end
  1. XSS対策
# helpers/sanitize_helper.rb
require 'rack/utils'

module SanitizeHelper
  def h(text)
    Rack::Utils.escape_html(text)
  end

  def sanitize_params
    params.each do |key, value|
      params[key] = Rack::Utils.escape_html(value) if value.is_a?(String)
    end
  end
end

# app.rb
helpers SanitizeHelper

before do
  sanitize_params
end
  1. セキュアなヘッダー設定
# config.ru
use Rack::Protection::HttpOrigin
use Rack::Protection::FrameOptions
use Rack::Protection::XSSHeader

before do
  headers 'X-Frame-Options' => 'DENY'
  headers 'X-Content-Type-Options' => 'nosniff'
  headers 'X-XSS-Protection' => '1; mode=block'
  headers 'Content-Security-Policy' => "default-src 'self'"
end

これらのベストプラクティスを適用することで、保守性が高く、セキュアなSinatraアプリケーションを構築することができます。

Sinatraアプリケーションの本番運用ガイド

最適なデプロイ方法の選択

Sinatraアプリケーションの代表的なデプロイ方法を解説します:

  1. Herokuへのデプロイ
# Procfile
web: bundle exec puma -C config/puma.rb

# config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
  1. Docker環境でのデプロイ
# Dockerfile
FROM ruby:3.2.2-slim

WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN apt-get update && \
    apt-get install -y build-essential && \
    bundle install --without development test

COPY . .

CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
  1. Nginx + Pumaの設定
# /etc/nginx/sites-available/sinatra-app
upstream sinatra {
    server unix:///var/run/puma.sock;
}

server {
    listen 80;
    server_name example.com;

    root /var/www/sinatra-app/public;
    access_log /var/log/nginx/sinatra-access.log;
    error_log /var/log/nginx/sinatra-error.log;

    location / {
        try_files $uri @puma;
    }

    location @puma {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
        proxy_pass http://sinatra;
    }
}

パフォーマンス監視と最適化の手法

  1. パフォーマンスモニタリングの実装
# config/initializers/monitoring.rb
require 'newrelic_rpm' if production?

# カスタムメトリクスの追加
before do
  @start_time = Time.now
end

after do
  duration = Time.now - @start_time
  NewRelic::Agent.record_metric("Custom/Response/Duration", duration)
end

# キャッシュの設定
configure do
  set :cache, Dalli::Client.new(
    ENV['MEMCACHIER_SERVERS'],
    expires_in: 60 * 60 # 1時間
  )
end

helpers do
  def cache_fetch(key, ttl = 3600)
    settings.cache.fetch(key, ttl) { yield }
  end
end
  1. レスポンスタイム最適化
# アセットの圧縮
use Rack::Deflater

# 静的ファイルのキャッシュ設定
set :static_cache_control, [:public, max_age: 31536000]

# データベースクエリの最適化
get '/api/posts' do
  cache_fetch("posts_#{params[:page]}") do
    Post.includes(:user, :comments)
        .page(params[:page])
        .per(20)
        .to_json
  end
end

トラブルシューティングの実践的アプローチ

  1. ログ管理の設定
# config/logging.rb
require 'logger'

configure do
  # 詳細なログ設定
  logger = Logger.new(File.join(settings.root, 'log', "#{settings.environment}.log"))
  logger.level = Logger::INFO
  set :logger, logger
end

# カスタムログの実装
helpers do
  def log_error(e)
    logger.error "Error: #{e.message}"
    logger.error e.backtrace.join("\n")
  end
end

# エラーハンドリング
error do |e|
  log_error(e)
  'サーバーエラーが発生しました。'
end
  1. 主要なトラブルシューティングポイント
# メモリリーク対策
configure do
  # リクエスト間でのメモリクリーンアップ
  after do
    GC.start
  end

  # 大きなリクエストの制限
  use Rack::MaxRequestSize, 3145728 # 3MB
end

# デッドロック対策
configure do
  # トランザクションタイムアウトの設定
  ActiveRecord::Base.connection.execute(
    "SET statement_timeout = 5000;" # 5秒
  )
end

# 接続エラー対策
helpers do
  def with_connection_retry(max_retries = 3)
    retries = 0
    begin
      yield
    rescue ActiveRecord::ConnectionTimeoutError
      retries += 1
      if retries <= max_retries
        sleep(0.1 * retries)
        retry
      else
        raise
      end
    end
  end
end
  1. 監視とアラート設定
# config/initializers/monitoring.rb
configure :production do
  # Slack通知の設定
  def notify_slack(message)
    uri = URI(ENV['SLACK_WEBHOOK_URL'])
    Net::HTTP.post(uri, {
      text: "[#{settings.environment}] #{message}"
    }.to_json, 'Content-Type' => 'application/json')
  end

  # エラー監視
  error do |e|
    notify_slack("Error: #{e.message}")
    raise e
  end

  # パフォーマンス監視
  before do
    @request_start = Time.now
  end

  after do
    duration = Time.now - @request_start
    if duration > 1.0 # 1秒以上かかったリクエスト
      notify_slack("Slow request: #{request.path} (#{duration.round(2)}s)")
    end
  end
end

これらの設定と実装により、本番環境での安定した運用が可能になります。

実践的なコード例で学ぶSinatraアプリケーション

RESTful APIの実装例

以下に、シンプルなブログAPIの実装例を示します:

# app/api.rb
require 'sinatra/base'
require 'sinatra/json'
require 'json'

class BlogAPI < Sinatra::Base
  # JSONパースの設定
  before do
    content_type :json
    if request.content_type == 'application/json'
      request.body.rewind
      @request_payload = JSON.parse(request.body.read)
    end
  end

  # 記事一覧の取得
  get '/api/posts' do
    posts = Post.order(created_at: :desc).map do |post|
      {
        id: post.id,
        title: post.title,
        excerpt: post.content[0..100],
        author: post.author.name,
        created_at: post.created_at
      }
    end
    json posts
  end

  # 記事の詳細取得
  get '/api/posts/:id' do |id|
    post = Post.find(id)
    json post
  rescue ActiveRecord::RecordNotFound
    status 404
    json error: 'Post not found'
  end

  # 記事の作成
  post '/api/posts' do
    post = Post.new(@request_payload)
    if post.save
      status 201
      json post
    else
      status 422
      json errors: post.errors.full_messages
    end
  end

  # 記事の更新
  put '/api/posts/:id' do |id|
    post = Post.find(id)
    if post.update(@request_payload)
      json post
    else
      status 422
      json errors: post.errors.full_messages
    end
  end

  # 記事の削除
  delete '/api/posts/:id' do |id|
    post = Post.find(id)
    post.destroy
    status 204
  end
end

認証機能の実装例

セキュアな認証システムの実装例を示します:

# app/auth.rb
require 'sinatra/base'
require 'bcrypt'
require 'jwt'

class AuthApp < Sinatra::Base
  # JWTトークンの生成
  def generate_token(user_id)
    payload = {
      user_id: user_id,
      exp: Time.now.to_i + (24 * 60 * 60) # 24時間有効
    }
    JWT.encode(payload, ENV['JWT_SECRET'], 'HS256')
  end

  # 認証ミドルウェア
  def authenticate!
    auth_header = request.env['HTTP_AUTHORIZATION']
    if auth_header
      token = auth_header.split(' ').last
      begin
        payload = JWT.decode(token, ENV['JWT_SECRET'], true, algorithm: 'HS256')[0]
        @current_user = User.find(payload['user_id'])
      rescue JWT::ExpiredSignature
        halt 401, json(error: 'Token has expired')
      rescue JWT::DecodeError
        halt 401, json(error: 'Invalid token')
      end
    else
      halt 401, json(error: 'Authorization header required')
    end
  end

  # ユーザー登録
  post '/auth/register' do
    user = User.new(@request_payload)
    user.password = BCrypt::Password.create(@request_payload['password'])

    if user.save
      status 201
      json token: generate_token(user.id)
    else
      status 422
      json errors: user.errors.full_messages
    end
  end

  # ログイン
  post '/auth/login' do
    user = User.find_by(email: @request_payload['email'])
    if user && BCrypt::Password.new(user.password_digest) == @request_payload['password']
      json token: generate_token(user.id)
    else
      status 401
      json error: 'Invalid email or password'
    end
  end

  # パスワードリセット
  post '/auth/reset_password' do
    user = User.find_by(email: @request_payload['email'])
    if user
      reset_token = SecureRandom.hex(32)
      user.update(reset_token: reset_token, reset_token_expires_at: 1.hour.from_now)
      # メール送信処理(省略)
      status 200
      json message: 'Password reset instructions sent'
    else
      status 404
      json error: 'User not found'
    end
  end
end

非同期処理の実装例

Sidekiqを使用した非同期処理の実装例を示します:

# config/initializers/sidekiq.rb
require 'sidekiq'

Sidekiq.configure_server do |config|
  config.redis = { url: ENV['REDIS_URL'] }
end

Sidekiq.configure_client do |config|
  config.redis = { url: ENV['REDIS_URL'] }
end

# app/workers/email_worker.rb
class EmailWorker
  include Sidekiq::Worker
  sidekiq_options retry: 3, queue: 'mailers'

  def perform(user_id, template, data)
    user = User.find(user_id)
    UserMailer.send(template, user, data).deliver_now
  end
end

# app/workers/image_processing_worker.rb
class ImageProcessingWorker
  include Sidekiq::Worker
  sidekiq_options retry: 5, queue: 'media'

  def perform(image_id)
    image = Image.find(image_id)

    # 画像の処理
    processed_image = ImageProcessor.new(image).process

    # 処理結果の保存
    image.update(
      processed_url: processed_image.url,
      processed_at: Time.current
    )
  end
end

# app/api/upload.rb
class UploadAPI < Sinatra::Base
  # 画像アップロード
  post '/api/images' do
    image = Image.new(file: params[:file])

    if image.save
      # 非同期で画像処理を開始
      ImageProcessingWorker.perform_async(image.id)

      status 202
      json message: 'Image upload accepted', image_id: image.id
    else
      status 422
      json errors: image.errors.full_messages
    end
  end

  # 処理状況の確認
  get '/api/images/:id/status' do |id|
    image = Image.find(id)

    json({
      id: image.id,
      status: image.processed_at.present? ? 'completed' : 'processing',
      processed_url: image.processed_url
    })
  end
end

これらの実装例は、実際のプロジェクトですぐに活用できる実践的なコードとなっています。必要に応じて、プロジェクトの要件に合わせてカスタマイズしてください。

Sinatraで作る本格的なWebアプリケーション開発の次のステップ

テスト駆動開発の導入方法

Sinatraアプリケーションへのテスト駆動開発(TDD)の導入例を示します:

# Gemfile
group :test do
  gem 'rspec'
  gem 'rack-test'
  gem 'database_cleaner'
  gem 'factory_bot'
end

# spec/spec_helper.rb
ENV['RACK_ENV'] = 'test'

require_relative '../app'
require 'rspec'
require 'rack/test'
require 'database_cleaner'

RSpec.configure do |config|
  config.include Rack::Test::Methods

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end

# spec/routes/user_spec.rb
describe UserController do
  let(:app) { UserController }

  describe 'GET /users' do
    before do
      @user = create(:user)
    end

    it 'returns user list' do
      get '/users'
      expect(last_response).to be_ok
      expect(JSON.parse(last_response.body)).to include(
        'id' => @user.id,
        'name' => @user.name
      )
    end
  end

  describe 'POST /users' do
    let(:valid_params) { { name: 'Test User', email: 'test@example.com' } }

    it 'creates a new user' do
      expect {
        post '/users', valid_params
      }.to change(User, :count).by(1)

      expect(last_response.status).to eq 201
    end
  end
end

CICD環境の構築方法

GitHub Actionsを使用したCI/CD環境の構築例:

# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:13
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: myapp_test
        ports: ['5432:5432']
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

    steps:
    - uses: actions/checkout@v2

    - name: Set up Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 3.2.2
        bundler-cache: true

    - name: Install dependencies
      run: bundle install

    - name: Setup database
      run: |
        bundle exec rake db:create
        bundle exec rake db:migrate
      env:
        RAILS_ENV: test
        DATABASE_URL: postgres://postgres:postgres@localhost:5432/myapp_test

    - name: Run tests
      run: bundle exec rspec

    - name: Run rubocop
      run: bundle exec rubocop

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest

    steps:
    - name: Deploy to Heroku
      uses: akhileshns/heroku-deploy@v3.12.12
      with:
        heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
        heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
        heroku_email: ${{ secrets.HEROKU_EMAIL }}

マイクロサービスアーキテクチャへの展開

Sinatraを使用したマイクロサービスの実装例:

# services/user_service/app.rb
require 'sinatra/base'
require 'httparty'

class UserService < Sinatra::Base
  configure do
    set :service_registry_url, ENV['SERVICE_REGISTRY_URL']
    set :service_name, 'user-service'
  end

  def register_service
    HTTParty.post("#{settings.service_registry_url}/register", body: {
      name: settings.service_name,
      url: ENV['SERVICE_URL'],
      health_check_path: '/health'
    }.to_json)
  end

  def discover_service(name)
    response = HTTParty.get("#{settings.service_registry_url}/services/#{name}")
    JSON.parse(response.body)['url']
  end

  get '/health' do
    status 200
    json status: 'ok'
  end

  get '/users/:id' do |id|
    user = User.find(id)

    # 投稿サービスから関連データを取得
    posts_service_url = discover_service('post-service')
    posts_response = HTTParty.get("#{posts_service_url}/users/#{id}/posts")

    json({
      user: user,
      posts: JSON.parse(posts_response.body)
    })
  end
end

# services/post_service/app.rb
class PostService < Sinatra::Base
  # Circuit Breaker パターンの実装
  use CircuitBreaker,
      method: :get,
      path: '/users/:user_id/posts',
      threshold: 5,
      timeout: 30

  get '/users/:user_id/posts' do |user_id|
    posts = Post.where(user_id: user_id)
    json posts
  end
end

# lib/circuit_breaker.rb
class CircuitBreaker
  def initialize(app, options = {})
    @app = app
    @options = options
    @failures = 0
    @last_failure_time = nil
  end

  def call(env)
    return circuit_open_response if circuit_open?

    begin
      response = @app.call(env)
      reset_circuit
      response
    rescue StandardError => e
      record_failure
      raise e
    end
  end

  private

  def circuit_open?
    return false if @failures < @options[:threshold]
    return false if @last_failure_time.nil?

    Time.now - @last_failure_time < @options[:timeout]
  end

  def record_failure
    @failures += 1
    @last_failure_time = Time.now if @failures >= @options[:threshold]
  end

  def reset_circuit
    @failures = 0
    @last_failure_time = nil
  end

  def circuit_open_response
    [503, {'Content-Type' => 'application/json'}, [{
      error: 'Circuit breaker is open',
      retry_after: @options[:timeout]
    }.to_json]]
  end
end

このマイクロサービスアーキテクチャの実装では、以下の重要なパターンを導入しています:

  1. サービスディスカバリ:各サービスの登録と発見
  2. Circuit Breaker:サービス間の呼び出しの信頼性向上
  3. ヘルスチェック:サービスの状態監視
  4. 分散トレーシング:サービス間の依存関係の可視化

これらの発展的な実装方法を理解し、適切に活用することで、Sinatraを使用した本格的なWebアプリケーション開発が可能になります。