自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

.NET Core中的RabbitMQ消費(fèi)者CPU高,竟然是這個(gè)原因

開(kāi)發(fā) 架構(gòu)
通過(guò)一段時(shí)間的努力,產(chǎn)品終于支持多租戶模式了,測(cè)試在做測(cè)試的時(shí)候發(fā)現(xiàn)了一個(gè)問(wèn)題,隨著租戶數(shù)添加的越來(lái)越多,RabbitMQ 消費(fèi)者的 CPU 占用也越來(lái)越高。

在 RabbitMQ 中有一個(gè) vhsot 機(jī)制,可以用來(lái)做租戶隔離,當(dāng)產(chǎn)品從單租戶演化為多租戶時(shí),正好可以用到這個(gè)特性,不同 vhost 中的交換機(jī)、隊(duì)列互不影響。

起初在產(chǎn)品中引入 RabbitMQ 的時(shí)候,版本如下:

  • RabbitMQ:3.7.2 (后來(lái)升級(jí)為 3.8.2)。
  • RabbitMQ Client:5.1.2。
  • .NET Core:3.1。

通過(guò)一段時(shí)間的努力,產(chǎn)品終于支持多租戶模式了,測(cè)試在做測(cè)試的時(shí)候發(fā)現(xiàn)了一個(gè)問(wèn)題,隨著租戶數(shù)添加的越來(lái)越多,RabbitMQ 消費(fèi)者的 CPU 占用也越來(lái)越高。

100 左右的租戶數(shù),每個(gè)租戶隊(duì)列大概 10 幾個(gè),這時(shí) CPU 占用穩(wěn)定在 50% 左右,即使系統(tǒng)沒(méi)有任何人訪問(wèn)。

分析下可能的原因:

  • 因產(chǎn)品比較復(fù)雜,可能是其代碼影響到。
  • 可能是 RabbitMQ 的參數(shù)問(wèn)題。
  • 可能是 .NET Core 中的驅(qū)動(dòng)的問(wèn)題,可以嘗試下 Java 。

正式進(jìn)入問(wèn)題的排查。

簡(jiǎn)單示例

1、在 .NET Core 3.1 中編寫(xiě)一個(gè)簡(jiǎn)單的 RabbitMQ 示例:

public void Start()
{
Console.WriteLine("App Start...");
_defMqConfig = new MQConfig()
{
MQAutomaticRecoveryEnabled = true,
MQHeartBeat = 5,
MQNetworkRecoveryInterval = 5,
MQVHost = "/",
MQHostName = _mqHostName,
MQUserName = _mqUserName,
MQPassword = _mqPassword,
MQPort = _mqPort,
MQServerPort = string.IsNullOrEmpty(_mqServerPort) ? $"1{_mqPort}" : _mqServerPort
};
Console.WriteLine(" MQ vhost init Start...");
string prefix = "testhost";
for (int i = 0; i < 200; i++)
{
string vhost = $"{prefix}{i}";
InitAllVhost(vhost);
Console.WriteLine($" 初始化vhost:{vhost}...");
}
Console.WriteLine(" MQ vhost init Done...");
Console.WriteLine("App Start Done...");
}
private void InitAllVhost(string vhost)
{
string url = $"http://{_mqHostName}:{_mqServerPort}";
_mqManager.AddVirtualHost(url, vhost, _mqUserName, _mqPassword);

_defMqConfig.MQVHost = vhost;
_mqManager.Subscribe(_defMqConfig);
}

2、監(jiān)聽(tīng)的代碼如下:

public void Subscribe(MQConfig engineConfig)
{
var factory = new ConnectionFactory();
factory.HostName = engineConfig.MQHostName;
factory.UserName = engineConfig.MQUserName;
factory.Password = engineConfig.MQPassword;
factory.VirtualHost = engineConfig.MQVHost;
factory.RequestedHeartbeat = (ushort) engineConfig.MQHeartBeat;
factory.AutomaticRecoveryEnabled = true;
factory.NetworkRecoveryInterval = new TimeSpan(engineConfig.MQNetworkRecoveryInterval);
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
channel.QueueDeclare("TestQueue", false, false, false, null);
channel.ExchangeDeclare("TestQueueExchange", ExchangeType.Direct, false, false, null);
var consumer = new EventingBasicConsumer(channel);
channel.BasicConsume("TestQueue", false, consumer);
channel.QueueBind("TestQueue", "TestQueueExchange", "TestQueueExchange");
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine("已接收: {0}", message);
};
}

3、上面代碼創(chuàng)建了 200 個(gè) vhost ,每個(gè) vhost 中 1 個(gè)隊(duì)列,程序運(yùn)行后觀察 cpu 如下圖:

