View
2.203
Download
1
Category
Preview:
DESCRIPTION
2013/05/24に行われたPerlBeginners#8でトークした「メルマガシステム失敗談」のスライドです。当社が失敗したわけじゃないですよ、外注の失敗談です。当時の数々の縛りプレイの中、それを見事に復旧させた当時の当社のPerl Hacker達の凄まじい技術のお話です。
Citation preview
メルマガシステム失敗談
尾形 鉄次 (OGATA Tetsuji)
Twitter: @xtetsuji2013/5/24 PerlBeginners#8
自己紹介
• 尾形 鉄次 (OGATA Tetsuji)
• Twitter: @xtetsuji
• Blog: http://post.tetsuji.jp/
• 専門領域:Apache mod_perl
• よく行く:Hokkaido.pm、Hachioji.pm
所属紹介• 株式会社fonfun(フォンファン)http://www.fonfun.co.jp/
• リモートメールhttp://rmail.jp/
• 中心事業として、ウェブメールをやっている会社から来ました(質問歓迎です!)
• 開発設計や新規技術の研究が私の主な仕事
遍歴• 2000年頃:i-mode向け統合ウェブメールサービス「リモートメール」(リモメ)を始める(当時としては先進的)
• →サーバ1台 + Perl4? CGI
• 2003年:私が入社→システムを第4世代に作り替えている最中だった
遍歴• 2005年頃から会社規模が大きくなり、リモメのようなケータイキャリア課金代行サービスによるBtoC以外に、受託事業もやりはじめる
• 子会社や他の外注にシステム発注
• そのアドバイザー役で多忙に
外注を使う• 企画「受託でメルマガシステム作る事になったから外注に発注する」
• 外注「はい作ります」
• 横で眺めているだけの簡単な(?)お仕事
• …のはずだった
炎上
炎上• 多重配信。配信無限ループ。連日徹夜
• 当時でこそ、メルマガシステム開発経験のある外注なんて、ほとんどいない
• なぜか尻拭いはこちら側になる
• 若いから何とか乗り切れたようなもの
何がダメだったのか
何がダメだったのか• 参考情報:孫請けの開発言語はPHP
• PHPという言語に罪はないけど、正直PHPの外注は慎重に選んだほうがいい
• MySQLにある配信メルマガテーブル
• そして秘技、毎分cron
CREATE TABLE メルマガ ( id INT NOT NULL AUTO INCREMENT, 配信日時 DATETIME,
配信完了フラグ INTEGER,
メルマガ本文 TEXT,
PRIMARY KEY id);
メルマガ配信テーブル• そのままは公開できないけど、概要としてはこんな感じだった
メルマガ配信テーブル
• 管理画面も提供されていて、納品先のお客様が配信日時指定をしたメルマガをセットできる
• その内容は配信テーブルにINSERT
• 配信先ユーザはユーザテーブルで管理
毎分cron
• 5つのアスタリスクのcron
• * * * * * www-data php /path/to/mailmag.php
• 配信テーブルを毎分監視して、未配信メルマガがあったら配信処理開始
• これが意外にヤバイ→なぜでしょう?
毎分cronの罠• 一つのプロセスが1分以内に終わらないと次のプロセスが起き上がる
• 何らかの排他処理をしないとヤバイ
• 多重処理が発生→システムが重くなる→さらに多重処理が発生→無限ループ
テーブル設計ミス
• しかもこれ、INTの「配信完了フラグ」が「未配信」と「配信済み」の2つしかなかった!→後は分かりますね…
• 少なくとも「配信途中」というフラグは必要だろ!
突然の作り直し
• 外注、ギブアップ!
• ブチギレた発注元「外注使ってんじゃねーよ。おまえの会社、ウェブメールやってて開発者いるんだろ?そいつらが作り直せよ外注絶対使うなよコラ」
Perlプログラマの精鋭部隊、集合!
Perl Hacker招集
• ここでようやくPerl登場
• 社内の精鋭が集められて設計会議
• 早朝に集まって再設計素案作成
環境の縛りプレイ• 特に製品納品型の受託の場合、「CentOSにあるRPMしか…」とか多い
• PerlもPerl5.8コア+αモジュール縛り
• 迫り来る時間で他のモジュールのRPM
化とか、できる余裕すらなかった
再設計計画DB編• 既存のMySQLのテーブルの設計変更はしない→闇仕様の中、危険すぎる
• 配信フラグINTだった→これを利用して配信途中の様々な状況を詳細に記録
• 新たなテーブルで既存のテーブルを参照して、それの不備を補正する
再設計計画Perl編• 既存のPHPの配信プログラム完全廃棄
• ヤバいコードが色々書かれていた…
• Perl5.8縛り
• Net::SMTPの登場(Perl5.7で既にコア)
• DBD::mysqlはあった!助かった!
Net::SMTP
• SMTPをクラス化したPerlモジュール
• 生のSMTPに近くて分かりづらい→その分、高速化や細かい処理ができる
• メール(MIME構造)構築や、デコりたいとかは Email::* などを探すとよいかも
もっと簡単に• メール送信だけなら、最近だと
Email::Senderがいいらしい
• 最近MooseからMooに依存が変わって、使う心理的障壁が低くなった
• Net::SMTPと見比べてみるといいかも
再設計計画cron編• 縛りプレイ、当時の情勢等により、
JobQueueやイベント駆動などは使えず
• 毎分cronをそのまま使う
• その分、前述の配信フラグの強化で、排他処理を完璧に行う
再設計計画cron編• psのコマンド出力を見て排他処理
• 1分前に起動された「同じプログラム」がまだいるかも詳細にチェックするfor (`ps auxwww`) { chomp; my @row = split /\s+/, $_; my ($pid, $name) = @row[1,10]; if ( $pid != $$ && $name eq $0 ) { # pidが違う自分自身と同じ名前のやつがいる! exit; }}
努力の甲斐あって
• これらの補修で「Perl版新メルマガ配信プログラム」が完成した
• 先方に訪問、新設計のプレゼン
• その後、見事配信しきった
参考として• レンタルサーバスペックや、I/Oボトルネックは2006年当時とそれほど大きな差は無い
• 安いレンタルサーバ1台で配信しきれるメールは大体800通/1分あたりかな(様々な状況により数値は変わってきます)
考えが甘い開発者• 数人で数十アカウントを作って配信、というテストは完全に甘すぎる
• 少なくとも数千件のメールアドレスに短い間隔でセットした複数のメルマガがあるといった状況でテストしないとダメ
その後• 自社開発のECサイトでメルマガ開発をするときにこの仕組みを入れた→成功
• エラーメールの戻りを処理するのをPostfix pipeでやったらForkコストが無視できなかった→今ならQpsmtpdなど
• このあたりのPostfix話は別の場所で…
その後• 時が経ち他の部署でメルマガシステムをまた諸事情で外注することとなった
• アドバイザーとして1万アドレス用意、条件を提示して「ここに無事配信しきれたら合格」としたら、期待通り失敗してくれた→その後修正してくれました
ここ最近• 受託が下火に、柱事業に力を入れるという方向になってくれた
• メーリングリストシステムを開発した
• http://rmail.jp/service/s_groupmail.html グループメール
• これの中の実装はApache2+mod_perl2
詳細• 詳細は拙作の「mod_perl温故知新 ~
Perl CGIの高速化からメールサーバまで~」が詳しいです
• http://www.slideshare.net/xtetsuji/mod-perl-hokkaidopm5
• 縛りが無ければQpsmtpd使うのが良い
現在• 最近有料メルマガブームだし、競合もそれほど少ないからメルマガシステムまたいいかもなぁ、とか考えている
• 高速配信が課題→目標高く100万通/1分
• 設計案は何となく頭の中にある
続きは懇親会で• 気軽にご質問ください
• 懇親会にも出ます
• メールサーバ勉強会があればPostfix側をもっと詳細にしゃべりたい
• Perl製のQpsmtpdの話もどこかでしたい
ご清聴ありがとうございました
Recommended