C#使用RabbitMQ

来源:https://www.cnblogs.com/damsoft/archive/2018/02/01/8399959.html
-Advertisement-
Play Games

1. 說明 在企業應用系統領域,會面對不同系統之間的通信、集成與整合,尤其當面臨異構系統時,這種分散式的調用與通信變得越發重要。其次,系統中一般會有很多對實時性要求不高的但是執行起來比較較耗時的地方,比如發送簡訊,郵件提醒,更新文章閱讀計數,記錄用戶操作日誌等等,如果實時處理的話,在用戶訪問量比較大 ...


1. 說明 

  在企業應用系統領域,會面對不同系統之間的通信、集成與整合,尤其當面臨異構系統時,這種分散式的調用與通信變得越發重要。其次,系統中一般會有很多對實時性要求不高的但是執行起來比較較耗時的地方,比如發送簡訊,郵件提醒,更新文章閱讀計數,記錄用戶操作日誌等等,如果實時處理的話,在用戶訪問量比較大的情況下,對系統壓力比較大。

面對這些問題,我們一般會將這些請求,放在消息隊列MQ中處理;異構系統之間使用消息進行通訊。

    MQ全稱為Message Queue, 消息隊列(MQ)是一種應用程式對應用程式的通信方法。應用程式通過讀寫出入隊列的消息(針對應用程式的數據)來通信,而無需專用連接來鏈接它們。消息傳遞指的是程式之間通過在消息中發送數據進行通信,而不是通過直接調用彼此來通信,直接調用通常是用於諸如遠程過程調用的技術。排隊指的是應用程式通過 隊列來通信。隊列的使用除去了接收和發送應用程式同時執行的要求。

  MQ是消費-生產者模型的一個典型的代表,一端往消息隊列中不斷寫入消息,而另一端則可以讀取或者訂閱隊列中的消息。

   RabbitMQ是一個在AMQP基礎上完整的,可復用的企業消息系統。他遵循Mozilla Public License開源協議。 

  消息傳遞相較文件傳遞與遠程過程調用(RPC)而言,似乎更勝一籌,因為它具有更好的平臺無關性,並能夠很好地支持併發與非同步調用。所以如果系統中出現瞭如下情況:

  • 對操作的實時性要求不高,而需要執行的任務極為耗時;
  • 存在異構系統間的整合;

  一般的可以考慮引入消息隊列。對於第一種情況,常常會選擇消息隊列來處理執行時間較長的任務。引入的消息隊列就成了消息處理的緩衝區。消息隊列引入的非同步通信機制,使得發送方和接收方都不用等待對方返回成功消息,就可以繼續執行下麵的代碼,從而提高了數據處理的能力。尤其是當訪問量和數據流量較大的情況下,就可以結合消息隊列與後臺任務,通過避開高峰期對大數據進行處理,就可以有效降低資料庫處理數據的負荷。 

  本文簡單介紹在RabbitMQ這一消息代理工具,以及在.NET中如何使用RabbitMQ.

2. 搭建環境

  2.1 安裝Erlang語言運行環境

  由於RabbitMQ使用Erlang語言編寫,所以先安裝Erlang語言運行環境。具體移步博客:windows配置Erlang環境

  2.2 安裝RabbitMQ服務端

  地址 http://www.rabbitmq.com/

  下載安裝。

  使RabbitMQ以Windows Service的方式在後臺運行:打開cmd切換到sbin目錄下執行

rabbitmq-service install
rabbitmq-service enable
rabbitmq-service start

   現在RabbitMQ的服務端已經啟動起來了。

  要查看和控制RabbitMQ服務端的狀態,可以用rabbitmqctl這個腳本。

  比如查看狀態:

rabbitmqctl status

  

  假如顯示node沒有連接上,需要到C:\Windows目錄下,將.erlang.cookie文件,拷貝到用戶目錄下 C:\Users\{用戶名},這是Erlang的Cookie文件,允許與Erlang進行交互。

   使用命令查看用戶:

rabbitmqctl list_users

  RabbitMQ會為我們創建預設的用戶名guest和密碼guest,guest預設擁有RabbitMQ的所有許可權。

  一般的,我們需要新建一個我們自己的用戶,設置密碼,並授予許可權,並將其設置為管理員,可以使用下麵的命令來執行這一操作:

rabbitmqctl  add_user  JC JayChou   //創建用戶JC密碼為JayChou
rabbitmqctl  set_permissions  JC ".*"  ".*"  ".*"    //賦予JC讀寫所有消息隊列的許可權
rabbitmqctl  set_user_tags JC administrator    //分配用戶組

  修改JC密碼為123:

rabbitmqctl change_password JC  123

  刪除用戶JC:

rabbitmqctl delete_user  JC

  也可以開啟rabbitmq_management插件,在web界面查看和管理RabbitMQ服務

rabbitmq-plugins enable rabbitmq_management  

 

  2.3下載RabbitMQ的Client端dll

  下載地址:http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/

  本人下載了這個 rabbitmq-dotnet-client-3.6.6-dotnet-4.5.zip

   解壓,我們需要的是這個文件,以後會引用到vs的項目中:

3.使用

  3.1在使用RabitMQ之前,先對幾個概念做一下說明

  

  RabbitMQ是一個消息代理。他從消息生產者(producers)那裡接收消息,然後把消息送給消息消費者(consumer)在發送和接受之間,他能夠根據設置的規則進行路由,緩存和持久化。

  一般提到RabbitMQ和消息,都用到一些專有名詞。

  • 生產(Producing)意思就是發送。發送消息的程式就是一個生產者(producer)。我們一般用"P"來表示:

       producer

  • 隊列(queue)就是郵箱的名稱。消息通過你的應用程式和RabbitMQ進行傳輸,它們只能存儲在隊列(queue)中。 隊列(queue)容量沒有限制,你要存儲多少消息都可以——基本上是一個無限的緩衝區。多個生產者(producers)能夠把消息發送給同一個隊列,同樣,多個消費者(consumers)也能從同一個隊列(queue)中獲取數據。隊列可以畫成這樣(圖上是隊列的名稱):

     queue

  • 消費(Consuming)和獲取消息是一樣的意思。一個消費者(consumer)就是一個等待獲取消息的程式。我們把它畫作"C":

     consumer

  通常,消息生產者,消息消費者和消息代理不在同一臺機器上。

3.2 Hello Word

  下麵來展示簡單的RabbitMQ的使用:


      rabbitmq hello world

 3.2.1 首先創建名為ProjectSend的控制台項目,需要引用RabbitMQ.Client.dll。這個程式作為Producer生產者,用來發送數據:

複製代碼
static void Main(string[] args)
    {
        var factory = new ConnectionFactory();
        factory.HostName = "localhost";//RabbitMQ服務在本地運行
        factory.UserName = "guest";//用戶名
        factory.Password = "guest";//密碼

        using (var connection = factory.CreateConnection())
        {
            using (var channel = connection.CreateModel())
            {
                channel.QueueDeclare("hello", false, false, false, null);//創建一個名稱為hello的消息隊列
                string message = "Hello World"; //傳遞的消息內容
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish("", "hello", null, body); //開始傳遞
                Console.WriteLine("已發送: {0}", message);
          Console.ReadLine(); } } }
複製代碼

  

  首先,需要創建一個ConnectionFactory,設置目標,由於是在本機,所以設置為localhost,如果RabbitMQ不在本機,只需要設置目標機器的IP地址或者機器名稱即可,然後設置前面創建的用戶名和密碼。

  緊接著要創建一個Channel,如果要發送消息,需要創建一個隊列,然後將消息發佈到這個隊列中。在創建隊列的時候,只有RabbitMQ上該隊列不存在,才會去創建。消息是以二進位數組的形式傳輸的,所以如果消息是實體對象的話,需要序列化和然後轉化為二進位數組。

  現在客戶端發送代碼已經寫好了,運行之後,消息會發佈到RabbitMQ的消息隊列中,現在需要編寫服務端的代碼連接到RabbitMQ上去獲取這些消息。

3.2.2創建名為ProjectReceive的控制台項目,引用RabbitMQ.Client.dll。作為Consumer消費者,用來接收數據:

複製代碼
static void Main(string[] args)
        {
            var factory = new ConnectionFactory();
            factory.HostName = "localhost";
            factory.UserName = "guest";
            factory.Password = "guest";

            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare("hello", false, false, false, null);

                    var consumer = new EventingBasicConsumer(channel);
                    channel.BasicConsume("hello", false, consumer);
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body;
                        var message = Encoding.UTF8.GetString(body); 
                        Console.WriteLine("已接收: {0}", message);   
                    };
                    Console.ReadLine(); 
                }
            }
        }
