Skip Navigation
Show nav
Dev Center
  • Get Started
  • ドキュメント
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • ドキュメント
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku のアーキテクチャ
    • Dyno (アプリコンテナ)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • スタック (オペレーティングシステムイメージ)
    • ネットワーキングと DNS
    • プラットフォームポリシー
    • プラットフォームの原則
  • Developer Tools
    • コマンドライン
    • Heroku VS Code Extension
  • デプロイ
    • Git を使用したデプロイ
    • Docker によるデプロイ
    • デプロイ統合
  • 継続的デリバリーとインテグレーション
    • 継続的統合
  • 言語サポート
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails のサポート
      • Bundler の使用
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Python でのバックグランドジョブ
      • Python Behavior in Heroku
      • Django の使用
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Maven の使用
      • Spring Boot の使用
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go の依存関係管理
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • データベースとデータ管理
    • Heroku Postgres
      • Postgres の基礎
      • Postgres スターターガイド
      • Postgres のパフォーマンス
      • Postgres のデータ転送と保持
      • Postgres の可用性
      • Postgres の特別なトピック
      • Migrating to Heroku Postgres
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • その他のデータストア
  • AI
    • Working with AI
    • Heroku Inference
      • Inference API
      • Quick Start Guides
      • AI Models
      • Inference Essentials
    • Vector Database
    • Model Context Protocol
  • モニタリングとメトリクス
    • ログ記録
  • アプリのパフォーマンス
  • アドオン
    • すべてのアドオン
  • 共同作業
  • セキュリティ
    • アプリのセキュリティ
    • ID と認証
      • シングルサインオン (SSO)
    • Private Space
      • インフラストラクチャネットワーキング
    • コンプライアンス
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Team
    • Heroku Connect (Salesforce 同期)
      • Heroku Connect の管理
      • Heroku Connect のリファレンス
      • Heroku Connect のトラブルシューティング
  • パターンとベストプラクティス
  • Heroku の拡張
    • Platform API
    • アプリの Webhook
    • Heroku Labs
    • アドオンのビルド
      • アドオン開発のタスク
      • アドオン API
      • アドオンのガイドラインと要件
    • CLI プラグインのビルド
    • 開発ビルドパック
    • Dev Center
  • アカウントと請求
  • トラブルシューティングとサポート
  • Salesforce とのインテグレーション
  • 言語サポート
  • Scala
  • Scala を使用したデータベース接続プール

Scala を使用したデータベース接続プール

日本語 — Switch to English

この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。

最終更新日 2024年05月03日(金)

Table of Contents

  • Apache DBCP の使用
  • 接続プールの設定
  • PgBouncer を使用した接続の制限

接続プールは、事前に作成された一連の再利用可能な接続オブジェクトを使用してデータベースに接続するために、ソフトウェアアプリケーションによって使用されるパターンです。新しい接続が必要になった場合は、このプールから既存の接続が取得されます。接続を使用しているスレッドが完了すると、その接続は、別のスレッドで使用できるようにプールに戻されます。このパターンにより、ネットワークトラフィックが減少し、新しい接続を作成するコストが抑えられ、さらにガーベジコレクターへの負荷が軽減されるためデータベースへの接続のオーバーヘッドが削減されます。

多くの Scala および Java アプリケーションフレームワークには、独自の接続プール API が含まれています。ただし、すべてのフレームワークを設定するために使用される原則は一般に同じです。この記事では、Java Database Connectivity (JDBC) API と Apache DBCP プールライブラリを使用してデータベース接続プールを作成する方法について学習します。

すでに Scala アプリケーションがある場合は、それをこの例で使用できます。それ以外の場合は、先に進む前に「Heroku スターターガイド (Scala)​」の記事から単純なアプリケーションを作成します。また、「Java を使用して Heroku でリレーショナルデータベースに接続する​」にも精通しておいてください。

Apache DBCP の使用

アプリケーションの build.sbt​ ファイルを開き、次のライブラリを追加します。サンプルのスターターガイドアプリケーションを使用している場合は、postgresql 依存関係のアップグレードが必要になることがあります。

Apache DBCP 2 は、Java 7 および JDBC 4.1 とのみ互換性がありますJava 6 または JDBC 4 を使用している場合は、DBCP 1.4 を使用する必要があります。

