C#隊列學習筆記:RabbitMQ安裝及使用

来源:https://www.cnblogs.com/atomy/archive/2020/04/03/12592749.html
-Advertisement-
Play Games

一、環境搭建 1.1、由於RabbitMQ是使用Erlang語言開發的,因此要安裝Erlang運行時環境,下載地址:Erlang官網下載 CSDN分享下載 1.2、去RabbitMQ官網下載RabbitMQ Server服務端程式,選擇合適的平臺版本下載並安裝。 RabbitMQ安裝時,會自動在Wi ...


    一、環境搭建

    1.1、由於RabbitMQ是使用Erlang語言開發的,因此要安裝Erlang運行時環境,下載地址:Erlang官網下載  CSDN分享下載

    1.2、去RabbitMQ官網下載RabbitMQ Server服務端程式,選擇合適的平臺版本下載並安裝。

    RabbitMQ安裝時,會自動在Windows服務中創建RabbitMQ服務,並自動啟動。

    1.3、開始->所有程式->RabbitMQ Server->RabbitMQ Command Prompt (sbin dir):

    運行RabbitMQ Command Prompt與cmd下cd C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.3\sbin的效果是一樣的。

    1.3.1、sbin目錄下的rabbitmqctl.bat,是用來查看和控制服務端狀態的。運行rabbitmqctl status檢查RabbitMQ狀態:

    1.3.3、RabbitMQ Server上面也有用戶概念,使用rabbitmqctl list_users命令,可以看到目前的用戶:

    可以看到,現在只有一個名為gues角色為administratort的用戶,這個是RabbitMQ預設為我們創建的,它有RabbitMQ的所有許可權。一般情況下,我們需要新建一個自己的用戶,並設置密碼及授予許可權,同時設置為管理員。操作方法如下:

rabbitmqctl add_user hello world
rabbitmqctl set_permissions hello ".*" ".*" ".*"
rabbitmqctl set_user_tags hello administrator

    上面的第一命令添加了一個名為hello的用戶並設置了密碼world;第二條命令為用戶hello分別授予對所有消息隊列的配置、讀和寫的許可權;第三條命令將用戶hello設置為管理員。

    現在我們可以將預設的guest用戶刪掉,使用下麵的命令即可:

rabbitmqctl delete_user guest

    如果要修改密碼,可以使用下麵的命令:

rabbitmqctl change_password {username} {newpassowrd}

   二、管理界面

    RabbitMQ還有一個管理界面,是以插件形式提供的,通過該界面可以查看RabbitMQ Server當前的狀態。啟用命令如下: 

rabbitmq-plugins enable rabbitmq_management

    現在,在瀏覽器中輸入 http://server-name:15672/ 即可。

    註:server-name為電腦名或IP地址,如果是本地的,直接用localhost即可。登錄界面,使用我們之前創建的hello用戶登錄。

    三、開始使用

    在.NET中使用RabbitMQ需要下載RabbitMQ客戶端程式集,下載解壓後在bin下找到RabbitMQ.Client.dll,並添加引用到項目中。

    3.1、Hello World

    為了展示RabbitMQ的基本使用,我們發送一個HelloWorld消息,然後接收並處理。

rabbitmq hello world

    3.1.1、創建一個名為Send的客戶端控制台程式,用來將消息發送到RabbitMQ消息隊列中,代碼如下:

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.建立通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列
                    channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //5.構建byte消息數據包
                    string message = args.Length > 0 ? args[0] : "Hello World";
                    var body = Encoding.UTF8.GetBytes(message); //消息是以二進位數組的形式傳輸的
                    //6.發送數據包
                    channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: null, body: body);
                    Console.WriteLine($"Send {message}");
                    Console.Read();
                }
            }
            #endregion
        }
    }
Send.cs

    3.1.2、創建一個名為Receive的服務端控制台程式,用來接收RabbitMQ消息隊列中的消息,代碼如下:

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.創建通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列
                    channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //5.構造消費者實例
                    var consumer = new EventingBasicConsumer(channel);
                    //6.綁定消息接收後的事件委托
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body);
                        Console.WriteLine($"Received {message}");
                    };
                    //7.啟動消費者
                    channel.BasicConsume(queue: "hello", noAck: true, consumer: consumer);
                    Console.Read();
                }
            }
            #endregion
        }
    }
