文系プログラマによるTIPSブログスマートフォン用の表示で見る文系プログラマによるTIPSブログ文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。pillowTwitterGooglePocketしょうもないメモ書きみたいな記事です〜私は業務で結構長く続く負債満載プロジェクトを担当していたのですが、ようやくAWS移行する事になり、絶賛デスマ中なのです。私はインフラエンジニアではなく、片手間でインフラもやるサーバサイド・フロントエンド?エンジニアです。成果物をzip化するlambdaの設定TIPS出力先フォルダは作成しておかなくてもよいソース画像パスを維持したまま別バケットに出力したいlambdaのメモリ割り当て量おまけ1:私と画像変換の変遷javaのawtによる直列画像変換。Lambdaを起動して画像変換する。変換元画像はjpgのみとし、jpgからjpgを生成する。Pillowを使用する。変換元となるオリジナル画像からアスペクト比を保ったサムネイルを2種類生成し、画質を調整して別のバケットに画像をアップロードする。オリジナル画像はサイズは変えず、画質の調整のみを行う。サムネイルの縦横サイズ、画質のクオリティ等をパラメータ化し、環境変数のみで挙動を変える事ができる。ステージング・本番環境などの環境毎にサムネイル生成ロジックを用意せず、環境を変えるだけで済むようにして全環境同一のコードを利用する。現状だと画像変換に関してはnode.jsよりpythonの方が速いようですね。Pillowを使います。Pillowを使って画像変換します。そのためには最低限以下が必要です。v3.6のインストール。pipのインストール。lambdaにはImageMagickが最初からインストールされていますが、Pillowはインストールされていません。従って、lambdaの登録時にzip圧縮する際に一緒にPillowを内包する必要があります。Pillowを内包するために今回pipを使うので、pipを使えるようにしておきます。python自体のインストールはpyenvを使うと、v2.7系とv3.6系を共存できるので、それらで行うといいと思います。-lでv3.6系が列挙されない場合はpyenv自体のバージョンが古いので、バージョンアップして下さい。pipが無い場合は、以下のようにインストールする事ができます。pip検証していませんが、mac上でこれらを行うとlinux版と異なるモジュールの場合がある可能性があるため、この作業はlinuxサーバ上で行った方が安全です。labmdaにアップロードするzipを生成するまずはPillowをローカルに展開する準備です。setup.cfg[install]install-purelib=$base/lib64/pythonこれを配置しておく事で、zipに内包したライブラリを、lambda上で利用できるようになります。docs.aws.amazon.comPillowをローカルに展開するシステムにインストールするのではなく、カレントディレクトリにファイル・フォルダを展開するイメージです。.これでpipでインストールされるPillow関連ファイル群が、カレントディレクトリに展開されます。サムネイル生成ファイル以下を「thumbnail_util.py」というファイル名で保存します。ファイル名はlambda設定時に使います。eos.environの部分が、lambda側で設定する環境変数から値を取得しています。lambdaは恐らくdocker的なコンテナで、普通にOSが起動しています。lambdaのコンテナからオリジナル画像があるs3のバケットから目的の画像をダウンロードし、lambda内で画像変換し、変換したものを別のs3にアップロードします。s3に画像が配置されるとこれが起動します。lambdaが起動する事になり、複数画像を配置すれば、その数だけlambda(コンテナ)が並列でガンガン起動していきます。成果物をzip化するzip時の注意点ですが、zipを解凍した際にファイルが展開されないといけません。zipを解凍した際に以下の構造になっている場合はNGです。thumbnail_util.py以下のようになっていればOKです。olefile-0.44-py3.6.egg-infoOleFileIO_PL.pysetup.cfgthumbnail_util.pyzipファイル名は何でもOKです。自由に命名して下さい。「ハンドラ」ですが、どの関数を呼ぶかを記述します。lambdaから見るとどのファイル名のどの関数なのかが解らないので、「ファイル名.関数名」という指定をしてあげる必要があります。ここで登場する「環境変数」ですが、ここに指定した値を、関数から「os.environ」で取得する事ができます。このままだとlambdaは自動起動してくれないので、「何をした時にlambdaを起動するか」という「トリガー」を指定します。イベントソースにS3を指定したいのですが、プルダウンの下の方に合って探すのが大変なので、s3とフィルタした方が速いです。「イベントタイプ」には、「オブジェクトの作成(全て)」を指定しました。細かく指定できますが、ファイルを新規アップロードした時だけでなく、上書きされた場合等を考慮して全てを選択しました。ここは要件によって任意に変更するといいと思います。「プレフィックス」で「バケット内のどのパスに配置されたらイベントを起動するか」を設定します。「サフィックス」ではファイルの拡張子等の条件を付ける事ができます。イベントの設定ができたら、保存ボタンをクリックして完了です!後はs3のinputフォルダに画像を配置すると、別のバケットに画像がアップロードされます。TIPS出力先フォルダは作成しておかなくてもよい例えば「output」というフォルダに画像を出力するとして、outputフォルダを事前に生成しなくていいのか?と思うかもしれませんが、不要でした。いうか、S3は実はフォルダという概念が無いので、フォルダの生成という事自体が不要なのです。dev.classmethod.jpソース画像パスを維持したまま別バケットに出力したいthumbnail_util.pyに以下のコードがあったと思います。event['Records'][0]['s3']['object']['key']これは、アップロードされたバケット内の画像ファイルパスが取得されます。これが文字列で取得できるので、後は以下のように普通に文字列操作して出力先を加工できます。今回検証した感じだと、最低の128MByteで十分なようです。速度が遅かったりOutOfMemoryするようなら任意に増やすといいと思います。おまけ1:私と画像変換の変遷おまけが実は本編的なやつです。私が担当している業務での画像変換の変遷です。javaでやっていたようです。(私は担当してません)たまに使われるawtによる画像変換ですが、これがもう異常な程遅く、画質も良くはありません。余りにも処理が遅く、なんと次の日の定時バッチ実行までに終わらない事がある程でした。ImageMagickによる並列画像変換。「オマエ、コノジョウキョウ、ナントカシタマエ!」と。いう事で、できるだけ時間をかけず、且つできるだけ簡単に解決する方法を考えました。そこで私はjavaのawtの画像変換ではなく、ImageMagicのconvertコマンドによる画像変換を試し、相当速度アップ(詳細に速度比較してません)し、画質も改善した事を確認します。最後の問題はトータルの実行時間です。何十時間もかかっている実行時間を何とかしなくてはなりません。簡単な解決策は直列実行を並列実行に変えるというものでした。bashだけで並列数を管理するのが(インフラの都合上)ちょっと難しかったので、javaでスレッド数を管理する事にしました。cronが起動し、cronで画像変換javaバッチを起動。javaバッチからbashのconvertコマンドを呼び出し、並列8スレッドで画像変換を実行。全てのスレッドが実行完了するのをawait的に待ち、完了したらログ出力+メールで通知。こんな感じに直しました。並列実行の効果は抜群で、awt時代は1秒間に数枚程度しか画像変換できませんでしたが、変更後は1秒間に約60〜70枚画像変換できるようになりました。最終的に画像変換は30分〜1時間で完了するまでに高速化する事ができました。その新画像変換プログラムで数年運用し、何とか業務は回っていましたが、問題はありました。画像を変換しているサーバを画像サーバと呼びますが、画像サーバは当然冗長化され、複数台で構成されています。画像サーバといいつつメールサーバも兼任していたり、webサーバがインストールされていたり、もはや役割が曖昧なサーバです。画像サーバに配置された画像を全サーバに同期させるのにGlusterFSを使ってますが、くっそ重く、CPU使用率が上がりやすい。GlusterFSを管理できる人が全員退職し、もはや誰も触れず、秘伝のタレとすら呼べない、ロストテクノロジー状態です。いうのは難しいものなので、画像変換プログラムを触れる人が私以外いない。画像変換負荷に引きづられて他の処理(webサーバへのアクセスやメール送信処理)が遅い・失敗する事が多々有った。兼任させつつ並列処理を回し、それをディスク同期してるんですもの。教科書に載せてもいいくらいの悪い例ですね。AWS化する事になり、色々とインフラを変えます。S3なのでサーバ間のディスク同期要らず。Lambdaによるリアルタイム並列画像変換。こんな感じに変更し、以下の負債を解消する事ができました。物理サーバが壊れた場合にインフラベンダのディスク交換に1ヶ月を要する、という負債を解消。GlusterFSで問題が起きたら実は誰も修復できません、という負債を解消。画像サーバの負荷による他プログラムへの影響、という負債を解消。並列処理の難しさ、という負債を解消。画像サーバに画像を配置する別開発ベンダが、公開終了したデータの画像を削除してくれず、延々と画像が増え続ける、という負債を解消。サーバは無くなり、負荷は全部S3・lambda側が吸収してくれるようになりました。画像を削除してくれない問題も、S3に延々と蓄積していく事になりますが、ライフサイクルを設定できたり、物理サーバと構造が異なる事によって増えてもまあ問題無い(多分)ので、安心感があります。問題点やはりAWS移行後も問題点はあると思います。お客さんは従量課金に慣れていないオンプレ環境では無料でできていた画像変換が、AWS移行後は従量課金となります。普通に考えれば、オンプレで無料で実現していた件は、裏で膨大な人件費がかかっている事は想像付くと思いますが、お客さんはそれが理解できません。「なんでお金かかるの!?お金かえして!!」みたいな反応をします。ここは落ち着いて、無料だと思っていた今までの画像変換は、裏で開発ベンダがせっせと超高額な人件費を消費し、それを開発費として請求していたのでコストが見えて無かっただけですよ〜、的な説明をするしかありません。クラウドに不慣れなメンバーは一杯いる問、今の時代、AWS・GCP・Azureのどれか触った事あるでしょ???答、そんな事はありません。パートナー社員はインフラ未経験者は多く、「私はインフラはさっぱりです」という人は本当に多いです。開発メンバーはプロパー社員が1人(アーキテクト兼インフラ兼PM担当)、パートナー社員が複数人、という構成は世の中に一杯あると思いますが、そういう場合に「今後これチームメンバーに任せられるかな?」という不安は拭い去れません。こればっかりはチームメンバーに根気よくレクチャーし、勉強して貰うしかありませんね。おまけ2:s3にアップロードする前に画像変換したい例えば既存プロジェクトで、構成を変えずに画像変換したいぞ!という要望です。処理フロー的には以下をイメージします。pull取得したソースコード内から画像を探索し、画像変換。各サーバに配布してデプロイ。こんな感じでpullとデプロイの間に画像変換を挟みます。私の担当業務ではこれをdockerで行っています。linuxベースの画像変換コンテナを起動。コンテナが起動すると、ImageMagickが起動し、コンテナ内で並列に画像変換が行われる。画像ファイルはvolumeマウントされているので、コンテナ内の変換結果はそのままホスト側に配置されている。その処理の一部ですが、以下のような形で行っています。https://hub.docker.com/r/treetips/alpine-imagemagick-mogrify-example/ImageMagicには、フォルダ内の画像ファイルを一括変換するmogrifyというコマンドがあります。ImageMagickこれを利用しつつ、parallelというコマンドを使って、複数フォルダに対してmogrifyを実行しています。並列処理を並列処理している感じです。dockerで画像変換する際の注意点として、コンテナ内のowner:groupと、ホスト側のowner:groupのマッピングです。何も考えずにコンテナ側で画像変換しても、owner:groupは恐らくgidの数字が表示されてしまっていると思います。コンテナとホストでowner:groupが共通でないので、gid・uidが揃っていないので、こうなってしまいます。コンテナで作業ユーザを追加する際に、ホスト側で予めuid・gidを取得し、そのidを使ってコンテナ内の作業ユーザを作成、その作業ユーザでmogrifyすると、コンテナ内で変換した画像のowner:groupはホスト側と同一になります。hoge:hoge」しちゃってもいいかなと思います。Pillowで行ったらもっと速くなるかもしれませんね。おまけが本編化してしまいました。lambdaを使って画像変換する例はネット上でよく見かけますが、手段が目的にならないように注意したいですね。「こういう問題があるからs3+lambdaで解決しよう!」はとても良いのですが、「s3+lambdaを使いたい、だから画像変換で使ってみよう」だと、思わぬ部分で要件を満たせなかったりします。クラウドでは「あれが使ってみたい!」という気持ちが先行して、手段が目的になってしまい、炎上するケースが後を絶たないので、そこは本当に注意していきたいものです。週間)昔は業務系SIer、今はベンチャー企業でプログラムを書いています。INFILEを実行できるようにするmacのAutomatorでhomebrewのコマンドをFinderのサービスから実行できるようにするReactオススメ書籍React自体の基礎、AtomicDesignの適用、CSSの運用手法の歴史的な経緯とメリットデメリット、Reduxの基礎、redux-sagaによる非同期処理、サーバサイドレンダリング、テスト、lint、を学ぶ事ができます。単行本(ソフトカバー)この商品を含むブログを見るAngularオススメ書籍Angularを学ぶなら絶対以下がおすすめです!バインディング、ディレクティブ、パイプ、フォーム、コンポーネント、サービス、ルーティング、httpClientによる非同期httpリクエスト、テスト、angular-cli、を非常に丁寧な説明で網羅的に解説しています。大型本この商品を含むブログを見るSEOオススメ書籍SEOを学ぶなら絶対以下がおすすめです!クローラに対して何をどうすればサイトの巡回効率・速度を上げる事ができるのか、どういったマークアップをする事が標準仕様なのか。巷に溢れる業者による経験則に基づくオレオレSEO情報は一切無く、全てGoogle等のオフィシャルな情報に基づいて何をすべきか、どんな手段があるのかを解説されています。プログラマな私が業務で行った施策が多く書かれており、プログラマ寄りで高度な内容となっており、巷のビギナー向けの曖昧な情報集とは一線を画しています。Amazonアソシエイト・プログラムの参加者です。reserved.スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。