libraryDependencies ++= Seq(
  "org.postgresql" % "postgresql" % "9.3-1102-jdbc41",
  "org.apache.commons" % "commons-dbcp2" % "2.0.1"
)

ここで、sbt を実行して、新しい jar ファイルをダウンロードしてインストールします。

$ sbt clean stage
...
[info] downloading http://repo1.maven.org/maven2/org/postgresql/postgresql/9.3-1102-jdbc41/postgresql-9.3-1102-jdbc41.jar ...
[info]  [SUCCESSFUL ] org.postgresql#postgresql;9.3-1102-jdbc41!postgresql.jar (436ms)
[info] downloading http://repo1.maven.org/maven2/org/apache/commons/commons-dbcp2/2.0.1/commons-dbcp2-2.0.1.jar ...
[info]  [SUCCESSFUL ] org.apache.commons#commons-dbcp2;2.0.1!commons-dbcp2.jar (332ms)
[info] downloading http://repo1.maven.org/maven2/org/apache/commons/commons-pool2/2.2/commons-pool2-2.2.jar ...
[info]  [SUCCESSFUL ] org.apache.commons#commons-pool2;2.2!commons-pool2.jar (238ms)
...
[info] Done packaging.
[success] Total time: 5 s, completed Aug 18, 2014 10:35:38 AM

次に、接続を作成するクラスのソースコードを開きます。スターターガイドアプリケーションから作業している場合は、Server.scala​ ファイルを開きます。ファイルの先頭に次のステートメントを追加します。

import java.sql.Connection
import java.sql.Statement
import org.apache.commons.dbcp2._

次に、データベース接続プールを含めて設定するために、新しいシングルトンオブジェクトを追加します。ファイルの末尾に次のコードを追加します。

object Datasource {
  val dbUri = new URI(System.getenv("DATABASE_URL"))
  val dbUrl = s"jdbc:postgresql://${dbUri.getHost}:${dbUri.getPort}${dbUri.getPath}"
  val connectionPool = new BasicDataSource()

  if (dbUri.getUserInfo != null) {
    connectionPool.setUsername(dbUri.getUserInfo.split(":")(0))
    connectionPool.setPassword(dbUri.getUserInfo.split(":")(1))
  }
  connectionPool.setDriverClassName("org.postgresql.Driver")
  connectionPool.setUrl(dbUrl)
  connectionPool.setInitialSize(3)
}

このメソッドでは、プールされていない接続の場合と同様に username​、password​、dbUrl​ を取得します。その後、これらのパラメータを使用して connectionPool​ を初期化し、connectionPool.setInitialSize(3)​ を呼び出してプールの初期サイズを設定します。BasicDataSource​オブジェクトがこれらの接続をただちに自動的に作成した後、アプリケーションがトラフィックの受信を開始すると、その接続はすぐに使用できるようになります。

プールから接続を次のように取得できます。

val connection = Datasource.connectionPool.getConnection

val stmt = connection.createStatement()
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)")
stmt.executeUpdate("INSERT INTO ticks VALUES (now())")
val rs = stmt.executeQuery("SELECT tick FROM ticks")

while (rs.next()) {
  println("Read from DB: " + rs.getTimestamp("tick") + "\n")
}

接続オブジェクトが取得されたら、他の JDBC Connection​ とまったく同じように使用できます。

接続プールの初期サイズの設定に加えて、その最大サイズや (接続が破棄され、新しい接続で置き換えられるまでの) 接続の最大有効期間、またはプールのサイズを調整するまで保持されるアイドル接続の最大数と最小数を設定することもできます。これらのすべてを、BasicDataSource クラスのメソッド​を使用して設定できます。

接続プールを設定する方法について学習しましたが、設定するときにどのような値を使用するかを明確にすることは別のトピックで説明します。

接続プールの設定

プール内でウォーム状態に維持されるアイドル接続の数は、アプリケーションのサイズや性質によって異なります。多くのユーザーが、HTTP リクエストを処理するスレッドあたり 1 つの接続で十分であることに気付いています (HTTP リクエストを処理するスレッドが接続を使用する唯一のスレッドである場合)。アプリケーションが、接続を新しいスレッドにすぐに引き継げないほど非常に高いスループットを処理している場合は、さらに多くを必要とする可能性があります。または、すべての HTTP リクエストがデータベースへのアクセスを必要としているわけでない場合は、少なくて済む可能性があります。最終的には、本番環境の負荷の下でのアプリケーションのプロファイリングが適切なプールパラメータを決定するための最善の方法です。