Receive.cs

    3.1.3、先運行消息接收端,再運行消息發送端,結果如下:

    從上面的代碼中可以看出,發送端和接收端的代碼前4步都是一樣的。主要的區別在於發送端調用channel.BasicPublish方法發送消息,而接收端需要實例化一個EventingBasicConsumer實例來進行消息處理。另外一點需要註意的是:消息接收端和發送端的隊列名稱(queue)必須保持一致,這裡指定的隊列名稱為hello。

    3.2、工作隊列

    工作隊列(work queues,又稱Task Queues)的主要思想是:為了避免立即執行一些實時性要求不高但是比較耗資源或時間的操作(如寫日誌),把任務當作消息發送到隊列中,由一個運行在後臺的工作者(worker)進程取出並處理。當有多個工作者(workers)運行時,任務會在它們之間共用。

    現在發送一些字元串來模擬耗時的任務,在字元串中加上點號(.)來表示任務的複雜程度。一個點號將會耗時1秒鐘,比如"Hello World..."就會耗時3秒鐘。

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.建立通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列
                    channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //5.構建byte消息數據包
                    string message = args.Length > 0 ? string.Join(" ", args) : "Hello World...";
                    var properties = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2;//設置消息是否持久化 1:非持久化 2:持久化
                    var body = Encoding.UTF8.GetBytes(message);//消息是以二進位數組的形式傳輸的
                    //6.發送數據包
                    channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: null, body: body);
                    Console.WriteLine($"Send {message}");
                    Console.Read();
                }
            }
            #endregion
        }
    }
Send.cs
    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.創建通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列
                    channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //5.構造消費者實例
                    var consumer = new EventingBasicConsumer(channel);
                    //6.綁定消息接收後的事件委托
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body);
                        int dots = message.Split('.').Length - 1;
                        Thread.Sleep(dots * 1000);
                        Console.WriteLine($"Received {message}");
                    };
                    //7.啟動消費者
                    channel.BasicConsume(queue: "hello", noAck: true, consumer: consumer);
                    Console.Read();
                }
            }
            #endregion
        }
    }
Receive.cs

    3.3輪詢分發

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

    現在,我們先啟動兩個接收端,等待接受消息,然後啟動一個發送端開始發送消息(cmd->send.exe所在的目錄)。

    上面發了10條信息,兩個接收端各收到5條信息。

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

    3.4、消息響應

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

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

    為了防止消息丟失,RabbitMQ提供了消息響應(acknowledgments)機制。消費者會通過一個ack(響應),告訴RabbitMQ已經收到並處理了某條消息,然後RabbitMQ才會釋放並刪除這條消息。如果消費者掛掉了,沒有發送響應,RabbitMQ就會認為消息沒有被完全處理,然後重新發送給其它消費者。這樣,即使工作者偶爾的掛掉,也不會丟失消息。

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

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

    下麵修改Receive.cs,主要改動的是:將 autoAck:true修改為autoAck:fasle,以及在消息處理完畢後手動調用BasicAck方法進行手動消息確認。

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.創建通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列
                    channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //5.構造消費者實例
                    var consumer = new EventingBasicConsumer(channel);
                    //6.綁定消息接收後的事件委托
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body);
                        int dots = message.Split('.').Length - 1;
                        Thread.Sleep(dots * 1000);
                        Console.WriteLine($"Received {message}");
                        //7.發送消息確認信號(手動消息確認)
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    };
                    //8.啟動消費者(noAck: false 啟用消息響應)
                    channel.BasicConsume(queue: "hello", noAck: false, consumer: consumer);
                    Console.Read();
                }
            }
            #endregion
        }
    }
Receive.cs

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

