有助于优化大量用户提醒

时间:2010-07-12 07:33:58

标签: c# asp.net

每天晚上我都有一个执行asp.net页面的触发器,该方法首先从需要详细信息的DB用户那里检索,然后用他们需要的信息发送电子邮件,例如。在其个人资料中没有图像的用户。一旦我从DB获取数据,我就会使用编码的HTML构建大型字符串并将其分配给MailMessage.Body标记。每个动作/晚上大约有20000个用户收到邮件。存储过程只是根据我不需要优化的标准来获取用户(在制作了适当的索引之后)。

我如何优化它?我可以在ASP.NET中创建一种队列,它将在没有一次动作的情况下整天执行吗?也许我可以使用异步操作每次发送几封电子邮件。

需要建议,如果您对我如何执行每项操作有疑问,以帮助我不要害怕询问,我会回答我只是不知道代码中的哪个地方可能会让您感兴趣。

protected void Page_Load(object sender, EventArgs e)
{
    string type = Request.QueryString["type"];
    string spName = "";
    string message = "";

    switch (type)
    {
        //getUsersWithoutPictures
        case "uwp":
            spName = "getUsersWithoutPictures";
            message = getUsersWithoutPicturesTemplate();
            break;
        //getUsersWithoutText
        case "uwt":
            spName = "getUsersWithoutText";
            message = getUsersWithoutTextTemplate();
            break;
        //getUsersWithoutEnteringWebsiteForTwoWeeks
        case "uwewftw":
            spName = "getUsersWithoutEnteringWebsiteForTwoWeeks";
            message = getUsersWithoutEnteringWebsiteForTwoWeeksTemplate();
            break;
        //getUsersWithoutHobbies
        case "uwh":
            spName = "getUsersWithoutHobbies";
            message = getUsersWithoutHobbiesTemplate();
            break;
        //getUsersWithoutCharateristics
        case "uwc":
            spName = "getUsersWithoutCharateristics";
            message = getUsersWithoutCharateristicsTemplate();
            break;
        //getUsersWithoutActivation
        case "uwa":
            spName = "getUsersWithoutActivation";
            message = getUsersWithoutActivationTemplate();
            break;
        default:
            Response.Write("failure");
            Response.End();
            break;         
    }

    DataTable recipientsList = new DataTable();
    using (SqlConnection cn = cms.connect("someconnectionstring"))
    {
        SqlDataAdapter adp = new SqlDataAdapter(spName, cn);
        adp.SelectCommand.CommandType = CommandType.StoredProcedure;
        adp.Fill(recipientsList);
    }

    foreach (DataRow row in recipientsList.Rows)
    {
        try
        {
            IPHostEntry emailHost = Dns.GetHostEntry(row["email"].ToString().Remove(0, row["email"].ToString().LastIndexOf("@") + 1));
            MailMessage myMessage = new MailMessage(new MailAddress("support@" + row["registratioSite"].ToString()), new MailAddress(row["email"].ToString()));
            myMessage.Subject = "";
            myMessage.Body = getGenericEmailTemplate(AffDomains.getFullDomain(row["registratioSite"].ToString()), message, row["email"].ToString(), row["usernumber"].ToString(), row["nick"].ToString());
            myMessage.IsBodyHtml = true;

            SmtpClient mySmtp = new SmtpClient("mysmtp.server.com");
            mySmtp.Send(myMessage);
        }
        catch (Exception)
        {
        }
    }

    Response.Write("success");
    Response.End();
}

private string getGenericEmailTemplate(string domain, string message, string email, string usernumber, string nick)
{
    return "some html";
}

private string getUsersWithoutPicturesTemplate()
{
    return "some message";
}
private string getUsersWithoutTextTemplate()
{
    return "some message 2";
}
private string getUsersWithoutEnteringWebsiteForTwoWeeksTemplate()
{
    return "some message 3";
}
private string getUsersWithoutHobbiesTemplate()
{
    return "some message 4";
}
private string getUsersWithoutCharateristicsTemplate()
{
    return "some message 5";
}
private string getUsersWithoutActivationTemplate()
{
    return "some message 6";
}

1 个答案:

答案 0 :(得分:1)

基于您当前实现的一些指示:

  • 每周做一次。您的网站真的如此重要,以至于用户每晚都必须受到折磨吗?
  • 看起来您要多次向每位用户发送电子邮件,例如,如果他们没有图片且两周没有输入,他们将收到两封电子邮件。将所有活动合并到一个电子邮件中。
  • 根据应收到的通知将您的电子邮件批量分组,例如,一次只有BCC 5用户的个人资料中没有图片。
  • 仅从存储的过程中返回所需的数据。
  • 移动主循环的所有内容,例如创建EmailHost,MailMessage对象,并在循环内设置相关属性。

如果您希望此解决方案扩展超出其当前限制,您可能需要考虑某种多线程(或分布式)生产者/消费者队列。我在这里不再详述 - 网上有很多例子。