複製代碼

   和發送一樣,首先需要定義連接,然後聲明消息隊列。要接收消息,需要定義一個Consume,然後在接收消息的事件中處理數據。

 3.2.3 現在發送和接收的客戶端都寫好了,讓我們編譯執行起來

  發送消息:

  現在,名為hello的消息隊列中,發送了一條消息。這條消息存儲到了RabbitMQ的伺服器上了。使用rabbitmqctl 的list_queues可以查看所有的消息隊列,以及裡面的消息個數,可以看到,目前Rabbitmq上只有一個消息隊列,裡面只有一條消息:

  也可以在web管理界面查看此queue的相關信息:

 

 

  接收消息:

   既然消息已經被接收了,那我們再來看queue的內容:

  可見,消息中的內容在接收之後已被刪除了。

3.3 工作隊列

  前面的例子展示瞭如何在指定的消息隊列發送和接收消息。

  現在我們創建一個工作隊列(work queue)來將一些耗時的任務分發給多個工作者(workers):

   rabbitmq-work queue

  工作隊列(work queues, 又稱任務隊列Task Queues)的主要思想是為了避免立即執行並等待一些占用大量資源、時間的操作完成。而是把任務(Task)當作消息發送到隊列中,稍後處理。一個運行在後臺的工作者(worker)進程就會取出任務然後處理。當運行多個工作者(workers)時,任務會在它們之間共用。

  這個在網路應用中非常有用,它可以在短暫的HTTP請求中處理一些複雜的任務。在一些實時性要求不太高的地方,我們可以處理完主要操作之後,以消息的方式來處理其他的不緊要的操作,比如寫日誌等等。

準備

  在第一部分,發送了一個包含“Hello World!”的字元串消息。現在發送一些字元串,把這些字元串當作複雜的任務。這裡使用time.sleep()函數來模擬耗時的任務。在字元串中加上點號(.)來表示任務的複雜程度,一個點(.)將會耗時1秒鐘。比如"Hello..."就會耗時3秒鐘。

對之前示例的send.cs做些簡單的調整,以便可以發送隨意的消息。這個程式會按照計劃發送任務到我們的工作隊列中。

複製代碼
static void Main(string[] args)
{
    var factory = new ConnectionFactory();
    factory.HostName = "localhost";
    factory.UserName = "yy";
    factory.Password = "hello!";

    using (var connection = factory.CreateConnection())
    {
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare("hello", false, false, false, null);
            string message = GetMessage(args);
            var properties = channel.CreateBasicProperties();
            properties.DeliveryMode = 2;

            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish("", "hello", properties, body);
            Console.WriteLine(" set {0}", message);
        }
    }

    Console.ReadKey();
}

private static string GetMessage(string[] args)
{
    return ((args.Length > 0) ? string.Join(" ", args) : "Hello World!");
}
複製代碼

 

接著我們修改接收端,讓他根據消息中的逗點的個數來Sleep對應的秒數:

按 Ctrl+C 複製代碼 按 Ctrl+C 複製代碼

 

輪詢分發

  使用工作隊列的一個好處就是它能夠並行的處理隊列。如果堆積了很多任務,我們只需要添加更多的工作者(workers)就可以了,擴展很簡單。

現在,我們先啟動兩個接收端,等待接受消息,然後啟動一個發送端開始發送消息。

Send message queue 

  在cmd條件下,發送了5條消息,每條消息後面的逗點表示該消息需要執行的時長,來模擬耗時的操作。

  然後可以看到,兩個接收端依次接收到了發出的消息:

receive message queue 

預設,RabbitMQ會將每個消息按照順序依次分發給下一個消費者。所以每個消費者接收到的消息個數大致是平均的。 這種消息分發的方式稱之為輪詢(round-robin)。

3.4 消息響應

當處理一個比較耗時得任務的時候,也許想知道消費者(consumers)是否運行到一半就掛掉。在當前的代碼中,當RabbitMQ將消息發送給消費者(consumers)之後,馬上就會將該消息從隊列中移除。此時,如果把處理這個消息的工作者(worker)停掉,正在處理的這條消息就會丟失。同時,所有發送到這個工作者的還沒有處理的消息都會丟失。

我們不想丟失任何任務消息。如果一個工作者(worker)掛掉了,我們希望該消息會重新發送給其他的工作者(worker)。

為了防止消息丟失,RabbitMQ提供了消息響應(acknowledgments)機制。消費者會通過一個ack(響應),告訴RabbitMQ已經收到並處理了某條消息,然後RabbitMQ才會釋放並刪除這條消息。

如果消費者(consumer)掛掉了,沒有發送響應,RabbitMQ就會認為消息沒有被完全處理,然後重新發送給其他消費者(consumer)。這樣,即使工作者(workers)偶爾的掛掉,也不會丟失消息。

