Slide 1

Slide 1 text

PHP Application における Kubernetes 内 gRPC 通信 Mercari 編 @ganchiku(Shin Ohno), July 20th, 2026

Slide 2

Slide 2 text

$ whoami - Shin Ohno(@ganchiku) ● 2020年〜 Mercari の主に Backend 側の改善, 移行, 運用 ○ 入社以来, ずっとコードやテーブルを削除 ○ モノリスの将来設計とその実践 ● 複数チームのマネージャー ○ Mercari API(PHP Service) & DBRE(主にTiDB) ○ プレイングマネージャータイプ ● 関わっているチームの主な偉業 ○ Mercari の Monolithを Kubernetes Cluster へ移行 2022 ○ PHP Application のgRPC Client化 2025(今日話すのはココ ) ○ Mercari のコアなデータベースを TiDB Cloud へ移行 2026 ● Philosophy ○ No Improvement Cycle, No Maintainability

Slide 3

Slide 3 text

$ 今日の話の想定聴衆者 Kubernetes 上での大規模 PHP アプ リケーション運用に興味がある方 モノリス PHP とマイクロサービスの接 続・移行戦略に興味がある方 大規模サービスで PHP がどのように 活用されているか知りたい方 PHP アプリケーションを Kubernetes / gRPC 環境へ適応させる際の実践的な 知見を持ち帰れる内容を目指します PHP サービスにおける gRPC 連携の 実践例を知りたい方

Slide 4

Slide 4 text

● Mercari における PHP Application の 現在 ○ 規模感, 運用 ● PHP Application の Service 間連携の歴史 ○ 2018 - 2020 移行期初期 - オンプレミス /GCE ○ 2020 - 2024 移行期中期 - GKEへの移行 ○ 2025 - 2026 現在 - クラスタ内直接通信 ● PHP Application の gRPC Client の実際 ○ Application に任せること , istio(Envoy) に任せること ○ Go の gRPC 使用との違いとチャレンジ ● gRPC Client 利用コードの解説 ○ 簡略化した Application の呼び出しコード解説 $ Agenda

Slide 5

Slide 5 text

Mercari における PHP Application の現在

Slide 6

Slide 6 text

構成 API: 約400 CronJob: 約35 Worker: 約10 Deploy 頻度: 3-10/day Traffic: 30k-80k RPS (この service の参考値 , 時間帯により変動 ) Pod数: 300-600 (HPA設定により変動 ) $ Mercari の PHP Application 規模感

Slide 7

Slide 7 text

2013年から PHP で運用, 現在も重要なサービス • PHP8.5 & Apache, DataDog • 主に Transaction, Logiチームが開発(一部 IdP, Coupon チームも担当) ■API 約400 (用途別に3つの系統で提供) Public API • インターネット公開用 iOS, Android, Web 向け (サード パーティ向けではない) • コア機能の開発 創業期からの取引, 配送周りのコ アなAPI Internal API • クラスター内限定連携 ネット接続不可, Kubernetes内 Backend サービスが呼び出し • 移行期・共有ロジック DB使用移行や, Public APIとのロ ジック共有用 Admin API • 管理用途に特化 ネット接続不可, Kubernetes内の Admin 目的で利用 • コアDB制御・ロジック コアDBの限定利用, およびPublic APIとのロジック融合 $ Mercari の PHP Application 運用

Slide 8

Slide 8 text

CronJobs 約35 • Kubernetes CronJob で Workload を管理 Workers 約10 • Kubernetes Deployment で Workload を管理 • Q4M ベースの Workers • Transactional Outbox Pattern の Workers 開発環境 GitHub に PR にラベルを貼ることをトリガーと して, 開発環境 Cluster に Service, Deployment が作成され PR 用の pod が立 ち上がり QA が可能 関連資料 & 開発情報 • Kubernetes Controller for PR Based Env • The World Is at Your PR! • Dynamic Service Routing using Istio $ Mercari の PHP Application 運用

Slide 9

Slide 9 text

サービス概要 • 依然として大規模なトラ フィックを安定して運用 • ビジネス上極めて重要な サービスがPHP上で稼働 実行環境 & 監視 • Kubernetes上で稼働 • PHP8.5 & Apache構成 • DataDogによる高度なオ ブザーバビリティの実現 リリース & API • リリース頻度は多いとき で1日10回 3つの提供API • Public API (iOS, Android, Web用) • Internal API (Backend Services用) • Admin API (Admin用) $ Mercari の PHP Application まとめ

