Slide 1

Slide 1 text

Copyright © M&A Cloud All rights reserved. ある日突然、 Laravel Queue Workerが壊れた PHPerKaigi2021/LT Kenjiro Kubota

Slide 2

Slide 2 text

Copyright © M&A Cloud All rights reserved. Profile 2 久保田 賢二朗 kubotak-is kubotak_public kenjiro.kubota 株式会社M&Aクラウド JavaScript Go PHP https://kubotak.page

Slide 3

Slide 3 text

Copyright © M&A Cloud All rights reserved. 前提知識 前提知識 ● AWS ElasticBeanstalk(以降EB)のWebサーバーとWorkerサー バー上でLaravel Queuesを利用したJobを運用 ● メッセージングシステムとしてAWS SQSを利用

Slide 4

Slide 4 text

Copyright © M&A Cloud All rights reserved. アーキテクチャ

Slide 5

Slide 5 text

Copyright © M&A Cloud All rights reserved. ある日突然、 Laravel Queue Workerが壊れた

Slide 6

Slide 6 text

Copyright © M&A Cloud All rights reserved. 何もしてないのに壊れた ● というわけではない。 ● PHP7.2のEB環境からPHP7.4にアップグレード後 に死んだ ● EB環境が変わったことでなぜ死んだかは不明 何もしてないのに壊れた

Slide 7

Slide 7 text

Copyright © M&A Cloud All rights reserved. なぜ死んだのか なぜ死んだのか ● LaravelのQueueはJobというクラスをPHPシリアライズした文字 列のメッセージキューでやり取りする ● Workerではメッセージから取得した文字列をアンシリアライズ することでPHPのコードとして実行する ● アンシリアライズが失敗

Slide 8

Slide 8 text

Copyright © M&A Cloud All rights reserved. なぜアンシリアライズが失敗するのか なぜアンシリアライズが失敗するのか 原因が不明だがシリアライズ前にスペースが2つ連続で含まれる文字 列が、メッセージキューから取得されたあとのメッセージではスペー スが1つに纏められている事象があった (SQSからEBWorkerがHTTPに変換する際)

Slide 9

Slide 9 text

Copyright © M&A Cloud All rights reserved. コードで説明 PHPシリアライズされた状態の文字列

Slide 10

Slide 10 text

Copyright © M&A Cloud All rights reserved. コードで説明 アンシリアライズするともとのインスタンスに戻る

Slide 11

Slide 11 text

Copyright © M&A Cloud All rights reserved. コードで説明 12345678910111213 型:値

Slide 12

Slide 12 text

Copyright © M&A Cloud All rights reserved. コードで説明 アンシリアライズに失敗するとfalseとなる 11 実際の文字数と異なる

Slide 13

Slide 13 text

Copyright © M&A Cloud All rights reserved. わけがわからない上に影響範囲が大きい 対応

Slide 14

Slide 14 text

Copyright © M&A Cloud All rights reserved. 「文字列全部Base64エンコードしちゃお」 対応

Slide 15

Slide 15 text

Copyright © M&A Cloud All rights reserved. Base64 Base64 Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字 を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱う ためのエンコード方式である。 MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子 メールにて広く利用されている。具体的には、A–Z, a–z, 0–9 までの62文字 と、記号2つ (+, /)、さらにパディング(余った部分を詰める)のための記号と して = が用いられる。 この変換によって、データ量は4/3(約133%)になる[1]。また、MIMEの基準 では76文字ごとに改行コードが入るため、この分の2バイトを計算に入れると データ量は約137%となる[2]。 出典: フリー百科事典『ウィキペディア(Wikipedia)』

Slide 16

Slide 16 text

Copyright © M&A Cloud All rights reserved. Base64 Base64 Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字 を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱う ためのエンコード方式である。 MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子 メールにて広く利用されている。具体的には、A–Z, a–z, 0–9 までの62文字 と、記号2つ (+, /)、さらにパディング(余った部分を詰める)のための記号と して = が用いられる。 この変換によって、データ量は4/3(約133%)になる[1]。また、MIMEの基準 では76文字ごとに改行コードが入るため、この分の2バイトを計算に入れると データ量は約137%となる[2]。 出典: フリー百科事典『ウィキペディア(Wikipedia)』 スペース撲滅

Slide 17

Slide 17 text

Copyright © M&A Cloud All rights reserved. __serialize/__unserializeを利用 __serialize/__unserializeを利用 ● PHP7.4から追加されたマジックメソッドの __serialize/__unserializeを利用 ● 幸いにも弊社アプリケーションでは文字列をプリミティブではな くStringValue型という独自クラスで定義していたので、このク ラスに対してマジックメソッドを追加 ※7.4以前なら__sleep/__wakeupが代用できる

Slide 18

Slide 18 text

Copyright © M&A Cloud All rights reserved. __serialize/__unserializeを利用

Slide 19

Slide 19 text

Copyright © M&A Cloud All rights reserved. __serialize/__unserializeを利用

Slide 20

Slide 20 text

Copyright © M&A Cloud All rights reserved.

Slide 21

Slide 21 text

Copyright © M&A Cloud All rights reserved. まとめ まとめ ● メッセージングシステムを利用するときはPHPシリアライズの文字 列ではなくJSON形式のような汎用的な形式が良いと思う! ○ とはいえスペースが消えちゃうのはよくわからん ● プリミティブな値ではなくラッパーした型を使っているとこういう ケースで助かるぞ! ● マジックメソッドありがとう!

Slide 22

Slide 22 text

Copyright © M&A Cloud All rights reserved. Thank you for watching :)