MagicStack / MagicStack/asyncpg

Potential starvation with connection pool

オープン
#1,247 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Python
スター
8.1k
フォーク
468
PR マージ指標
30日以内にマージされた PR はありません

説明

I have the following piece of code where I initialize 100 workers and a connection pool of size 10. Each worker loops and trys to acquire a connection and hold it for 200ms.

```python
import asyncio

import asyncpg

async def worker(pool: asyncpg.Pool):
while True:
async with pool.acquire(timeout=10):
# hold the connection for 200ms
await asyncio.sleep(0.2)

async def main():
async with asyncpg.pool.create_pool(max_size=10) as pool:
async with asyncio.TaskGroup() as tg:
for _ in range(100):
tg.create_task(worker(pool))

asyncio.run(main())
```

When running on my laptop, this code reliably crashes with a `TimeoutError` after a few minutes, meaning that at least one worker failed to acquire a connection after 10 seconds. Given that there're 10 workers per connection and each worker holds the connection for 200ms, I would expect workers to be able to acquire a connection every 2 seconds.

This looks like starvation to me. Are there fairness guarantees regarding connection pools? Is there anything I could do other than just increasing the max pool size?

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、asyncio.TaskGroup、100 workers、asyncpg.pool.create_pool(max_size=10)を使用して、提供されたPython再現コードを実行します。競合下でのpool.acquire(timeout=10)の動作を調査し、観測されたTimeoutErrorがstarvationを示しているのか、想定されたスケジューリングによるものなのかを判断します。fairness guaranteeを文書化するか、再現可能なpoolの不具合を特定できれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
postgresql, python
領域
databases
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。