Slide 10

Slide 10 text

Mercari における PHP Application の Service 間連携の歴史

Slide 11

Slide 11 text

$ 2018 - 2019移行初期 - DataCenter ● PHP Service ○ DataCenter ○ 全て HTTP ● Go Service ○ Kubernetes & DataCenter(記載 なし) ● Authority Service ○ Mercari Token を 検証し, Private Token を発行 ○ Private Token を 検証する ● Database は DataCenter 側

Slide 12

Slide 12 text

$ 2019 - 2021移行初期 - GCEへ ● PHP Service ● HTTP Server, HTTP Client ● DataCenterから GCE へ移行 ● 同じ時期に一部の Go Service も GCE へ移行(記載無し) ● Go Service ○ HTTP & gRPC Server, gRPC Client ○ gRPC Server, gRPC Client ● Authority Service ○ Mercari Token を検証し , Private Token を発行 ○ Private Token を検証する ● GCE, Data Center, Kubernetes Cluster 内に Proxy がいる ● Database は DataCenter 側

Slide 13

Slide 13 text

$ 20201- 2024 移行 - GKEへの移行開始時 ● PHP Service ● HTTP Server, HTTP Client ● Go Service ○ HTTP & gRPC Server, gRPC Client ○ gRPC Server, gRPC Client ● Authority Service ○ Mercari Token を検証し , Private Token を発行 ○ Private Token を検証する ● GCE, Data Center, Kubernetes Cluster 内に Proxy がいる ● Database は DataCenter 側

Slide 14

Slide 14 text

$ 2025 - 2026 現在 - クラスタ内直接通信 ● PHP Service ● HTTP Server, gRPC Client ● Go Service ○ HTTP & gRPC Server, gRPC Client ○ gRPC Server, gRPC Client ● 2 つの異なる用途の Token ● Mobileapp や Web 用の Platform Token ● Kubernetes Cluster 内の Private Token ● Authority Service(One of the Go Services) ○ Platform Token を検証し , Private Token を発行 ○ Private Token を検証する ● Database は TiDB Cloud or DataCenter 側s

Slide 15

Slide 15 text

$ Service 間連携の歴史的遷移のまとめ 2018 - 2020 移行期初期 オンプレミス /GCE • PHP Applicationは Kubernetesクラスタ 外で運用 • Gateway経由の HTTP通信を, gRPC へ変換して接続 2020 - 2024 移行期中期 GKEへの移行 • PHPをGKEへ移行 しクラスタ内通信が可 能に • 通信は一度インター ネット経由で Gatewayへ出力する フロー 2025 - 2026 現在 クラスタ内直接通信 • PHPから各サービス へgRPC直接通信に 切り替え • 外部からのリクエスト 受付は引き続きHTTP を使用 202x ~ 将来 次期フェーズ • 現在活動中であり, 具体的な成果はまだ 出せる段階にない

Slide 16

Slide 16 text

Mercari における PHP Application の Service 呼び出し

Slide 17

Slide 17 text

$ HTTP Client から gRPC Client へ HTTP Client (gRPC 移行前) ● Guzzle で HTTP Client を実装 ● 生の Guzzle では timeout, retry, UA などを個別に指定する 薄いラッパー を用意 ● リクエストは Gateway を経由し, Gateway が HTTP を gRPC に変換 する ● Gateway には Platform(Mercari)Token を使用 gRPC Client ● ext-grpc 拡張で, 実際のネットワーク処 理を担当 ○ バージョンに関して難あり (後スライドに おいて説明) ● grpc/grpc パッケージ github.com/grpc/grpc/tree/master/src/ php ● HTTPの時と同じく, timeout, UA などを 指定する薄いラッパー を用意 ● Gateway を経由せず直接サービスを Private Token でリクエストする

Slide 18

Slide 18 text

Load Balancing と Routing • Load Balancing には istio が必須 Go なら Client Load Balancing があるが, PHP は… 実装の切り分け • 業務ロジックが必要なのは Application • Canary Release は PHP Application で は基本用意していない。危険な Release は 検討の余地があるが, 多くのリリースがある ため実現可能性と相談 $ Application or istio(Envoy)

Slide 19

