0

我想知道为每秒需要处理 30-100 封电子邮件的自研 SMTP 中继服务器实现高可用性的最佳方法是什么。

该服务器本质上是通过各种 smtp 客户端进行身份验证,然后中继到特定的邮件服务器并处理错误,例如邮件服务器不可用等。因此,需要一个队列来包含可能包含大附件的电子邮件消息。为了实现高可用性,系统应该支持集群,我可以将 Windows Clustering 用于主/从活动集群。

我认为电子邮件队列可以驻留在:

  1. 内存(由于明显的原因,此方法已失效。)
  2. 关系管理系统
  3. 文件(我相信这是 IIS 虚拟 SMTP 使用的?)
  4. 嵌入式数据库,例如 SQLite
  5. SQLite 和文件的混合
  6. 一些需要安装和配置的奇特的 3rd 方 Queue 产品?

实现高可用性的常用方法是使用 RDBMS,例如 MySQL,但是除非我拥有强大的 MySQL 服务器,否则将 RDBMS 用于消息队列会显着降低性能。最重要的是,我将不得不实现 MySQL 集群,这并不容易。另外,我在某处读到没有人应该使用 MySQL 作为队列 - http://www.engineyard.com/blog/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why -它会咬你/

或者,我可以使用 SQLite+File,这可能是最快的(除了纯内存)和最容易部署的方法(无需安装),但是 SQLite 没有集群,所以如果服务器崩溃,未发送的消息可能仍然是丢失。

4

1 回答 1

1

2 和 4 是同一个东西 - RDBMS。这是一个糟糕的选择,因为 RDBMS 是针对复杂查询的,并且必须及时维护自身。收集垃圾,重建索引,增长数据库文件......任何时候下一次 INSERT 都会很慢甚至完全被阻塞一段时间。即使在 Firebird 和 Postgress 等基于版本的引擎中也是如此。像 MS SQL 和 SQLite 这样的基于锁的情况更是如此。

如果您希望它可靠,那么您可能会将其实现为几个窄任务工作者,这也将使您受益于使用 OmniThraLibrary 或 AsyncCalls 的多线程。

“接收器”工作人员应该将邮件接收到内存缓冲区中,也许会提取一些元数据表单标题并将其存储到当前接收队列中。由于 Win32 线程很昂贵,最好让一个线程同时处理多个套接字,这是 Erlang/Scala 的“演员”框架。您甚至可以将一些线程移动到单独的 exe 中,例如 qmail 设计的,以使崩溃本地化。将来甚至可以跨计算机集群。

“Dumper”会采用一个孤立的队列并将其转储到一个连续的非 SQL 文件中(由于 HDD 颠簸 data-filesystem-data-filesystem-...,您不想要单独的文件),然后他会切换队列:隔离上述接收队列以进行转储,并将其替换为刚刚清空的队列。“有两个队列并切换它们”是一种常见的“页面翻转”特性,例如在 3D 游戏中使用。TForm.DoubleBuffering 是类似但简化的概念。顺便说一句,您还应该有两个包含这些文件的文件夹,例如上面的内存队列。

“dbkeeper”将类似地获取文件转储之一,将其移动到 RDBMS 中,然后进行切换。

您必须围绕这些切换活动设置这些工作人员之间的通信。每个队列要么接收,要么转储,最小化并发访问(频率和寿命)。

您可能会阅读有关 mailinator 设计的信息 - 它的维护者在跨过一个或另一个瓶颈后几次重构了他的软件,这也可以让您估计这些瓶颈何时开始影响性能。


但实际上,为什么不使用一些现成且经过测试的服务器呢?

于 2012-10-01T10:28:43.660 回答