圖片

4、在 Subscribe 方法中有創(chuàng)建 Connection 和 CreateModel 方法,如果使用 using 或在方法最后對(duì)其進(jìn)行釋放,CPU 會(huì)是一個(gè)正常的狀態(tài),但消息也就接收不到了。

調(diào)整參數(shù)

1、在 RabbitMQ 中有兩個(gè)參數(shù) MQHeartBeat、MQNetworkRecoveryInterval :

  • MQHeartBeat:心跳檢測(cè)
  • MQNetworkRecoveryInterval:掉線重連

2、不斷調(diào)整這兩個(gè)參數(shù)的值,進(jìn)行嘗試,發(fā)現(xiàn) CPU 并沒(méi)有明顯改善。

嘗試 Java

當(dāng)沒(méi)有什么頭緒的時(shí)候,就會(huì)采用各種方式進(jìn)行嘗試,來(lái)排除問(wèn)題,所以決定用 Java 試試。

在 Java 程序中,使用的 RabbitMQ 客戶端為 rabbitmq-java-client ,版本為 5.14.2 ,因?yàn)橹霸?.NET 程序驗(yàn)證時(shí)已經(jīng)創(chuàng)建了 vhost ,所以在 Java 程序中只寫(xiě)了消費(fèi)者進(jìn)行監(jiān)聽(tīng)。

當(dāng) Java 程序跑起來(lái)的時(shí)候,發(fā)現(xiàn) CPU 占用是正常的,在遍歷 vhost 監(jiān)聽(tīng)的過(guò)程中 CPU 有所波動(dòng),遍歷完后 ,CPU 占用比較穩(wěn)定。

真正的原因

這時(shí)基本可以確定,是 .NET Core 的 RabbitMQ 客戶端的問(wèn)題,到這時(shí)才想起有可能是 .NET Core  RabbitMQ 客戶端的版本問(wèn)題,檢查發(fā)現(xiàn)目前使用的版本是 5.1.2,而最新的版本為 6.3.0 。

升級(jí) .NET Core RabbitMQ 到最新版本,升級(jí)后有兩個(gè)地方不兼容:

  • RequestedHeartbeat 類(lèi)型變成了 TimeSpan。
  • 接收的消息由 byte[] 變成了 ReadOnlyMemory類(lèi)型。

圖片

修改這兩處后,趕緊運(yùn)行進(jìn)行測(cè)試,CPU 終于正常了。

查看了下 RabbitMQ 客戶端在 GitHub 上的更新記錄,發(fā)現(xiàn)在版本 6.2.4 中有修復(fù)一個(gè)關(guān)于連接的 Bug:

圖片

又繼續(xù)將版本回退到 6.2.3 進(jìn)行測(cè)試,問(wèn)題又能重現(xiàn)了,就更加確定了這個(gè)問(wèn)題是在 6.2.4 中解決了。

最后

現(xiàn)在無(wú)論是做項(xiàng)目還是做產(chǎn)品,都會(huì)使用很多中間件,這些中間件和相關(guān)的庫(kù)也是在不斷地更新迭代的,當(dāng)我們進(jìn)行功能迭代的同時(shí),也需要關(guān)注這些中間件的發(fā)展,在新的版本中提供了什么新特性,修復(fù)了什么問(wèn)題,這給我們是否升級(jí)提供依據(jù)。

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2024-09-27 11:38:49

2021-10-18 13:42:52

加密貨幣金融工具

2022-07-07 19:44:22

Python 3.1

2016-10-25 21:00:27

云計(jì)算

2017-11-03 09:10:48

2024-09-30 09:48:41

RabbitMQ消息中間件

2019-02-12 14:53:44

物聯(lián)網(wǎng)設(shè)備物聯(lián)網(wǎng)IOT

2020-09-29 06:45:49

JDK

2020-08-19 09:23:10

傳輸網(wǎng)絡(luò)WDM網(wǎng)絡(luò)技術(shù)

2009-07-15 19:51:01

AMD六核CPU服務(wù)器

2020-11-03 09:14:30

編程語(yǔ)言Go技術(shù)

2018-06-23 13:49:56

蘋(píng)果谷歌手機(jī)

2015-06-18 11:04:58

2020-12-15 08:05:40

路由器服務(wù)器網(wǎng)絡(luò)層

2021-07-28 06:51:08

Nacos代理模式

2024-08-05 01:28:26

2022-11-15 07:35:50

Spring事件觀察者模式

2023-03-13 08:09:03

Protobuffeature分割

2018-07-06 00:09:47

2023-06-01 08:08:38

kafka消費(fèi)者分區(qū)策略
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)