C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.3\sbin>rabbitmqctl list_queues name messages_ready messages_unacknowledged
Timeout: 60.0 seconds ...
Listing queues for vhost / ...
name    messages_ready  messages_unacknowledged
hello   1       0

    3.5、消息持久化

    消息確認確保了即使消費端異常,消息也不會丟失能夠被重新分發處理。但是如果RabbitMQ服務端異常,消息依然會丟失。除非我們指定durable:true,否則當RabbitMQ退出或崩潰時,消息將依然會丟失。通過指定durable:true(隊列),並指定Persistent=true(消息),來告知RabbitMQ將消息持久化。一句話概括:需要保證隊列和消息都是持久化的。

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.建立通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列(指定durable:true,告知rabbitmq對消息進行持久化。)
                    channel.QueueDeclare(queue: "hello", durable: true, exclusive: false, autoDelete: false, arguments: null);
                    //將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    //5.構建byte消息數據包
                    string message = args.Length > 0 ? args[0] : "Hello World";
                    var body = Encoding.UTF8.GetBytes(message);//消息是以二進位數組的形式傳輸的
                    //6.發送數據包(指定basicProperties)
                    channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: properties, body: body);
                    Console.WriteLine($"Send {message}");
                    Console.Read();
                }
            }
            #endregion
        }
    }
Send.cs
    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.創建通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列(指定durable:true,告知rabbitmq對消息進行持久化。)
                    channel.QueueDeclare(queue: "hello", durable: true, exclusive: false, autoDelete: false, arguments: null);
                    //將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    //5.構造消費者實例
                    var consumer = new EventingBasicConsumer(channel);
                    //6.綁定消息接收後的事件委托
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body);
                        int dots = message.Split('.').Length - 1;
                        Thread.Sleep(dots * 1000);
                        Console.WriteLine($"Received {message}");
                        //7.發送消息確認信號(手動消息確認)
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    };
                    //8.啟動消費者(noAck: false 啟用消息響應)
                    channel.BasicConsume(queue: "hello", noAck: false, consumer: consumer);
                    Console.Read();
                }
            }
            #endregion
        }
    }
Receive.cs

    將消息標記為持久性不能完全保證消息不會丟失。雖然它告訴RabbitMQ將消息保存到磁碟,但是當RabbitMQ接受消息並且還沒有保存時​​,仍然有一個很短的時間視窗。RabbitMQ可能只是將消息保存到了緩存中,並沒有將其寫入到磁碟上。持久化不是一定能夠保證的,但是對於一個簡單任務隊列來說已經足夠。

    如果需要確保消息隊列的持久化,可以使用publisher confirms

    3.6、公平分發

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

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

//Receive.cs
//4.聲明隊列(指定durable:true,告知rabbitmq對消息進行持久化。)
//channel.QueueDeclare(queue: "hello", durable: true, exclusive: false, autoDelete: false, arguments: null);
channel.QueueDeclare("hello", true, false, false, null);
//將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
var properties = channel.CreateBasicProperties();
properties.Persistent = true;
//設置prefetchCount : 1來告知RabbitMQ,在未收到消費端的消息確認時,不再分發消息。
//channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
channel.BasicQos(0, 1, false);

    3.7完整實例

    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.建立通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列(指定durable:true,告知rabbitmq對消息進行持久化。)
                    channel.QueueDeclare(queue: "hello", durable: true, exclusive: false, autoDelete: false, arguments: null);
                    //將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    //5.構建byte消息數據包
                    string message = args.Length > 0 ? args[0] : "Hello World";
                    var body = Encoding.UTF8.GetBytes(message);//消息是以二進位數組的形式傳輸的
                    //6.發送數據包(指定basicProperties)
                    channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: properties, body: body);
                    Console.WriteLine($"Send {message}");
                    Console.Read();
                }
            }
            #endregion
        }
    }
Send.cs
    class Program
    {
        static void Main(string[] args)
        {
            #region Hello World
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.創建通道
                using (var channel = connection.CreateModel())
                {
                    //4.聲明隊列(指定durable:true,告知rabbitmq對消息進行持久化。)
                    channel.QueueDeclare(queue: "hello", durable: true, exclusive: false, autoDelete: false, arguments: null);
                    //將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    //設置prefetchCount : 1來告知RabbitMQ,在未收到消費端的消息確認時,不再分發消息。
                    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
                    //5.構造消費者實例
                    var consumer = new EventingBasicConsumer(channel);
                    //6.綁定消息接收後的事件委托
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body);
                        int dots = message.Split('.').Length - 1;
                        Thread.Sleep(dots * 1000);
                        Console.WriteLine($"Received {message}");
                        //7.發送消息確認信號(手動消息確認)
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    //8.啟動消費者(noAck: false 啟用消息響應)
                    channel.BasicConsume(queue: "hello", noAck: false, consumer: consumer);
                    Console.Read();
                }
            }
            #endregion
        }
    }