Slide 19 text

$ 移行自体は 2021年くらいから 2025年まで BACKGROUND & CONTEXT 周りは Go のサービスで gRPC 接続が当たり前の状態だった 移行への契機と確信 当初はチーム内での小さな技術的改善と してスタート その後, Forward Proxy のメンテナンス 上の問題が顕在化し廃止を決定 , さらに オブザーバビリティ改善の必要性が判明 したことで, プロジェクトの方向性がより確 固たるものに CORE OBJECTIVES / 移行の目的 リクエストの追跡を単純化したい 複数サービス間の複雑な通信経路を一元的にトラッキング可能 に DataDog での Trace でオブザーバビリティ向上 分散トレーシングの強化により, ボトルネックの可視化を容易に Token のハンドリングを統一 認証ロジックを標準化し, システム全体のメンテナンス懸念を排 除 エラーの対処を統一化したい 共通のエラーハンドリング定義を適用し, システム品質を安定化

Slide 20

Slide 20 text

$ 移行の結果得られたもの トラフィックの簡略化と認証認可の強化 Cluster 内での直接呼び出しが可能になり , 通信トラ フィックが大幅に簡略化された • Private Token の活用により, よりきめ細かな認証認可の制御が可能 に 構造上課題の解決 Cluster 内限定で使用すべき Private Tokenが, 旧アー キテクチャでは外部経路を経由していた構成上の課題 を根本解決した • 暫定的なForward Proxy IP制限の運用を廃止し、アーキテクチャレベ ルでの恒久的な解決を実現。 オブザーバビリティの大幅な向上 DataDog Tracing における Span の可視化が実現さ れた • 障害発生時, エンドポイントから呼び出し先サービス内部まで一貫した トレースが可能になり , 調査工数を削減。 コード健全化とパフォーマンス改善 長年放置されていたバグや , 既に使われていない不要 なコードを発見・整理できた • コードの保守性(メンテナビリティ)が向上したほか , 無駄な通信を削る ことで Latency 自体も改善

Slide 21

Slide 21 text

$ 移行の苦労話 CHALLENGE & BACKGROUND エンジニアリング的改善ゆえにプ ライオリティの扱いが難しい 技術負債の蓄積 約50のサービス, 200以上のAPI呼び 出しが存在し, 中には作りっぱなしで放 置されたものもあるなど, 見えない負債 が積み重なっている状態だった TRANSITION & EXECUTION / 移行の推進 役割の変遷とメンバーの支援 最初はICとして自ら動きつつ, 途中からEMへ立場が変化。 2022年頃に入社したメンバーに対しても, 諦めずに「最後ま でやり切ることの大切さ」を説き続け, やり遂げてもらった 地道な問題の計画的対処 先頭に立って泥臭い問題に対処し, 計画的にクリアしていっ た ● すでに使われていない不要なAPI呼び出しの整理 ● 誤った定義で呼び出されているAPIの修正 ● そもそも常時エラーになっていた箇所の根本解決 お疲れ様です 🙏

Slide 22

Slide 22 text

$ gRPC Client php-ext の問題 ext-grpc STDERR noise Errors by statically-linked Abseil library . ● 最新版は 1.82.0 (2026/7/2 に出た)。少なくとも 1.78(2026/2/6) までは absl::InitializeLog の初期化のロ グが STDERR に大量に出てしまう問題があり ,1.64.1 より上に上げることができていなかった ○ Static link されている abseil の初期化のログが出てしまう問題 ● 一方, Debian trixie が 1.64.1をビルドできなくて, bookworm で止まってしまっている 問題はこの辺 , Public issues on GitHub/gRPC ● grpc/grpc ○ https://github.com/grpc/grpc/issues/31772 ○ https://github.com/grpc/grpc/issues/37178 ○ https://github.com/grpc/grpc/issues/38336 ○ https://github.com/grpc/grpc/issues/41525 ● Abseil ○ https://github.com/abseil/abseil-cpp/issues/1656

Slide 23

Slide 23 text

