35
メルマガシステム 失敗談 尾形 鉄次 (OGATA Tetsuji) Twitter: @xtetsuji 2013/5/24 PerlBeginners#8

メルマガシステム失敗談 #perlbeginners

Embed Size (px)

DESCRIPTION

2013/05/24に行われたPerlBeginners#8でトークした「メルマガシステム失敗談」のスライドです。当社が失敗したわけじゃないですよ、外注の失敗談です。当時の数々の縛りプレイの中、それを見事に復旧させた当時の当社のPerl Hacker達の凄まじい技術のお話です。

Citation preview

Page 1: メルマガシステム失敗談 #perlbeginners

メルマガシステム失敗談

尾形 鉄次 (OGATA Tetsuji)

Twitter: @xtetsuji2013/5/24 PerlBeginners#8

Page 2: メルマガシステム失敗談 #perlbeginners

自己紹介

• 尾形 鉄次 (OGATA Tetsuji)

• Twitter: @xtetsuji

• Blog: http://post.tetsuji.jp/

• 専門領域:Apache mod_perl

• よく行く:Hokkaido.pm、Hachioji.pm

Page 3: メルマガシステム失敗談 #perlbeginners

所属紹介• 株式会社fonfun(フォンファン)http://www.fonfun.co.jp/

• リモートメールhttp://rmail.jp/

• 中心事業として、ウェブメールをやっている会社から来ました(質問歓迎です!)

• 開発設計や新規技術の研究が私の主な仕事

Page 4: メルマガシステム失敗談 #perlbeginners

遍歴• 2000年頃:i-mode向け統合ウェブメールサービス「リモートメール」(リモメ)を始める(当時としては先進的)

• →サーバ1台 + Perl4? CGI

• 2003年:私が入社→システムを第4世代に作り替えている最中だった

Page 5: メルマガシステム失敗談 #perlbeginners

遍歴• 2005年頃から会社規模が大きくなり、リモメのようなケータイキャリア課金代行サービスによるBtoC以外に、受託事業もやりはじめる

• 子会社や他の外注にシステム発注

• そのアドバイザー役で多忙に

Page 6: メルマガシステム失敗談 #perlbeginners

外注を使う• 企画「受託でメルマガシステム作る事になったから外注に発注する」

• 外注「はい作ります」

• 横で眺めているだけの簡単な(?)お仕事

• …のはずだった

Page 7: メルマガシステム失敗談 #perlbeginners

炎上

Page 8: メルマガシステム失敗談 #perlbeginners

炎上• 多重配信。配信無限ループ。連日徹夜

• 当時でこそ、メルマガシステム開発経験のある外注なんて、ほとんどいない

• なぜか尻拭いはこちら側になる

• 若いから何とか乗り切れたようなもの

Page 9: メルマガシステム失敗談 #perlbeginners

何がダメだったのか

Page 10: メルマガシステム失敗談 #perlbeginners

何がダメだったのか• 参考情報:孫請けの開発言語はPHP

• PHPという言語に罪はないけど、正直PHPの外注は慎重に選んだほうがいい

• MySQLにある配信メルマガテーブル

• そして秘技、毎分cron

Page 11: メルマガシステム失敗談 #perlbeginners

CREATE TABLE メルマガ ( id INT NOT NULL AUTO INCREMENT, 配信日時 DATETIME,

配信完了フラグ INTEGER,

メルマガ本文 TEXT,

PRIMARY KEY id);

メルマガ配信テーブル• そのままは公開できないけど、概要としてはこんな感じだった

Page 12: メルマガシステム失敗談 #perlbeginners

メルマガ配信テーブル

• 管理画面も提供されていて、納品先のお客様が配信日時指定をしたメルマガをセットできる

• その内容は配信テーブルにINSERT

• 配信先ユーザはユーザテーブルで管理

Page 13: メルマガシステム失敗談 #perlbeginners

毎分cron

• 5つのアスタリスクのcron

• * * * * * www-data php /path/to/mailmag.php

• 配信テーブルを毎分監視して、未配信メルマガがあったら配信処理開始

• これが意外にヤバイ→なぜでしょう?

Page 14: メルマガシステム失敗談 #perlbeginners

毎分cronの罠• 一つのプロセスが1分以内に終わらないと次のプロセスが起き上がる

• 何らかの排他処理をしないとヤバイ

• 多重処理が発生→システムが重くなる→さらに多重処理が発生→無限ループ

Page 15: メルマガシステム失敗談 #perlbeginners

テーブル設計ミス

• しかもこれ、INTの「配信完了フラグ」が「未配信」と「配信済み」の2つしかなかった!→後は分かりますね…

• 少なくとも「配信途中」というフラグは必要だろ!

Page 16: メルマガシステム失敗談 #perlbeginners

突然の作り直し

• 外注、ギブアップ!

• ブチギレた発注元「外注使ってんじゃねーよ。おまえの会社、ウェブメールやってて開発者いるんだろ?そいつらが作り直せよ外注絶対使うなよコラ」

Page 17: メルマガシステム失敗談 #perlbeginners

Perlプログラマの精鋭部隊、集合!

Page 18: メルマガシステム失敗談 #perlbeginners

Perl Hacker招集

• ここでようやくPerl登場

