.Net网站架构设计(五) 消息中间件

.Net网站架构设计(五)消息中间件

消息中间件是异步化、解耦、流量削峰的利器

在设计互联架构是,往往遇到需要推送消息,而推送消息比较耗时。

做法

       1:直接执行业务,调用推送

       

int main()
{
执行业务代码
doBussiness();//调用消息推送
NoteMessageObject obj = (NoteMessageObject)state;NoteXmppMessage nXmpp = new NoteXmppMessage(obj.noteInfo, obj.listNoteSendToObjects);
}

优点:开发简单

缺点:由于推送需要时间,所以返回到客户端时间有延迟,较长

       2:开启线程执行推送

int main()
{

//执行业务代码

doBussiness();
Thread r=ThreadStart(doSendNoteMessage);
r.Start();
}

 name="code" class="csharp">void doSendNoteMessage(object state)
        {
            try
            {
                //调用消息推送
  NoteMessageObject obj = (NoteMessageObject)state; NoteXmppMessage nXmpp = new NoteXmppMessage(obj.noteInfo, obj.listNoteSendToObjects); nXmpp.SendMessage(); } catch(Exception e) { // MagicSales.CommonTools.Log.WriteLog(e.Message); // CommonTools.Log.WriteLog(e.Message); } }
优点:执行完代码不用管推送是否成功直接返回给客户端,把推送交给线程,提高了系统响应速度;

缺点:a大量消息并发,开启线程十分耗费资源,当线程开启到一定程度,会报一些莫名其妙的错误;

           b需要维护系统重启,未完成的推送消息丢失。

       3:利用线程池开启线程实现推送

int main()
{

//执行业务代码

doBussiness();
NoteMessageObject obj = new NoteMessageObject();
obj.noteInfo = noteInfo;
obj.listNoteSendToObjects = listNoteSendToObjects;
ThreadPool.QueueUserWorkItem(doSendNoteMessage, obj);//开启线程池
}

void doSendNoteMessage(object state)
        {
            try
            {

                //调用消息推送

               NoteMessageObject obj = (NoteMessageObject)state;
                NoteXmppMessage nXmpp = new NoteXmppMessage(obj.noteInfo, obj.listNoteSendToObjects);
                
                nXmpp.SendMessage();
            }
            catch(Exception e)
            {
               // MagicSales.CommonTools.Log.WriteLog(e.Message);
             //   CommonTools.Log.WriteLog(e.Message);
            }
        }
优点:有了线程池管理线程,很好的解决的多线程时,线程资源的复用,大大提供了效率,减少了由于线程过多带来的问题。

缺点:随着推送消息的增多,大量消息堆积。系统负荷增大。

            重启系统后,推送消息丢失。

       4:利用消息队列实现。

1,第一要选用一种消息队列,可备选项目有:RabbitMQ,MSMQ,AcivityMQ,Kafka 有关他们几个的对比请参考

      我这里选择RabbitMQ.net RabbitMQ参考

用RabbitMQ就要分生产者,和消费者 

生产者代码:

static void Main(string[] args)
        {

          //执行业务代码
           doBussiness();
 var factory = new ConnectionFactory(); factory.HostName = "192.168.1.219"; factory.UserName = "lim"; 
factory.Password = "liming!123"; using (
var connection = factory.CreateConnection()) 
{ 
using (var channel = connection.CreateModel()) 
{ 
bool durable = true; channel.QueueDeclare("task_queue", durable, false, false, null); 
NoteMessageObject obj = new NoteMessageObject(); 
obj.noteInfo = noteInfo; obj.listNoteSendToObjects = listNoteSendToObjects;
string message = Json.Convert(obj) ;//序列化 
var properties = channel.CreateBasicProperties();
 properties.SetPersistent(true); 
var body = Encoding.UTF8.GetBytes(message);
 channel.BasicPublish("", "task_queue", properties, body);
 Console.WriteLine(" set {0}", message); }
 } Console.ReadKey();
消费者代码:

 static void Main(string[] args)
        {
            var factory = new ConnectionFactory();
            factory.HostName = "192.168.1.219";
            factory.UserName = "lim";
            factory.Password = "liming!123";

            using (var connection = factory.CreateConnection())
                using (var channel = connection.CreateModel())
                {
                    bool durable = true;
                    channel.QueueDeclare("task_queue", durable, false, false, null);
                    channel.BasicQos(0, 1, false);

                    var consumer = new QueueingBasicConsumer(channel);
                    channel.BasicConsume("task_queue", false, consumer);

                    while (true)
                    {
                        var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();

                        var body = ea.Body;
                        var message = Encoding.UTF8.GetString(body);

                       NoteMessageObject obj = Json.DescConvert(message) ;//反序列化
            

                     NoteXmppMessage nXmpp = new NoteXmppMessage(obj.noteInfo, obj.listNoteSendToObjects);
          nXmpp.SendMessage();


channel.BasicAck(ea.DeliveryTag, false); } } }
优点:a生产者,和消费者分离, b.消息持久化保存,重启RabbitMQ,和应用系统,消费者,生产者程序,都不会丢失消息。 c:当列队待处理消息大量滞留时,可以单纯的增加消费者个数来,提高消费能力。缺点:开发部署较为复杂
 
 

你可能感兴趣的:(C#【高级】互联网架构)