Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ZOZOのマイクロサービス共通規約を守るための取り組み

 ZOZOのマイクロサービス共通規約を守るための取り組み

iskitahara

May 24, 2023
Tweet

Other Decks in Technology

Transcript

  1. © ZOZO, Inc. https://zozo.jp/
 3 • ファッションEC
 • 1,500以上のショップ、8,400以上のブランドの取り扱い
 •

    常時95万点以上の商品アイテム数と毎日平均2,900点以上の新着 商 品を掲載(2023年3月末時点)
 • ブランド古着のファッションゾーン「ZOZOUSED」や
 コスメ専門モール「ZOZOCOSME」、靴の専門モール
 「ZOZOSHOES」、ラグジュアリー&デザイナーズゾーン
 「ZOZOVILLA」を展開
 • 即日配送サービス
 • ギフトラッピングサービス
 • ツケ払い など

  2. © ZOZO, Inc. マイクロサービスを展開する際の課題 6 マイクロサービスの共通規約とは 例) • アクセスログ •

    認証ミドルウェア • HTTPヘッダーのキー値 • エラーレスポンス など 共通規約は社内の開発ガイドラインで定義されたルールとなります
  3. © ZOZO, Inc. マイクロサービスを展開する際の課題 • こまごまとした共通規約の違反 ◦ 例)既存の用途における規約外のHTTPヘッダーの利用 ◦ 例)エラーレスポンスのフォーマット違反

    • 似たような汎用機能が各サービスに点在 ◦ 今までのサービスを流用しての開発が原因 … 7 マイクロサービスのサービスが増えるにつれて。。。
  4. © ZOZO, Inc. マイクロサービスSDKの構築 11 マイクロサービスSDKの範囲 • マイクロサービスの共通規約を実現する機能 ◦ アクセスログ、認証ミドルウェア、HTTPヘッダーのキー値、

    エラーレスポンス... • マイクロサービス以外でも利用できるライブラリ ◦ Optional型、エラーの伝搬、contextの伝搬...
  5. © ZOZO, Inc. マイクロサービスの共通規約を実現する機能例 HTTPヘッダーのキー定義と値の持ち回り 12 const ( // APIクライアントを判別するためのヘッダー

    HeaderKeyAPIClient = "zozo-api-client" // ios zozo-api-clientヘッダーの値 APIClientIOS = "zozotown-ios" … return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() if apiClient := r.Header.Get(constant.HeaderKeyAPIClient); apiClient != "" { ctx = SetAPIClient(ctx, apiClient) } …
  6. © ZOZO, Inc. マイクロサービスの共通規約を実現する機能例 エラーレスポンス 13 type Error struct {

    Type ErrorType Message string Detail any } var ErrUnauthorized = Error{Type: Unauthorized, Message: "unauthorized error"} … var Unauthorized = ErrorType{Type: "unauthorized", Status: http.StatusUnauthorized} … var NotFound = ErrorType{Type: "not_found", Status: http.StatusNotFound} var NotExistsData = ErrorType{Type: "not_exists_data", Status: http.StatusNotFound}
  7. © ZOZO, Inc. マイクロサービス以外でも利用できるライブラリ例 Optional型 14 type Optional[T any] struct

    { value T valid bool } func (o Optional[T]) IsNull() bool { return !o.valid } func (o Optional[T]) Unwrap() (T, error) { if o.IsNull() { var result T return result, xerrors.New("optional value should …") } return o.value, nil } func Some[T any](v T) Optional[T] { return Optional[T]{ value: v, valid: true, } } …
  8. © ZOZO, Inc. SSH経由でプライベートリポジトリにアクセス GitHubに公開鍵を登録し ssh -T [email protected] が通る状態で接続 16

    git config --global url."ssh://[email protected]/<アカウント>".insteadOf "https://github.com/<ア カウント>" go env -w GOPRIVATE=github.com/<アカウント>/<リポジトリ> go get -u github.com/<アカウント>/<リポジトリ> GOPRIVATEを設定することで GONOPROXY, GONOSUMDB にも設定されます。 https://go.dev/ref/mod#private-modules
  9. © ZOZO, Inc. Dockerfileのプライベートリポジトリにアクセス設定 GitHub Personal access token を secret

    で受け取り接続 17 FROM golang:1.20.2-bullseye as builder … RUN --mount=type=secret,id=github_token git config --global url."https://x-access-token:$(cat /run/secrets/github_token)@github.com/<アカウント>/".insteadOf "https://github.com/<アカ ウント>/" ENV GOPRIVATE=github.com/<アカウント>/<リポジトリ> COPY go.mod go.sum ./ RUN go mod download RUN : > ~/.gitconfig Dockerfile
  10. © ZOZO, Inc. CI (GitHub Actions) でのbuild設定 buildする際にtokenを渡しプライベートリポジトリに接続 18 -

    name: Build and save image … run: | build_option="-t '${IMAGE_NAME}':latest --target '${BUILD_TARGET}'" if "${BUILD_WITH_PRIVATE_REPOSITORY}"; then export GITHUB_TOKEN=${{ steps.generate-github-app-token.outputs.token }} build_option="${build_option} --secret 'id=github_token,env=GITHUB_TOKEN'" fi cmd="docker build ${build_option} '${DOCKERFILE_PATH}'" eval "${cmd}" … yaml
  11. © ZOZO, Inc. compose.yaml の GitHub Personal access token の設定

    19 • ファイルで渡す(ファイル名 github_token) secrets: github_token: file: ./github_token secrets: github_token: environment: GITHUB_TOKEN • 環境変数で渡す(環境変数名 GITHUB_TOKEN) compose.yaml compose.yaml