$ 調査, 検証中 EXISTING EXT-GRPC 複数バージョン検証も改善に至らず 検証済みバージョン 1.65.0, 1.65.1, 1.67.0, 1.70.0, 1.74.0, 1.78.0 また, パッチを当てたり試したりするなどの 対策も実施したが, 改善は見られなかった ALTERNATIVE / grpc-php-rs の検討 https://github.com/BSN4/grpc-php-rs 開発環境での検証結果(良好) 採用には至っていないが , 開発環境で試したところ , 問題のあったログが出なくなっていることを確認 採用における懸念点と検討状況 ● 個人ライブラリであり , 実績・スターが少ない → 現在の ext-grpc に問題があるため, バージョン 固定での採用を検討 ● ドロップイン互換があるが , 網羅的な互換性 検証が困難 → 切り戻しが可能なため, 試験的な 導入・検証も視野に

Slide 24

Slide 24 text

PHP Application on gRPC Server? ● Mercari JP では, PHP Application で gRPC Server の実績はない ● Mercari US では, PHP Application で gRPC Server の実績はある ○ nginx+php-fpm を使用 ○ nginx は HTTP/2 gRPC で受けて行かを FastCGRI に落として php-fpm に渡して grpc-status を戻している ■ REQUEST_URI ■ QUERY_STRING ■ STDIN protobuf ■ HTTP_* 化した metadata ■ プロトコル変換だけを担い , 中身のデコードは PHP(REQUEST_URI と php://input)が 行っている JP では, 既存のものを置き換える必要性は現状ないという判断 ● それをするなら, Go に移行しようという話はあるが , それは別の機会 $ btw, why not to use gRPC Server?

Slide 25

Slide 25 text

gRPC Client 利用コードの解説 と一般化した例

Slide 26

Slide 26 text

$ gRPC のリクエストの流れ

Slide 27

Slide 27 text

$ proto 定義と PHP パッケージ(例) 生成物は手コミットせず , バージョン付きパッケー ジとして配布する Mercari では, proto が Merge されたタイミング でそれぞれの言語用に パッケージを配布

Slide 28

Slide 28 text

$ gRPC Client 呼び出し(without Inhouse Wrapper) ベタッと書くと分かり易いが , metadata, timeout, ErrorHandlingの共通化を検討

Slide 29

Slide 29 text

$ gRPC Client 呼び出し(with inHouse Wrapper) 「何を呼ぶか」と「どう呼ぶか」を分 離する "どう呼ぶか "(timeout・認証・エ ラー処理・型・トレーシング)を毎回 書かなくても , デフォルトで正しく動く 状態にしている $greeterService を DI Container に登録すれば , 環境毎に切り替えが柔軟に 可能

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

$ inHouse Wrapper(ClientBuilder 簡略版抜粋 ) $interceptors, $timeoutUsec は省略しているので , よしなに grpc.primary_user_agent で 共通 UA を指定

Slide 32

Slide 32 text

$ inHouse Wrapper(BaseService 簡略版) Status code をまとめたり , ErrorDetail を Parse したり 開発者は BaseService を継 承し、呼びたい API を指定し, invoke を呼ぶ

Slide 33

Slide 33 text

$ inHouse Wrapper(CallInvoker, UnaryCall 簡略版)

Slide 34

Slide 34 text

$ CallInvoker, UnaryCall 解説

Slide 35

Slide 35 text

$ まとめ ● PHP Application の 現在 ○ 規模感, 運用 ● PHP Application の Service 間連携の歴史 ○ 2018 - 2020 移行期初期 - オンプレミス /GCE ○ 2020 - 2024 移行期中期 - GKEへの移行 ○ 2025 - 2026 現在 - クラスタ内直接通信 ● PHP Application の gRPC Client の実際 ○ Application に任せること , istio(Envoy) に任せること ○ Go の gRPC 使用との違いとチャレンジ ● gRPC Client 利用コードの解説 ○ 簡略化した Application の呼び出しコード解説

Slide 36

Slide 36 text

$ 積極採用中! ● 今日の話とは違いますが , 大規模サービスの DBに興味のある方ぜひ! ○ 今日の話は mercari-api チーム側の話でしたが , もう一つのチームで積極採用し ています! ○ ご興味のある方 , カジュアル面談いたします。 ○ このチームに関しては現在 , 英語はやる気があったら良い , くらいの募集としています。 むしろミッションクリティカルな DB を高いレベルで運用していきたい , 改善していきた い, という方を積極採用しています! ■ 止めずに移行 メルカリの 40TB超・50台MySQLからTiDB Cloudへ エンジニアリング | 株式会社メルカリ - 採用情報