Receive.cs

    四、Exchange

    上面的示例,生產者和消費者直接是通過相同隊列名稱進行匹配銜接的。消費者訂閱某個隊列,生產者創建消息發佈到隊列中,隊列再將消息轉發到訂閱的消費者。這樣就會有一個局限性,即消費者一次只能發送消息到某一個隊列。

    那消費者如何才能發送消息到多個消息隊列呢?

    RabbitMQ提供了Exchange,它類似於路由器的功能,對消息進行路由,將消息發送到多個隊列上。Exchange一方面從生產者接收消息,另一方面將消息推送到隊列。但是Exchange是如何知道將消息附加到哪個隊列或者直接忽略的呢?這些其實是由Exchange Type來定義的。關於Exchange的圖文介紹,請看上一篇《C#隊列學習筆記:RabbitMQ基礎知識》,此處僅提供示例代碼。

    4.1、fanout

    class Program
    {
        static void Main(string[] args)
        {
            #region fanout exchange type
            //1.實例化連接工廠
            var factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "hello",
                Password = "world"
            };
            //2.建立連接
            using (var connection = factory.CreateConnection())
            {
                //3.建立通道
                using (var channel = connection.CreateModel())
                {
                    //4.使用fanout exchange type,指定exchange名稱。
                    channel.ExchangeDeclare(exchange: "fanoutEC", type: "fanout");
                    //將消息標記為持久性 - 將IBasicProperties.SetPersistent設置為true
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    //5.構建byte消息數據包
                    for (int i = 1; i <= 10; i++)
                    {
                        string message = args.Length > 0 ? args[0] : "Hello World" + new string('.', i);
                        	   

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

-Advertisement-
Play Games
更多相關文章
  • 今天給大家分享五個開源的博客系統,可用於免費創建自己的博客,也有大量精美的模板使用,也就是說你不懂技術,用了這五個開源系統也能創建自己的博客,至於創建博客的好處,想必大家都知道,可用戶記錄生活,分享技術,也能鍛煉一下自己的文筆。 一.wordpress wordpress老牌博客系統,開源免費,有大 ...
  • 1、 Docker虛擬化鏡像製作實戰一 1)Docker commit可以實現容器提交為新的鏡像,提交的鏡像自動進入當前系統的鏡像列表(容器|鏡像內容是完整的); docker commit 7ec01484db55 centos7:v1 docker images 2)Docker export可 ...
  • 我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 8. 字元串轉換整數 (atoi) 題目 請你來實現一個 at ...
  • tensorflow入門 tensorflow是由谷歌人工智慧團隊谷歌大腦(Google Brain)開發和維護的一個深度學習框架。 入門案例 以下是一個加法運算的示例,我們通過tensorflow構建一個tensorflow graph ,然後通過session 會話去運行該graph,我們通過a ...
  • title: Java基礎語法(11) 面向對象之關鍵字 blog: "CSDN" data: "Java學習路線及視頻" 1.this 1. this是什麼 它在方法內部使用,即這個方法所屬對象的引用; 它在構造器內部使用,表示該構造器正在初始化的對象。 this可以作為一個類中構造器相互調用的特 ...
  • 經過數十天的忙碌,今天終於有時間寫博客。 前面一章通過介紹有關模板工作方式相關的內容,同時介紹了FrameWorkElement下所有控制項的模板。接下來將介紹如何構建一個簡單的自定義按鈕,併在該過程中學習有關控制項模板的一些細節。 通過上一章內容,基本Button控制項使用ButtonChrome類繪製 ...
  • 問題: 還是升級到3.1的問題,直接上圖,現象如下: 我們的系統里,有一些查詢條件是從枚舉轉化過來的,但是為了統一,界面渲染的時候追加了一個“請選擇”,value為-999,這種場景很多很多, 可以看到-999不在枚舉的定義里,只要我以當前選擇狀態提交請求,後端全局的modal valid就會報錯, ...
  • .NET Core 概述 .NET Core是一個免費的、開源的、跨平臺的、廣泛使用的Web框架;它是由微軟維護的。社區廣泛參與支持的一個框架。.NET Core可以運行在:Windows、MacOS以及Linux操作系統上。 .Net Core可以用來開發各種不同的應用程式,例如:移動端、桌面端、 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...