前言
从第一次使用消息队列开始,业务背景是报名系统通知到我们的系统。正常流量下数据都能正常通知过来,但遇到导入报名人时,采用了Task异步通知,数据量一大,队列就死了。当时是尽量采用同步方式,减少并发量。
后来业务上有了专门的营销系统,各种数据的增删改都要进营销系统,我采用的方式在仓储层对需要通知的表的任何更新都通知到队列,这样的方式几乎对其他业务无侵犯。
好处有,坏处也有。很多批量任务的更新如果采用同步方式频繁通知是十分浪费速度的,既影响数据的更新速度,也对队列带来了挑战。我曾经专门拉了个分支来优化批量任务,但由于需要涉及很多批量任务最后不了了之。
更合理的推送模型应该是这样,更新消息先到内存队列,积累一段时间(5秒或30秒)后,聚合到一起推送到消息队列,如下图:
挑战过去
其实也说不上是问题,原因知道,解决方法也知道。只是现状还能支撑,就没有去解决,但这些事情总要面对的。挑战过去的糟糕代码,优化提升性能,本身就是一个技术成长的过程。
迈出第一步
第一步当然是Demo,先列出代码。先贴上一个基于Rabbitmq.Client的客户端帮助代码,用于推送单条数据和多条数据。
<pre style="box-sizing: border-box; font-family: monospace; font-size: 18px; margin: 20px 0px; padding: 15px; border: 0px; background-color: rgb(244, 245, 246); white-space: pre-wrap; word-break: break-all; color: rgb(34, 34, 34); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class RabbitProvider
{
public const string RABBITMQURL = "amqp://test:test@rabbitmq.login1.com:5672/test";
private static IConnection conn;
/// <summary>
/// 获取连接。
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static IConnection CreateConnection(string url)
{
ConnectionFactory factory = new ConnectionFactory();
factory.Uri = new Uri(url);
factory.AutomaticRecoveryEnabled = true;
IConnection conn = factory.CreateConnection();
return conn;
}
/// <summary>
/// 单个
/// </summary>
/// <param name="data"></param>
public static void Publish<T>(string exchange, string queue, string route, T data)
{
if (conn == null || !conn.IsOpen)
{
conn = CreateConnection(RABBITMQURL);
}
using (IModel model = conn.CreateModel())
{
model.ExchangeDeclare(exchange, ExchangeType.Direct);
model.QueueDeclare(queue, false, false, false, null);
model.QueueBind(queue, exchange, route, null);
//IBasicProperti