消息是沒有超時這個概念的;當工作者與它斷開連的時候,RabbitMQ會重新發送消息。這樣在處理一個耗時非常長的消息任務的時候就不會出問題了。

消息響應預設是開啟的。在之前的例子中使用了no_ack=True標識把它關閉。是時候移除這個標識了,當工作者(worker)完成了任務,就發送一個響應。

複製代碼
channel.BasicConsume("hello", false, consumer);

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

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

    int dots = message.Split('.').Length - 1;
    Thread.Sleep(dots * 1000);

    Console.WriteLine("Received {0}", message);
    Console.WriteLine("Done");

    channel.BasicAck(ea.DeliveryTag, false);
}
複製代碼

 

現在,可以保證,即使正在處理消息的工作者被停掉,這些消息也不會丟失,所有沒有被應答的消息會被重新發送給其他工作者.

一個很常見的錯誤就是忘掉了BasicAck這個方法,這個錯誤很常見,但是後果很嚴重. 當客戶端退出時,待處理的消息就會被重新分發,但是RabitMQ會消耗越來越多的記憶體,因為這些沒有被應答的消息不能夠被釋放。調試這種case,可以使用rabbitmqct列印messages_unacknoledged欄位。

rabbitmqctl list_queues name messages_ready messages_unacknowledged
Listing queues ...
hello    0       0
...done.

 

3.5 消息持久化

前面已經搞定了即使消費者down掉,任務也不會丟失,但是,如果RabbitMQ Server停掉了,那麼這些消息還是會丟失。

當RabbitMQ Server 關閉或者崩潰,那麼裡面存儲的隊列和消息預設是不會保存下來的。如果要讓RabbitMQ保存住消息,需要在兩個地方同時設置:需要保證隊列和消息都是持久化的。

首先,要保證RabbitMQ不會丟失隊列,所以要做如下設置:

bool durable = true;
channel.QueueDeclare("hello", durable, false, false, null);

 

雖然在語法上是正確的,但是在目前階段是不正確的,因為我們之前已經定義了一個非持久化的hello隊列。RabbitMQ不允許我們使用不同的參數重新定義一個已經存在的同名隊列,如果這樣做就會報錯。現在,定義另外一個不同名稱的隊列:

bool durable = true;
channel.queueDeclare("task_queue", durable, false, false, null);

 

queueDeclare 這個改動需要在發送端和接收端同時設置。

現在保證了task_queue這個消息隊列即使在RabbitMQ Server重啟之後,隊列也不會丟失。 然後需要保證消息也是持久化的, 這可以通過設置IBasicProperties.SetPersistent 為true來實現:

var properties = channel.CreateBasicProperties();
properties.SetPersistent(true);

 

需要註意的是,將消息設置為持久化並不能完全保證消息不丟失。雖然他告訴RabbitMQ將消息保存到磁碟上,但是在RabbitMQ接收到消息和將其保存到磁碟上這之間仍然有一個小的時間視窗。 RabbitMQ 可能只是將消息保存到了緩存中,並沒有將其寫入到磁碟上。持久化是不能夠一定保證的,但是對於一個簡單任務隊列來說已經足夠。如果需要消息隊列持久化的強保證,可以使用publisher confirms

3.6 公平分發

你可能會註意到,消息的分發可能並沒有如我們想要的那樣公平分配。比如,對於兩個工作者。當奇數個消息的任務比較重,但是偶數個消息任務比較輕時,奇數個工作者始終處理忙碌狀態,而偶數個工作者始終處理空閑狀態。但是RabbitMQ並不知道這些,他仍然會平均依次的分發消息。

為了改變這一狀態,我們可以使用basicQos方法,設置perfetchCount=1 。這樣就告訴RabbitMQ 不要在同一時間給一個工作者發送多於1個的消息,或者換句話說。在一個工作者還在處理消息,並且沒有響應消息之前,不要給他分發新的消息。相反,將這條新的消息發送給下一個不那麼忙碌的工作者。

channel.BasicQos(0, 1, false); 

 

3.7 完整實例

現在將所有這些放在一起:

發送端代碼如下:

