Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AWS SDKのClientはFactory経由で作ろう
Search
TomoyaIwata
September 26, 2023
Programming
1
1k
AWS SDKのClientは Factory経由で作ろう
「緊急開催!サーバーレス座談会 in JAWS-UG 大阪」にてLTさせて頂いた際の資料です
https://jawsugosaka.doorkeeper.jp/events/162714
TomoyaIwata
September 26, 2023
Tweet
Share
More Decks by TomoyaIwata
See All by TomoyaIwata
Lambdaの常識はどう変わる?!re:Invent 2025 before after
iwatatomoya
1
1k
Aurora DSQLはサーバーレスアーキテクチャの常識を変えるのか
iwatatomoya
1
2.1k
これでLambdaが不要に?!Step FunctionsのJSONata対応について
iwatatomoya
2
6.3k
Qdrantでベクトルデータベースに入門してみよう
iwatatomoya
0
1.9k
詳解 AWS Lambdaコールドスタート
iwatatomoya
2
3.2k
真のサーバーレスへ向けたAuroraの進化Aurora Limitless Database
iwatatomoya
1
5k
OpentelemetryでアプリケーションのObservabilityを強化しよう
iwatatomoya
0
1.3k
AWS Lambdaは俺が作った
iwatatomoya
2
3.1k
SnapStartの未来についての期待と妄想
iwatatomoya
1
1.5k
Other Decks in Programming
See All in Programming
2026年は Rust 置き換えが流行る! / 20260220-niigata-5min-tech
girigiribauer
0
220
AWS Infrastructure as Code の新機能 2025 総まとめ 〜SA 4人による怒涛のデモ祭り〜
konokenj
10
3.2k
守る「だけ」の優しいEMを抜けて、 事業とチームを両方見る視点を身につけた話
maroon8021
3
280
Takumiから考えるSecurity_Maturity_Model.pdf
gessy0129
1
120
AIに仕事を丸投げしたら、本当に楽になれるのか
dip_tech
PRO
0
180
どんと来い、データベース信頼性エンジニアリング / Introduction to DBRE
nnaka2992
1
140
PostgreSQL を使った快適な go test 環境を求めて
otakakot
0
410
Go Conference mini in Sendai 2026 : Goに新機能を提案し実装されるまでのフロー徹底解説
yamatoya
0
520
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
210
CSC307 Lecture 11
javiergs
PRO
0
590
RAGでハマりがちな"Excelの罠"を、データの構造化で突破する
harumiweb
9
2.5k
Codex の「自走力」を高める
yorifuji
0
280
Featured
See All Featured
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
370
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.4k
Producing Creativity
orderedlist
PRO
348
40k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
360
Visualization
eitanlees
150
17k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
600
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
99
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
140
Unsuck your backbone
ammeep
672
58k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
310
Transcript
AWS SDKのClientは Factory経由で作ろう クラスメソッド株式会社 岩⽥ 智哉 1
2 ⾃⼰紹介 l クラスメソッド株式会社 サーバーサイドエンジニア l 2023 Japan AWS Top
Engineer l 2023 Japan AWS All Certifications Engineer l 前⼗字靭帯再建⼿術リハビリ中 岩⽥ 智哉
3 ⾔いたいこと AWS SDKのClientは Factory経由で作ろう
4 LambdaとEC2/ECSの違い リクエストとコンピューティング環境がN:1 リクエストとコンピューティング環境が1:1
5 リクエストとコンピューティング環境が1:1だと… ソケット ソケット ソケット ソケット DynamoDB等のAWSサービス ソケット ソケット Lambda実⾏環境で⽣成するソケットは1つで⼗分
(なことが多い)
6 これらを意識すると AWS SDKのClientの扱いが 最適化できる
7 良くない例1 import boto3 class TableA: def __init__(self): self._client =
boto3.client('dynamodb') def put_item(self, item): self._client.put_item(TableName='tableA', Item=item) class TableB: def __init__(self, client): self._client = boto3.client('dynamodb') def put_item(self, item): self._client.put_item(TableName='tableB', Item=item) def handler(event, context): table_a = TableA() table_a.put_item({'foo': 'bar’}) table_b = TableB() table_b.put_item({'hoge': 'fuga'})
8 何が良くないのか︖
9 よくある解決策 class TableA: def __init__(self, client): self._client = client
def put_item(self, item): self._client.put_item(TableName='tableA', Item=item) class TableB: def __init__(self, client): self._client = client def put_item(self, item): self._client.put_item(TableName='tableB', Item=item) import boto3 client = boto3.client('dynamodb’) def handler(event, context): table_a = TableA(client) table_a.put_item({'foo': 'bar'}) table_b = TableB(client) table_b.put_item({'hoge': 'fuga'})
10 そうはいっても • 現実世界のアプリはもっと複雑。呼び出し階層も深くなる • 呼び出し先の呼び出し先の呼び出し先…にclientを伝搬するのは⾯倒 • clientの処理化処理はもっと⾊々やることがある import boto3
client = boto3.client('dynamodb’) def handler(event, context): table_a = TableA(client) table_a.put_item({'foo': 'bar'}) table_b = TableB(client) table_b.put_item({'hoge': 'fuga'})
11 提案 Factoryクラスを使おう︕
12 実装例(簡易版) import boto3 class Boto3ClientFactory: # ⽣成したclientクラスのインスタンスをクラス変数に保持しておく _clients =
{} @classmethod def get_singleton_client(cls, service_name, **kwargs): # 対象サービスのclientクラスを⽣成済みならクラス変数のキャッシュから返却 # 複数リージョンを扱う場合はキャッシュキーにリージョンを含めるなど追加の考慮が必要 if service_name in cls._clients: return cls._clients[service_name] client = boto3.client(service_name, **kwargs) cls._clients[service_name] = client return client
13 Factoryクラスの追加実装例 • タイムアウト値の調整 • デフォルト値はLambda実⾏環境の設定値としては不適切 • connect_timeout:60, read_timeout:60 •
Event Systemを利⽤したフックの登録 • API呼び出し前にパラメータをクラス変数に保存 • 例外キャッチ時にクラス変数に保存したパラメータをログ出⼒ • ⾮シングルトンなclientクラス⽣成処理 • たまにはPromise.All的な実装が必要になることもある
14 Factoryクラスの利⽤例 client = Boto3ClientFactory.get_singleton_client('dynamodb') def handler(event, context): table_a =
TableA(client) table_a.put_item({'foo': 'bar'}) table_b = TableB(client) table_b.put_item({'hoge': 'fuga'}) def foo(): bar() def bar(): baz() def baz(): client = Boto3ClientFactory.get_singleton_client('dynamodb') table_a = TableA(client) table_a.put_item({'foo': 'bar'}) def handler(event, context): foo() タイムアウト値など適切に設定された clientクラスが1発で取得可能 呼び出し階層の深いところまでclientクラ スを引き回さなくて良くなる
15 Provisioned Concurrency利⽤時の注意 Boto3ClientFactory.get_singleton_client('dynamodb’) def handler(event, context): … Init処理の中でclientクラスの⽣成を「空打ち」しておく
16 初回のClientクラス⽣成処理は重い https://github.com/boto/botocore/blob/40d6219947f4d047088cbeb80f8f222f599f9c7c/botocore/loaders.py • 初回のclientクラス⽣成時はJSONファイルを読み込んで動的にクラスを⽣成するので「重い」 • 2回⽬以後はキャッシュを使う • Init処理の中でclientクラス向けのキャッシュを「暖気」することでProvisioned Concurrencyに最適化
https://github.com/boto/botocore/blob/40d6219947f4d047088cbeb80f8f222f599f9c7c/botocore/data/dynamo db/2012-08-10/service-2.json
17 以上 ありがとうございました
18