• 社内の精鋭が集められて設計会議

• 早朝に集まって再設計素案作成

Page 19: メルマガシステム失敗談 #perlbeginners

環境の縛りプレイ• 特に製品納品型の受託の場合、「CentOSにあるRPMしか…」とか多い

• PerlもPerl5.8コア+αモジュール縛り

• 迫り来る時間で他のモジュールのRPM

化とか、できる余裕すらなかった

Page 20: メルマガシステム失敗談 #perlbeginners

再設計計画DB編• 既存のMySQLのテーブルの設計変更はしない→闇仕様の中、危険すぎる

• 配信フラグINTだった→これを利用して配信途中の様々な状況を詳細に記録

• 新たなテーブルで既存のテーブルを参照して、それの不備を補正する

Page 21: メルマガシステム失敗談 #perlbeginners

再設計計画Perl編• 既存のPHPの配信プログラム完全廃棄

• ヤバいコードが色々書かれていた…

• Perl5.8縛り

• Net::SMTPの登場(Perl5.7で既にコア)

• DBD::mysqlはあった!助かった!

Page 22: メルマガシステム失敗談 #perlbeginners

Net::SMTP

• SMTPをクラス化したPerlモジュール

• 生のSMTPに近くて分かりづらい→その分、高速化や細かい処理ができる

• メール(MIME構造)構築や、デコりたいとかは Email::* などを探すとよいかも

Page 23: メルマガシステム失敗談 #perlbeginners

もっと簡単に• メール送信だけなら、最近だと

Email::Senderがいいらしい

• 最近MooseからMooに依存が変わって、使う心理的障壁が低くなった

• Net::SMTPと見比べてみるといいかも

Page 24: メルマガシステム失敗談 #perlbeginners

再設計計画cron編• 縛りプレイ、当時の情勢等により、

JobQueueやイベント駆動などは使えず

• 毎分cronをそのまま使う

• その分、前述の配信フラグの強化で、排他処理を完璧に行う

Page 25: メルマガシステム失敗談 #perlbeginners

再設計計画cron編• psのコマンド出力を見て排他処理

• 1分前に起動された「同じプログラム」がまだいるかも詳細にチェックするfor (`ps auxwww`) { chomp; my @row = split /\s+/, $_; my ($pid, $name) = @row[1,10]; if ( $pid != $$ && $name eq $0 ) { # pidが違う自分自身と同じ名前のやつがいる! exit; }}

Page 26: メルマガシステム失敗談 #perlbeginners

努力の甲斐あって

• これらの補修で「Perl版新メルマガ配信プログラム」が完成した

• 先方に訪問、新設計のプレゼン

• その後、見事配信しきった

Page 27: メルマガシステム失敗談 #perlbeginners

参考として• レンタルサーバスペックや、I/Oボトルネックは2006年当時とそれほど大きな差は無い

• 安いレンタルサーバ1台で配信しきれるメールは大体800通/1分あたりかな(様々な状況により数値は変わってきます)

Page 28: メルマガシステム失敗談 #perlbeginners

考えが甘い開発者• 数人で数十アカウントを作って配信、というテストは完全に甘すぎる

• 少なくとも数千件のメールアドレスに短い間隔でセットした複数のメルマガがあるといった状況でテストしないとダメ

Page 29: メルマガシステム失敗談 #perlbeginners

その後• 自社開発のECサイトでメルマガ開発をするときにこの仕組みを入れた→成功

• エラーメールの戻りを処理するのをPostfix pipeでやったらForkコストが無視できなかった→今ならQpsmtpdなど

• このあたりのPostfix話は別の場所で…

Page 30: メルマガシステム失敗談 #perlbeginners

その後• 時が経ち他の部署でメルマガシステムをまた諸事情で外注することとなった

• アドバイザーとして1万アドレス用意、条件を提示して「ここに無事配信しきれたら合格」としたら、期待通り失敗してくれた→その後修正してくれました

Page 31: メルマガシステム失敗談 #perlbeginners

ここ最近• 受託が下火に、柱事業に力を入れるという方向になってくれた

• メーリングリストシステムを開発した

• http://rmail.jp/service/s_groupmail.html グループメール

• これの中の実装はApache2+mod_perl2

Page 32: メルマガシステム失敗談 #perlbeginners

詳細• 詳細は拙作の「mod_perl温故知新 ~

Perl CGIの高速化からメールサーバまで~」が詳しいです

• http://www.slideshare.net/xtetsuji/mod-perl-hokkaidopm5

• 縛りが無ければQpsmtpd使うのが良い

Page 33: メルマガシステム失敗談 #perlbeginners

現在• 最近有料メルマガブームだし、競合もそれほど少ないからメルマガシステムまたいいかもなぁ、とか考えている

• 高速配信が課題→目標高く100万通/1分

• 設計案は何となく頭の中にある

Page 34: メルマガシステム失敗談 #perlbeginners

続きは懇親会で• 気軽にご質問ください

• 懇親会にも出ます

• メールサーバ勉強会があればPostfix側をもっと詳細にしゃべりたい

• Perl製のQpsmtpdの話もどこかでしたい

Page 35: メルマガシステム失敗談 #perlbeginners

ご清聴ありがとうございました