複製代碼
static void Main(string[] args)
{
    var factory = new ConnectionFactory();
    factory.HostName = "localhost";
    factory.UserName = "yy";
    factory.Password = "hello!";

    using (var connection = factory.CreateConnection())
    {
        using (var channel = connection.CreateModel())
        {
                   
            bool durable = true;
            channel.QueueDeclare("task_queue", durable, false, false, null);
                    
            string message = GetMessage(args);
            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();
}

private static string GetMessage(string[] args)
{
    return ((args.Length > 0) ? string.Join(" ", args) : "Hello World!");
}
複製代碼

 

接收端代碼如下:

複製代碼
static void Main(string[] args)
{
    var factory = new ConnectionFactory();
    factory.HostName = "localhost";
    factory.UserName = "yy";
    factory.Password = "hello!";

    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);

                int dots = message.Split('.').Length - 1;
                Thread.Sleep(dots * 1000);

                Console.WriteLine("Received {0}", message);
                Console.WriteLine("Done");

                channel.BasicAck(ea.DeliveryTag, false);
            }
        }
    }
}
複製代碼

 

4 管理界面

RabbitMQ管理界面,通過該界面可以查看RabbitMQ Server 當前的狀態,該界面是以插件形式提供的,並且在安裝RabbitMQ的時候已經自帶了該插件。需要做的是在RabbitMQ控制台界面中啟用該插件,命令如下:

rabbitmq-plugins enable rabbitmq_management

rabbitmq management

現在,在瀏覽器中輸入 http://server-name:15672/ server-name換成機器地址或者功能變數名稱,如果是本地的,直接用localhost(RabbitMQ 3.0之前版本埠號為55672)在輸入之後,彈出登錄界面,使用我們之前創建的用戶登錄。

RabbitMQ Web management .

在該界面上可以看到當前RabbitMQServer的所有狀態。

5 總結

本文簡單介紹了消息隊列的相關概念,並介紹了RabbitMQ消息代理的基本原理以及在Windows 上如何安裝RabbitMQ和在.NET中如何使用RabbitMQ。消息隊列在構建分散式系統和提高系統的可擴展性和響應性方面有著很重要的作用,希望本文對您瞭解消息隊列以及如何使用RabbitMQ有所幫助。

 

轉自:https://www.cnblogs.com/longlongogo/p/6489574.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這篇文章我們將介紹Linux間進程通間信中的有名管道與無名管道。 一.無名管道 無名管道是一種特殊類型的文件,在內核中對應的資源即一段特殊記憶體空間,這段空間完全由操作系統管理和維護。可以使用read/write等函數進行讀寫操作,但不能使用lseek函數來修改當前的讀寫位置,因為管道需要滿足FIFO ...
  • 從百度里搜索里搜索了很多jwt的文章,跟著文章寫了一個demo,這裡記錄下學習過程中碰上的問題。看文章多遍,不如手工實現一次。 模板已上傳到 https://github.com/dogvane/webapi_jwt_template ...
  • 一、軟體安裝 Redis下載地址:https://github.com/MSOpenTech/redis/releases 因為官方並不支持windows系統,需要從微軟的GitHub上下載。 解壓縮後文件夾內容如圖所示(版本3.2.100): 最開始會用到的文件有redis-server.exe、 ...
  • 環境:vs2017 版本:15.5.6 這裡說明下, Razor頁面模式跟mvc出現了嚴重的不同。正如微軟官方說的一樣“Razor 頁面是 ASP.NET Core MVC 的一個新功能,它可以使基於頁面的編碼方式更簡單高效。” 但就代碼說沒有什麼不同幾乎完全一樣,但是存放的位置卻有了根本的區別。個 ...
  • <<操作系統精髓與設計原理>>讀書筆記(一) 併發性:互斥與同步 併發問題是所有問題的基礎,也是操作系統設計的基礎。併發包括很多設計問題,其中有進程間通信,資源共用與競爭,多個進程活動的同步以及分配給進程的處理器時間的。 和併發相關的關鍵術語:原子操作: 一個或多個指令的序列,對外是不可分的;即沒有 ...
  • 假設現在有三個項目,ProjectA,ProjectB,ProjectC。 ProjectA項目中有倆個介面,Get(),GetTest( string code )。 ProjectB項目中一個介面,GetHelloWorld()。 ProjectC是一個後臺任務。 遇到的問題是: Project ...
  • 隨機好說,不重覆以前一直是while(true)去判斷,偶然看到這個方法,for裡面兩個條件i++寫在if裡面,從來沒有這麼用過,記錄一下 int[] a = new int[100]; var rand = new Random(); for (int i = 0; i < 100; ) { va ...
  • Asp.Net Core 是開源,跨平臺,模塊化,快速而簡單的Web框架. "Asp.net Core官網的一個合集,方便一次性Clone" 目錄 "快速入門" "安裝" "一個最小的應用" "項目模板" "路由" "靜態文件" "頁面渲染" "請求" "錯誤和重定向" "關於響應" "會話" "日 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...