開発環境では、データベースをチェックすることにより、アプリケーションによって使用される接続の数を確認できます。

$ psql -h localhost
psql (9.3.2)
Type "help" for help.
jkutner=# \q

これにより、開発データベースへの接続が開かれます。その後、次を実行して Postgres データベースへの接続の数を確認できます。

select count(*) from pg_stat_activity where pid <> pg_backend_pid() and usename = current_user;

これにより、そのデータベース上の接続の数が返されます。

 count
-------
   5
(1 row)

シミュレートされた本番環境の負荷の下で、これは必要なプールのサイズを適切に示しています。ただし、いくつかの制約があります。

データベース接続の最大数

Heroku では、マネージド Postgres​ データベースが提供されます。 階層型データベースごとにさまざまな接続制限があります。これは、Heroku Postgres アドオンのドキュメント​にある一覧で見つけることができます。低い層のデータベースでは、高い層のデータベースより少ない接続が許可されます。データベースは、アクティブな接続の最大数に達すると、新しい接続を受け付けなくなります。これにより、アプリケーションが接続タイムアウトになり、例外が発生する可能性があります。

スケールアウトするときは、アプリケーションに必要なアクティブな接続の数に注意することが重要です。各 dyno で 5 つのデータベース接続が許可されている場合は、より堅牢なデータベースのプロビジョニングが必要になるまでに、4 つの dyno にしかスケールアウトできません。

これで、接続プールを設定する方法や、データベースで処理できる接続の数を見つける方法がわかったので、各 dyno に必要な接続の適切な数を計算する必要があります。

PgBouncer を使用した接続の制限

データベース接続の制限に達するまで、追加の dyno を使用して引き続きアプリケーションをスケールアウトできます。この時点に達する前に、PgBouncer buildpack​ を使用して、各 dyno に必要な接続の数を制限することをお勧めします。

PGBouncer では、データベーストランザクションで共有される接続のプールが保持されます。これにより、Postgres への接続 (通常は開いており、アイドル状態) が最小限に維持されます。ただし、トランザクションプーリングでは、名前付きプリペアドステートメント、セッションアドバイザリロック、リッスン/通知、またはセッションレベルで操作するその他の機能を使用できなくなります。詳細は、「PgBouncer buildpack FAQ for full list of limitations​」(制限の完全なリストに関する PgBouncer buildpack の FAQ) を参照してください。

多くのフレームワークでは、PGBouncer を使用するためにプリペアドステートメントを無効にする​必要があります。次に、他の buildpack を呼び出すカスタム buildpack を使用するようにアプリを設定します。

JDBC の場合、これには接続文字列への prepareThreshold=0​ の追加が必要です。ただし、JDBC ドライバへのパッチの適用​も必要になることがあります。

プリペアドステートメントを無効にするか、またはフレームワークでそれが使用されていないことを確認する前に続行しないでください。

$ heroku buildpacks:add heroku/pgbouncer

次に、アプリケーションを確実に実行可能にする必要があるため、言語固有の buildpack を追加する必要があります。Scala を使用しているため、次のようになります。

$ heroku buildpacks:add heroku/scala

ここで、PgBouncer を起動するように Procfile​ を変更する必要があります。Procfile​で、コマンド bin/start-pgbouncer-stunnel​ を web​ エントリの先頭に追加します。そのため、Procfile​ が

web: target/universal/stage/bin/scala-getting-started

であった場合は、次のようになります。

web: bin/start-pgbouncer-stunnel target/universal/stage/bin/scala-getting-started

結果を Git にコミットし、ステージングアプリでテストした後、本番環境にデプロイします。

デプロイ時、出力には次の内容が表示されます。

=====> Detected Framework: pgbouncer-stunnel

Scala、Java、JDBC、Apache DBCP を使用した接続プールについての詳細は、Apache Commons の Web サイト​を参照してください。

この記事で使用されている例のソースコード​は、GitHub で見つけることができます。

関連カテゴリー

  • Scala

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices