2008年10月28日火曜日

マルチスレッド・2

ネットワーク関係の例を出して説明してください

メール送信システムを用いて解説する。DMやメルマガ,情報通知等、大量のメールを送信するシステムについて、実例を基にした話。


■ 概要

ネットワークのイメージをかなり単純化してみた。本質としてはこんな感じ。

4つの SMTP サーバは負荷分散のためでは無く「特定の携帯電話キャリアに特化したSMTP(+普通の)」と考えて欲しい。実際には到達率を高めるために外部のサーバを利用している。


さて、例によって設計を描く前に調査。ここで言う「調査」とは分析結果を見て、軽くテストアプリを作ってみること。
いきなり設計書をバリバリ書く人もいるけどね。凄いな…自分には無理なので、先にこういうもので色々やってみる(それから設計する)。


■ セッションタイムアウト

設計前のテストアプリ開発スタート!

まずはWebサービスから。配信先リストをクライアントから受け取り、ドメイン名からPC用とキャリア毎のメールアドレスを分離。すぐに出来たね。テストデータを用意して送信!

[HttpException]: 要求がタイムアウトしました

あ、そうか。Webサービスと言っても、クライアントからリモートメソッドを実行しているだけで、完了を待っている間にタイムアウトした。スレッド化して、出来るだけ早くメソッドの完了を通知してやるべきか。


■ プロセス分離

そうそう。こういう要件があった。

深夜にメールが届くと困るという人がいる。
特定グループのユーザーは夜間帯のメールを保留し、朝にまとめて送信する。

それならスレッドよりも、別プロセスの方が向いている。送信リストを XML でローカルに保存し、.EXE に引数(パス)を渡す設計にしよう。遅延についてはOSのタスク機能を使えば良い。

SMTPサーバの数× 100件(計400件)のテストデータを作って、送信実行!
クライアントにはすぐに完了が通知されるし、タイムアウトしない。でも、延々テストメールが届く…送信ウェイトが原因だ。
「同一のSMTPサーバから、連続して○○件以上のメールが送信された場合は受け取りを拒否する」なんていうメールサーバもあり、数件送る毎に数秒間ウェイト(休憩)を入れている。


■ スレッド

やっぱりスレッドも使おう。先に各SMTP用のコレクションを作っているわけで、この送信メソッドをスレッドプールで実行。


取り合えず速くなった。でも、これで数万件を扱うのは問題がありそう。
これはもうアプリ側の改善よりも「多くのサーバに分散する」というアプローチが必要。ついでにアプリ側で分散用のコレクションを作る際に、宛先ドメインがばらける仕様にしておくと良いね。


ネットワーク関係の例として。こんな感じで。
 

1 件のコメント:

匿名 さんのコメント...

リクエストに答えてくださって、ありがとうございます。
実例に基づくだけあって、不思議と臨場感のある記事ですね。
こういう話は、噛んでふくめるように理論を説明してもらうよりも、実例を見せてもらったほうが、ずっと分かりやすいです。