原文:http://www.rabbitmq.com/configure.html
RabbitMQ 提供了三種方式來定制服務器:
- 環境變量
- 定義端口,文件位置和名稱(接受shell輸入,或者在環境配置文件(rabbitmq-env.conf)中設置)
- 配置文件
- 為服務器組件設置權限,限制和集群,也可以定義插件設置.
- 運行時參數和策略
- 可在運行時進行修改集群設置
驗證配置(怎樣找到配置文件地址)
有效配置文件可通過檢查RabbitMQ日志文件進行驗證.它會與其它中間件啟動日志條目放置在日志文件 的頂部,例如:
node : rabbit@example home dir : /var/lib/rabbitmq config file(s) : /etc/rabbitmq/rabbitmq.config如果找不到日志文件,日志將會顯示:
node : rabbit@example home dir : /var/lib/rabbitmq config file(s) : /var/lib/rabbitmq/hare.config (not found)
定制RabbitMQ環境
可通過環境變量來配置服務器參數:節點名稱, RabbitMQ 配置文件位置, AMQP 0-9-1 和節點通信端口等等.
Unix (general)
在基于Unix的系統(包含Linux, MacOSX)上,可以創建/編輯rabbitmq-env.conf來定義環境變量. 其位置是不可配置的(不像rabbitmq.config).
使用標準環境變量名稱(去掉RABBITMQ_前輟) 如:
#example rabbitmq-env.conf file entries #Rename the node NODENAME=bunny@myhost #Config file location and new filename bunnies.config CONFIG_FILE=/etc/rabbitmq/testdir/bunniesMore info on using rabbitmq-env.conf
Windows
如果要在windows上配置名稱,端口,位置,可通過在windows對話框來配置: Start > Settings > Control Panel > System > Advanced > Environment Variables.
創建或編輯系統變量名稱和值.
要Windows上的環境變量生效,必須重新安裝服務,光重啟是不夠的.這可以通過安裝器或帶有管理權限的命令行來完成:
- 啟動管理員命令提示窗口
- 進入RabbitMQ服務器安裝目錄下的sbin目錄 (e.g.C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.6.1\sbin)
- 運行rabbitmq-service.bat remove
- 通過命令行來設置環境變量,即像下面這樣來運行命令:set RABBITMQ_BASE=c:\Data\RabbitMQ
- 運行 rabbitmq-service.bat 來安裝
- 啟動管理員命令提示窗口
- 進入RabbitMQ服務器安裝目錄下的sbin目錄
- 通過命令行來設置環境變量
- 運行 rabbitmq-service.bat 來安裝, 這只會更新服務參數
RabbitMQ環境變量
RabbitMQ 環境變量有一個RABBITMQ_前輟. 典型的環境變量RABBITMQ_var_name是按下面進行設置的:
- 如果在 shell環境變量中定義了名為RABBITMQ_var_name的變量,則優先使用此定義;
- 否則,使用 rabbitmq-env.conf中變量名為var_name的定義;
- 否則,使用系統指定的默認值.
這樣,shell環境中的變量定義比rabbitmq-env.conf中的相同變量定義有更高的優先級, 而RabbitMQ中的系統默認值具有最低優先級.
- Generic UNIX -$RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf
- Debian - /etc/rabbitmq/rabbitmq-env.conf
- RPM - /etc/rabbitmq/rabbitmq-env.conf
- Mac OS X (Homebrew) -${install_prefix}/etc/rabbitmq/rabbitmq-env.conf, Homebrew 前輟通常是/usr/local
- Windows -%APPDATA%\RabbitMQ\rabbitmq-env-conf.bat
- 如果沒有設置, 服務器控制臺輸出將被丟棄(默認情況).
- new:服務每次啟動時都會創建一個新文件.
- reuse:每次服務啟動的時候,文件都會被覆蓋.
- Unix*: "+K true +A30 +P 1048576 -kernel inet_default_connect_options [{nodelay,true}]"
- Windows: None
- Unix*: None
- Windows: None
此外,還有幾個環境變量可用來告知RabbitMQ其數據庫,日志文件,插件,配置文件的位置.
RabbitMQ依賴的變量有:
HOSTNAME
- Unix, Linux: `env hostname`
- MacOSX: `env hostname -s`
COMPUTERNAME
當前機器的名稱
ERLANG_SERVICE_MANAGER_PATH
缺省
Windows Service:%ERLANG_HOME%\erts-x.x.x\bin
描述
erlsrv.exe位置路徑,Erlang服務的封裝腳本
配置文件
rabbitmq.config 文件
rabbitmq.config配置文件允許配置RabbitMQ 核心程序, Erlang 服務和RabbitMQ 插件. 它是標準的Erlang 配置文件, 文檔位于Erlang Config Man Page.
最小化的樣例配置文件如下:
[ {rabbit, [{tcp_listeners, [5673]}]} ].
這個例子中將會修改RabbitMQ監聽AMQP 0-9-1 客戶端連接端口,5672修改為5673.
配置文件不同于環境配置文件rabbitmq-env.conf,(它可在非Window系統上設置環境變量).
rabbitmq.config 和 rabbitmq-env.conf的位置
這些文件的位置分布特定的. 默認情況下,這些文件是沒有創建的,但每個平臺上期望的位置如下:
- Generic UNIX - $RABBITMQ_HOME/etc/rabbitmq/
- Debian - /etc/rabbitmq/
- RPM - /etc/rabbitmq/
- Mac OS X (Homebrew) - ${install_prefix}/etc/rabbitmq/, the Homebrew prefix is usually/usr/local
- Windows - %APPDATA%\RabbitMQ\
如果rabbitmq-env.conf不存在, 可在默認位置中手動創建. 它不能用于Windows系統.
如果rabbitmq.config不存在,可以手動創建它. 如果你修改了位置,可設置RABBITMQ_CONFIG_FILE 環境變量來指定. Erlang 運行時會自動在此變量值后添加.config擴展名,重啟服務器后生效.
Windows 服務用戶在刪除配置文件后,需要重新安裝服務.
示例rabbitmq.config文件
RabbitMQ server 源碼倉庫包含 一個示例配置文件 名為rabbitmq.config.example.這個示例文件中包含了你想要設置的大多數配置項(有一些省略)與其說明. 示例中的所有配置項都注釋了的,如果你有需要,你可以取消注解. 注意,示例文件僅僅只是示例,不應該將其視為通用的推薦.
在大多數發行版中,我們將此示例文件放在真實文件的位置.然而再 Debian 和RPM 發行策略禁止這樣做, 你可以在/usr/share/doc/rabbitmq-server/或 /usr/share/doc/rabbitmq-server-3.6.1/ respectively中找到.
rabbitmq.config中的變量配置
大部分的RabbitMQ用戶都會不會修改這些值,有些是相當模糊的.然而,為了完整性,他們都在這里列出。
Key | Documentation |
---|---|
tcp_listeners | 用于監聽 AMQP連接的端口列表(無SSL). 可以包含整數 (即"監聽所有接口")或者元組如 {"127.0.0.1", 5672} 用于監聽一個或多個接口. Default: [5672] |
num_tcp_acceptors | 接受TCP偵聽器連接的Erlang進程數。 Default: 10 |
handshake_timeout | AMQP 0-8/0-9/0-9-1 handshake (在 socket 連接和SSL 握手之后)的最大時間, 毫秒為單位. Default: 10000 |
ssl_listeners | 如上所述,用于SSL連接。 Default: [] |
num_ssl_acceptors | 接受SSL偵聽器連接的Erlang進程數。 Default: 1 |
ssl_options | SSL配置.參考SSL documentation. Default: [] |
ssl_handshake_timeout | SSL handshake超時時間,毫秒為單位. Default: 5000 |
vm_memory_high_watermark | 流程控制觸發的內存閥值.相看memory-based flow control 文檔. Default: 0.4 |
vm_memory_high_watermark_paging_ratio | 高水位限制的分數,當達到閥值時,隊列中消息消息會轉移到磁盤上以釋放內存. 參考memory-based flow control 文檔. Default: 0.5 |
disk_free_limit | RabbitMQ存儲數據分區的可用磁盤空間限制.當可用空間值低于閥值時,流程控制將被觸發. 此值可根據RAM的總大小來相對設置 (如.{mem_relative, 1.0}). 此值也可以設為整數(單位為bytes)或者使用數字單位(如."50MB"). 默認情況下,可用磁盤空間必須超過50MB. 參考 Disk Alarms 文檔. Default: 50000000 |
log_levels | 控制日志的粒度.其值是日志事件類別(category)和日志級別(level)成對的列表. level 可以是 'none' (不記錄日志事件), 'error' (只記錄錯誤), 'warning' (只記錄錯誤和警告), 'info' (記錄錯誤,警告和信息), or 'debug' (記錄錯誤,警告,信息以及調試信息). 目前定義了4種日志類別. 它們是:
Default: [{connection, info}] |
frame_max | 與客戶端協商的允許最大frame大小. 設置為0表示無限制,但在某些QPid客戶端會引發bug. 設置較大的值可以提高吞吐量;設置一個較小的值可能會提高延遲. Default: 131072 |
channel_max | 與客戶端協商的允許最大chanel大小. 設置為0表示無限制.該數值越大,則broker使用的內存就越高. Default: 0 |
channel_operation_timeout | Channel 操作超時時間(毫秒為單位) (內部使用,因為消息協議的區別和限制,不暴露給客戶端). Default: 5000 |
heartbeat | 表示心跳延遲(單位為秒) ,服務器將在connection.tune frame中發送.如果設置為 0, 心跳將被禁用. 客戶端可以不用遵循服務器的建議, 查看 AMQP reference 來了解詳情. 禁用心跳可以在有大量連接的場景中提高性能,但可能會造成關閉了非活動連接的網絡設備上的連接落下. Default: 60 (3.5.5之前的版本是580) |
default_vhost | 當RabbitMQ從頭開始創建數據庫時創建的虛擬主機. amq.rabbitmq.log交換器會存在于這個虛擬主機中. Default: <<"/">> |
default_user | RabbitMQ從頭開始創建數據庫時,創建的用戶名. Default: <<"guest">> |
default_pass | 默認用戶的密碼. Default: <<"guest">> |
default_user_tags | 默認用戶的Tags. Default: [administrator] |
default_permissions | 創建用戶時分配給它的默認Permissions . Default: [<<".*">>, <<".*">>, <<".*">>] |
loopback_users | 只能通過環回接口(即localhost)連接broker的用戶列表 如果你希望默認的guest用戶能遠程連接,你必須將其修改為[]. Default: [<<"guest">>] |
cluster_nodes | 當節點第一次啟動的時候,設置此選項會導致集群動作自動發生. 元組的第一個元素是其它節點想與其建立集群的節點. 第二個元素是節點的類型,要么是disc,要么是ram Default: {[], disc} |
server_properties | 連接時向客戶端聲明的鍵值對列表 Default: [] |
collect_statistics | 統計收集模式。主要與管理插件相關。選項:
Default: none |
collect_statistics_interval | 統計收集時間間隔(毫秒為單位). 主要針對于 management plugin. Default: 5000 |
auth_mechanisms | 提供給客戶端的SASL authentication mechanisms. Default: ['PLAIN', 'AMQPLAIN'] |
auth_backends | 用于 authentication / authorisation backends 的列表. 此列表可包含模塊的名稱(在模塊相同的情況下,將同時用于認證來授權)或像{ModN, ModZ}這樣的元組,在這里ModN將用于認證,ModZ將用于授權. 在2元組的情況中, ModZ可由列表代替,列表中的所有元素必須通過每個授權的確認,如{ModN, [ModZ1, ModZ2]}. 這就允許授權插件進行組合提供額外的安全約束. 除rabbit_auth_backend_internal外,其它數據庫可以通常 plugins來使用. Default: [rabbit_auth_backend_internal] |
reverse_dns_lookups | 設置為true,可讓客戶端在連接時讓RabbitMQ 執行一個反向DNS查找, 然后通過 rabbitmqctl 和 管理插件來展現信息. Default: false |
delegate_count | 內部集群通信中,委派進程的數目. 在一個有非常多核的機器(集群的一部分)上,你可以增加此值. Default: 16 |
trace_vhosts | tracer內部使用. 你不應該修改. Default: [] |
tcp_listen_options | 默認socket選項. 你可能不想修改這個選項. Default: [{backlog, 128}, {nodelay, true}, {exit_on_close, false}] |
hipe_compile | 將此選項設置為true,將會使用HiPE預編譯部分RabbitMQ,Erlang的即時編譯器. 這可以增加服務器吞吐量,但會增加服務器的啟動時間. 你可以看到花費幾分鐘延遲啟動的成本,就可以帶來20-50% 更好性能.這些數字與高度依賴于工作負載和硬件. HiPE 支持可能沒有編譯進你的Erlang安裝中.如果沒有的話,啟用這個選項,并啟動RabbitMQ時,會看到警告消息. 例如, Debian / Ubuntu 用戶需要安裝erlang-base-hipe 包. HiPE并非在所有平臺上都可用, 尤其是Windows. 在 Erlang/OTP 17.5版本之前,HiPE有明顯的問題 . 對于HiPE,使用最新的OTP版本是高度推薦的. Default: false |
cluster_partition_handling | 如何處理網絡分區.可用模式有:
Default: ignore |
cluster_keepalive_interval | 節點向其它節點發送存活消息和頻率(毫秒). 注意,這與 net_ticktime是不同的; 丟失存活消息不會引起節點掉線 Default: 10000 |
queue_index_embed_msgs_below | 消息大小在此之下的會直接內嵌在隊列索引中. 在修改此值時,建議你先閱讀 persister tuning 文檔. Default: 4096 |
msg_store_index_module | 隊列索引的實現模塊. 在修改此值時,建議你先閱讀 persister tuning 文檔. Default: rabbit_msg_store_ets_index |
backing_queue_module | 隊列內容的實現模塊. 你可能不想修改此值. Default: rabbit_variable_queue |
msg_store_file_size_limit | Tunable value for the persister. 你幾乎肯定不應該改變此值。 Default: 16777216 |
mnesia_table_loading_timeout | 在集群中等待使用Mnesia表可用的超時時間。 Default: 30000 |
queue_index_max_ journal_entries | Tunable value for the persister. 你幾乎肯定不應該改變此值。 Default: 65536 |
queue_master_locator | Queue master 位置策略. 可用策略有:
Default: <<"client-local">> |
此外,許多插件也可以在配置文件中配置, 其名稱是rabbitmq_plugin的形式. 我們的維護的插件被記錄在以下位置:
文件位置
你可以設置下面的環境變量來指定相關文件的位置,但大部分人都不必這樣做:
名稱 | 描述 |
---|---|
RABBITMQ_BASE | 此基礎目錄包含了RabbitMQ server的數據庫,日志文件的子目錄. 另外,也可以獨立設置RABBITMQ_MNESIA_BASE 和 RABBITMQ_LOG_BASE 目錄. |
RABBITMQ_CONFIG_FILE | 用于配置文件的路徑,無.config擴展名. 如果 configuration file 存在,服務器將使用它來配置RabbitMQ組件. 參考 Configuration guide 來了解更多信息. |
RABBITMQ_MNESIA_BASE | 包含RabbitMQ 服務器Mnesia數據庫文件子目錄的基本目錄,除非明確設置了RABBITMQ_MNESIA_DIR目錄,否則每個節點都應該配置一個. (除了Mnesia文件,這個位置還包含消息存儲和索引文件以及模式和集群的細節.) |
RABBITMQ_MNESIA_DIR | RabbitMQ節點Mnesia數據庫文件安放的目錄. (除了Mnesia文件,這個位置還包含消息存儲和索引文件以及模式和集群的細節.) |
RABBITMQ_LOG_BASE | 用于包含RabbitMQ 服務器日志文件的基本目錄, 除非明確設置了RABBITMQ_LOGS 或 RABBITMQ_SASL_LOGS. |
RABBITMQ_LOGS | RabbitMQ 服務器的Erlang日志文件路徑.在Window上不能覆蓋此變量. |
RABBITMQ_SASL_LOGS | RabbitMQ服務器的Erlang SASL (System Application Support Libraries)日志文件路徑. 在Window上不能覆蓋此變量. |
RABBITMQ_PLUGINS_DIR | 用于查找插件的目錄 . |
RABBITMQ_PLUGINS_EXPAND_DIR | 用于在啟動服務器時擴展啟用插件的工作目錄。 |
RABBITMQ_ENABLED_PLUGINS_FILE | 此文件記錄了顯式啟用的插件。 |
RABBITMQ_PID_FILE | 此文件中包含了rabbitmqctl所等待進程ID的信息. |
Unix 默認位置
在下面的表格中,${install_prefix}表示某個路徑. Homebrew 安裝時使用installation-prefix (Homebrew Cellar) . 默認是/usr/local.
Deb / RPM 包安裝使用空${install_prefix}.
Name | Location |
---|---|
RABBITMQ_BASE | (Not used) |
RABBITMQ_CONFIG_FILE | ${install_prefix}/etc/rabbitmq/rabbitmq |
RABBITMQ_MNESIA_BASE | ${install_prefix}/var/lib/rabbitmq/mnesia |
RABBITMQ_MNESIA_DIR | $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME |
RABBITMQ_LOG_BASE | ${install_prefix}/var/log/rabbitmq |
RABBITMQ_LOGS | $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME.log |
RABBITMQ_SASL_LOGS | $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME-sasl.log |
RABBITMQ_PLUGINS_DIR | $RABBITMQ_HOME/plugins |
RABBITMQ_PLUGINS_EXPAND_DIR | $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME-plugins-expand |
RABBITMQ_ENABLED_PLUGINS_FILE | ${install_prefix}/etc/rabbitmq/enabled_plugins |
RABBITMQ_PID_FILE | $RABBITMQ_MNESIA_DIR.pid |
Windows 默認位置
Name | Location |
---|---|
RABBITMQ_BASE | %APPDATA%\RabbitMQ |
RABBITMQ_CONFIG_FILE | %RABBITMQ_BASE%\rabbitmq |
RABBITMQ_MNESIA_BASE | %RABBITMQ_BASE%\db |
RABBITMQ_MNESIA_DIR | %RABBITMQ_MNESIA_BASE%\%RABBITMQ_NODENAME% |
RABBITMQ_LOG_BASE | %RABBITMQ_BASE%\log |
RABBITMQ_LOGS | %RABBITMQ_LOG_BASE%\%RABBITMQ_NODENAME%.log |
RABBITMQ_SASL_LOGS | %RABBITMQ_LOG_BASE%\%RABBITMQ_NODENAME%-sasl.log |
RABBITMQ_PLUGINS_DIR | Installation-directory/plugins |
RABBITMQ_PLUGINS_EXPAND_DIR | %RABBITMQ_MNESIA_BASE%\%RABBITMQ_NODENAME%-plugins-expand |
RABBITMQ_ENABLED_PLUGINS_FILE | %RABBITMQ_BASE%\enabled_plugins |
RABBITMQ_PID_FILE | (Not currently supported) |
通用UNIX默認位置
當解壓Generic Unix tar文件并運行時,由于默認獲得到位置,不需要進行. 在下面的表格中,$RABBITMQ_HOME指的是rabbitmq_server-3.6.1 解壓后的目錄.
Name | Location |
---|---|
RABBITMQ_BASE | (Not used) |
RABBITMQ_CONFIG_FILE | $RABBITMQ_HOME/etc/rabbitmq/rabbitmq |
RABBITMQ_MNESIA_BASE | $RABBITMQ_HOME/var/lib/rabbitmq/mnesia |
RABBITMQ_MNESIA_DIR | $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME |
RABBITMQ_LOG_BASE | $RABBITMQ_HOME/var/log/rabbitmq |
RABBITMQ_LOGS | $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME.log |
RABBITMQ_SASL_LOGS | $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME-sasl.log |
RABBITMQ_PLUGINS_DIR | $RABBITMQ_HOME/plugins |
RABBITMQ_PLUGINS_EXPAND_DIR | $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME-plugins-expand |
RABBITMQ_ENABLED_PLUGINS_FILE | $RABBITMQ_HOME/etc/rabbitmq/enabled_plugins |
RABBITMQ_PID_FILE | $RABBITMQ_MNESIA_DIR.pid |
持久化配置
持久化如何工作
首先,先講一下背景: 持久化和短暫消息都可以寫入磁盤.持久化消息一旦到達隊列,就會寫入磁盤,而短暫消息只在內存壓力較大被趕出內存時才會寫入磁盤.持久化消息在內存緊張釋放內存時,依然也會存在內存中. 持久層指的是存儲這兩種類型消息到磁盤的機制.
在本頁中,我們說的隊列是指無鏡像隊列或master隊列或slave隊列. 隊列鏡像會發生以上的持久化.
持久層有兩個組件: 隊列索引和消息存儲.隊列索引負責維護消息在隊列的位置,以及是否被投遞,是否應答的信息. 因此,每個隊列都有一個隊列索引。
消息存儲是消息的key-value存儲, 由服務器中的所有隊列共享.消息(消息體, 消息屬性或消息頭)可直接存儲于隊列索引,也可以寫到消息存儲中.在技術上有兩個消息存儲(一個暫時的和一個持久的消息),但他們通常一起被被認為是“消息存儲”。
內存成本
- 每個隊列都會為每個未應答消息維護一些元數據.如果它的目的地是消息存儲,則消息本身可以從內存中刪除。
- 消息存儲需要索引. 默認消息存儲索引對于存儲中的每個消息會使用少量內存.
隊列索引中的消息
將消息寫入隊列索引有優點也有缺點.
優點:
- 消息可在一個操作中(而不是兩個)寫入磁盤; 對于微小的消息,這可以是一個實質性的增益.
- 寫入隊列索引的消息不需要消息存儲索引中的條目,因此當頁出(paged out)時,不需要花費內存成本.
缺點:
- 隊列索引在內存中保有固定數量的記錄塊;如果寫入隊列索引中的消息不是小消息,那么內存占用也是巨大的.
- 如果一個消息通過一個交換路由到多個隊列,則消息將需要寫入多個隊列索引。如果這樣的消息被寫入消息存儲區,則只有一個副本需要被寫入。
- 目的地是隊列索引的未應答消息總會保存在內存中.
將小消息存儲在隊列索引中目的是優化,所有其它消息將會寫入消息存儲.這可以配置項queue_index_embed_msgs_below來配置.默認情況下,序列后大小小于4096字節 (包括屬性和頭)會存儲在隊列索引中.
當從磁盤中讀取消息時,每個隊列索引至少需要在內存中保留一個段文件(segment file). 段文件中包含了16,384個消息. 因此要謹慎如果增加queue_index_embed_msgs_below;小的增加會導致大量的內存使用。
無意中有限的持久性能(Accidentally limited persister performance)
持久化有可能表現不佳,因為持久化受限于文件句柄的數目或與它工作的異步線程.在這兩種情況下,當您有大量需要同時訪問磁盤的隊列時,會發生這樣的情況。.
太少的文件句柄
RabbitMQ 服務器通常受限于它能打開的文件句柄數量(在Unix上,無論如何). 每個運行的網絡連接都需要一個文件句柄, 其余的可用于隊列使用。如果磁盤訪問隊列比考慮到網絡連接后文件句柄更多,那么磁盤訪問隊列將與文件句柄一起共享; 每個都會在它返回交給另一個隊列之前,都會使用文件句柄一段時間.
當有太多磁盤訪問隊列時,這可以防止服務器崩潰,但代價是昂貴的. 管理插件可以顯示集群中每個節點的統計I/O統計信息,如讀,寫,查找的速率.同時它也會顯示重新開始(reopens)的速率- 文件句柄通過這種方式來回收利用. 一個有太少文件句柄繁忙的服務器每秒可能會做幾百次reopens - 在這種情況下,如果增加文件句柄,就有可能提高性能.
太少的異步線程
Erlang 虛擬機創建異步線程池來處理長時間運行的文件I/O操作. 這些線程池是所有隊列所共享的.每個活躍的文件I/O操作都會使用一個異步線程. 太少的異步線程可以因此傷害性能。
注意,異步線程的情況并不完全類似與文件句柄的情況. 如果一個隊列按順序來執行一定數量的I/O操作,假設它持有一個文件句柄來所理所有操作,其性能是最好的,否則,我們會占用CPU來做更多的刷新,查找 操作. 然而,隊列不能從持有一個異步線程執行一系列的操作中獲益(事實上也做不到).
因此理論上應該要有足夠的文件句柄來處理所有隊列上的I/O流操作, 并且要有足夠的線程來處理并發的 (simultaneous )的I/O操作.
由異步線程缺乏造成的性能問題,不是太明顯. (一般情況下都不太可能,可首先檢查其它地方!) .
太少異步線程的典型癥狀是,當服務器忙于持久化時,在很短的時間內,每秒 I/O操作的數目將會下降到0(管理插件可報告) ,報告的每個 I/O操作的時間將會增加.
Erlang虛擬主機的異步線程數目可通過+A 參數進行配置,這里有描述, 通常情況下,也可以通過環境變量RABBITMQ_SERVER_ERL_ARGS來配置. 默認值是 +A 30. 在修改之前,多進行幾次嘗試總是好主意.
網絡與RabbitMQ
介紹
網絡是Clients與RabbitMQ通信的媒介.broker支持的所有協議都是基于TCP的. RabbitMQ 和操作系統都提供了許多可調整的旋鈕.其中,有些是直接與TCP和IP操作相關的,其它則是與應用程序級協議如TLS相關的. 本指南涵蓋了RabbitMQ中與網絡相關的多個主題. 本指南并不是一廣泛的指南,而只是一個概述. 某些調整參數是與特定操作系統相關的.當有與特定操作系統相關的主題時, 本指南只關注Linux,因為它是部署RabbitMQ的最常見平臺.
- 網絡接口和端口
- TLS
- TCP socket 設置
- Kernel TCP 設置
- (AMQP 0-9-1, STOMP) Heartbeats
- Hostnames and DNS
網絡接口
RabbitMQ用于接受客戶端連接,它需要綁定一個或多個網絡接口,并監聽特定的端口. 網絡接口使用rabbit.tcp_listeners選項來配置.默認情況下,RabbitMQ會在所有可用網絡接口上監聽5672端口.
TCP listeners 可配置網絡接口和端口. 下面的示例演示了如何在一個特定網絡接口和端口上進行監聽:
[ {rabbit, [ {tcp_listeners, [{"192.168.1.99", 5672}]} ]} ].
在雙協議棧上(IPv4和IPv6)接口上監聽
下面的例子演示了如何在IPv4 and IPv6上進行監聽:
[ {rabbit, [ {tcp_listeners, [{"127.0.0.1", 5672}, {"::1", 5672}]} ]} ].
現代Linux kernels 以及Vista后的Windows版本,當在所有IPv6地址上配置端口時,IPv4是沒有明確禁用的,IPv4地址依然可用,因此
[ {rabbit, [ {tcp_listeners, [{"::", 5672}]} ]} ].等價于
[ {rabbit, [ {tcp_listeners, [{"0.0.0.0", 5672}, {"::", 5672}]} ]} ].
只監聽IPv4接口
在這個例子中,RabbitMQ只會監聽IPv4接口:
[ {rabbit, [ {tcp_listeners, [{"192.168.1.99", 5672}]} ]} ].
此外,如果只希望有單個stack設置, 可使用RABBITMQ_NODE_IP環境變量來配置. 參考 Configuration guide 來了解細節.
只監聽IPv6接口
在這個例子中,RabbitMQ會只監聽IPv6接口:
[ {rabbit, [ {tcp_listeners, [{"fe80::2acf:e9ff:fe17:f97b", 5672}]} ]} ].
此外,如果只希望有單個stack設置, 可使用RABBITMQ_NODE_IP環境變量來配置. 參考 Configuration guide 來了解細節.
端口訪問
SELinux 以及相似的機制可能會阻止RabbitMQ綁定到某個端口. 當這樣的情況發生時,RabbitMQ啟動會失敗.必須保證可打開下面的端口:
- 4369 (epmd), 25672 (Erlang distribution)
- 5672, 5671 (AMQP 0-9-1無或有TLS)
- 15672 (如果啟用了管理插件)
- 61613, 61614 (如果啟用了STOMP)
- 1883, 8883 (如果啟用了MQTT)
在RabbitMQ中可使用TLS來加密. 使用對等證書的身份驗證也是可能的。請參閱TLS / SSL的更多信息指南。
優化吞吐量
優化吞吐量是一個共同的目錄. 可通過下面的來實現
- 增大TCP 緩沖區大小
- 確保Nagle的算法失效
- 啟用可選TCP功能和擴展
TCP緩沖區大小
這是關鍵的調整參數. 每個TCP連接都分配了緩沖區. 一般來說,緩沖區用得越大,每個連接上RAM就用得越多,就有更好的吞吐率.在Linux,操作系統默認會自動調整TCP緩沖區的大小,通常會設置為80到120 KB之間.要獲取最大吞吐量,可使用rabbit.tcp_listen_options來加大配置.
下面的例子將TCP緩沖區設置為192 KiB:
[ {rabbit, [ {tcp_listen_options, [ {backlog, 128}, {nodelay, true}, {sndbuf, 196608}, {recbuf, 196608} ]} ]} ].注意,將發發送緩沖區和接收緩沖區設置不同的值是很危險的,且是不推薦的.
Erlang 虛擬機I/O線程池
Erlang 運行時使用線程池來異步執行I/O操作. 池的大小可通過+A VM命令行標志來配置,如+A 128. 我們強烈建議使用`RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS`環境變量來覆蓋此選項:
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+A 128"默認值為30. 8個或8個以上的節點建議使用高于96的值,即: 每核上可以運行12或12以上的I/O線程. 注意:值越高不意味著有更好的吞吐量或由于等待的I / O 而造成較低的處理器燒傷.
優化大量連接
有多個因素可以限制單個節點上支持的并發連接數:
- 可打開的最大文件句柄數目,以及其它kernel強制的資源限制
- 每個連接使用的RAM數量
- 每個連接使用的CPU資源數目
- VM中配置的最大Erlang進程數目
打開文件句柄限制
大部分操作系統都限制了同一時間可以打開的文件句柄數目. 限制是如何配置的 每個操作系統上都不同.
當在優化并發連接數的時候,須確保你的系統有足夠的文件描述符來支持你的client和節點的使用.
要粗略地計算限制,可以用每個節點上連接的數目乘以1.5. 例如,要支持100,000個連接,需要設置限制文件描述符為150,000.稍為增加限制可增加閑置機器內存的使用量,但這是一個合理的權衡。
TCP 緩沖區大小
見上文的部分概述. 可使用rabbit.tcp_listen_options選項來減小緩沖區大小,這樣就可以減小每個連接上使用的RAM使用量. 在每個節點上的并發量比吞吐量重要的環境中,這通常是必須的.
下面的例子將TCP緩沖區設置為32 KiB:
[ {rabbit, [ {tcp_listen_options, [ {backlog, 128}, {nodelay, true}, {sndbuf, 32768}, {recbuf, 32768} ]} ]} ].注意,越小的TCP緩沖區會導致明顯的吞吐量下降, 所以最優的值可在吞吐量和每連接使用的RAM值中找到 ,即在它們之間作一個權衡.將發送緩沖區和接收緩沖區的值設為不同,這是非常危險的且是不推薦的.低于8 KiB的值是不推薦的.
Nagle's 算法 ("nodelay")
[ {kernel, [ {inet_default_connect_options, [{nodelay, true}]}, {inet_default_listen_options, [{nodelay, true}]} ]}, {rabbit, [ {tcp_listen_options, [ {backlog, 4096}, {nodelay, true} ]} ]} ].
Erlang虛擬機I/O線程池優化
連接積壓(Backlog)
當只有較少數量的客戶端時,新連接的分布是非常不均勻的,但因為足夠小,所以沒有太大的差異. 當數量達到數萬或更多時,重要的是要確保服務器可以接受入站連接.未接受的TCP連接會放在帶有限制長度的隊列中. 此長度必須能應對負載較小和較高時的情況,例如,當許多客戶端因為網絡中斷或重連時,必須能應對.
這可以通過rabbit.tcp_listen_options.backlog選項來配置:
[ {rabbit, [ {tcp_listen_options, [ {backlog, 4096}, {nodelay, true} ]} ]} ].默認值是128. 當掛起的連接隊列長度超出此值時,連接將被操作系統拒絕。也可參見優化內核部分的net.core.somaxconn。
操作系統級別的調整
操作系統設置可影響RabbitMQ的操作.有些是直接與網絡相關的(如. TCP設置),其它影響是TCP sockets以及其它東西(如打開文件句柄的限制).理解這些限制是很重要的,因為隨著工作量不同而改變.
幾個重要的可配置內核選項包括 (針對IPv4):
- fs.file-max
- net.ipv4.ip_local_port_range
- 本地IP端口范圍,定義為一對值。該范圍必須為并發連接的峰值數提供足夠的條目。
- net.ipv4.tcp_tw_reuse
- 當啟用時,允許內核重用TIME_WAIT狀態的sockets.參考Coping with the TCP TIME_WAIT connections on busy servers 來了解細節. 當用在NAT時,此選項是很危險的.
- net.ipv4.tcp_fin_timeout
- 降低此值到5-10 可減少連接關閉的時間,之后會停留在TIME_WAIT狀態.建議用在有大量并發連接的場景.
- net.core.somaxconn
- 監聽隊列的大小(同一時間建立過程中有多少個連接). 默認是128. 增大到4096或更高,可以支持入站連接的爆發,如clients集體重連.
- net.ipv4.tcp_max_syn_backlog
- 尚未收到連接客戶端確認的連接請求的最大數量。默認為128,最大值為65535。優化吞吐量時,4096和8192是推薦的起始值。
- net.ipv4.tcp_keepalive_*
- net.ipv4.tcp_keepalive_time, net.ipv4.tcp_keepalive_intvl,net.ipv4.tcp_keepalive_probes 用于配置TCP存活時間. AMQP 0-9-1 和 STOMP有Heartbeats ,這部分撤銷了其效果,換句話說,它可以花幾分鐘來探測未響應的同等端,如:硬件或掉電故障. 當啟用了TCP keepalive,我們建議設置心跳超時為8-20秒.
- net.ipv4.conf.default.rp_filter
- 啟用反向地址過濾. 如果你的系統不關心IP地址欺騙 ,那么就禁用它.
內核參數調整在不同操作系統之間是不同的.這篇指南針對的是Linux. 配置內核參數交互,使用sysctl -w (需要超級權限),例如:
sysctl -w fs.file-max 200000要使修改永久生效,需要將它產加到 /etc/sysctl.conf. 參考sysctl(8) 和 sysctl.conf(5) 來了解細節.
TCP Socket 選項
通用選項
rabbit.tcp_listen_options.nodelay
- 當設置為true,可禁用Nagle算法.默認為true. 高度推薦給大多數用戶。
- rabbit.tcp_listen_options.sndbuf
- 參考本指南先前討論的TCP緩沖區. 默認值自動由操作系統高速,在現代Linux版本上,通常是88 KiB 到 128 KiB的范圍.增大緩沖區可以提高消費者的吞吐量,同時也會加大每個連接上的RAM使用量.減小會有相反的效果.
- rabbit.tcp_listen_options.recbuf
- 參考本指南先前討論的TCP緩沖區. 默認值的效果類似于rabbit.tcp_listen_options.sndbuf ,但這里一般針對的是發布者或協議操作.
- rabbit.tcp_listen_options.backlog
- 隊列中未接受連接的最大數目.當達到此大小時,新連接會被拒絕. 對于成千上萬的并發連接環境以及可能存在大量客戶重新連接的場景,可設為4096或更高.
- rabbit.tcp_listen_options.linger
- 當設置為{true, N},當socket關閉時,用于設置刷新未發送數據的超時時間(秒為單位)
- rabbit.tcp_listen_options.keepalive
- 當設置為true,將啟用TCP keepalives (查看上面的章節). 默認為false.對于連接長時間空閑(至少10分鐘)的環境來說是有意義的, 盡管更推薦使用heartbeats 選項.
缺省
下面是RabbitMQ使用的默認TCP socket選項:
[ {rabbit, [ {tcp_listen_options, [{backlog, 128}, {nodelay, true}, {linger, {true, 0}}]} ]} ].
心跳(Heartbeats)
RabbitMQ支持某些協議, 包括AMQP 0-9-1, 支持心跳,一種更多快速探測死亡 TCP對等端的方法. 請參考 Heartbeats guide 來了解更多信息.
Net Tick Time
Heartbeats 用于探測客戶端與RabbitMQ之間的對等端或連接故障 .net_ticktime 也有同樣的目的,但它針對的是集群節點通信. 低于5(秒)的值可能會導致負面影響,不建議使用。
連接握手超時(Connection Handshake Timeout)
RabbitMQ有連接握手超時時間,默認為10秒鐘. 當客戶端在嚴重受限的環境中運行時,可能需要增加超時時間。這可以通過rabbit.handshake_timeout(毫秒)來完成:
[ {rabbit, [ %% 20 seconds {handshake_timeout, 20000} ]} ].
TLS/SSL Handshake
如果啟用了TLS/SSL,也有必要增大TLS/SSL握手超時時間. 這可以通過rabbit.ssl_handshake_timeout (毫秒)來完成:
[ {rabbit, [ %% 10 seconds {ssl_handshake_timeout, 10000} ]} ].
主機名解析和DNS
Client Libraries執行
如果client library配置成用主機名進行連接,它會執行主機名解析.依賴于 DNS 和本地解析器(類似于/etc/hosts)配置,這可能會花點時間.錯誤配置可能會導致解析超時,如,當試圖通過DNS解析本地主機名如my-dev-machine. 其結果是,客戶端連接會花很長的時候(幾十秒到幾分鐘).
簡短的和全限定RabbitMQ節點名稱
RabbitMQ 依賴于Erlang運行時來進行節點間通信. Erlang節點包括主機名,要么是短的 (rmq1) 要么是全限定的(rmq1.dev.megacorp.local). 混合使用簡短的和全限定的節點名稱,是運行時不允許的 .集群中的每個節點必須能夠解析其它節點的主機名, 簡短的和全限定的. 默認情況下,RabbitMQ 會使用簡短主機名. 設置RABBITMQ_USE_LONGNAME 環境變量可以開啟使用全限定節點名稱如.rmq1.dev.megacorp.local.
反向DNS查找
如果rabbit.reverse_dns_lookups 配置選項設為了true, RabbitMQ會為客戶端IP地址執行反向DNS查找,并在connection中列出主機名稱 (如,在Management UI).
參數和策略
介紹
躍然RabbitMQ大部分配置都生活在configuration file, 有些東西卻不能在配置文件中配置:
- 如果他們需要在一個集群中的所有節點是相同的
- 如果他們有可能在運行時改變
RabbitMQ 稱這些項為參數. 參數可通過調用rabbitmqctl 或通過the management plugin 的HTTP API來設置. 參數的scope是基于虛擬主機(vhost)的.
參數特殊的使用情況是策略( policies),它用于為成組的隊列和交換器,以及插件(如Federation 和 Shovel)指定可選參數.
參數管理
參數可以被設置,清除,和列舉:
rabbitmqctl | rabbitmqctl set_parameter {-p vhost} component_name name value rabbitmqctl clear_parameter {-p vhost} component_name name rabbitmqctl list_parameters {-p vhost} |
---|---|
HTTP API | PUT /api/parameters/component_name/vhost/name DELETE /api/parameters/component_name/vhost/name GET /api/parameters |
由于參數值是一個JSON文檔, 當在使用rabbitmqctl命令行創建時,你通常需要引用它. 在Unix上,很容易使用單引號來引用整個文檔,在其中可以使用雙引號.在Windows上,你必須轉義所有雙引號.基于此理由,我們為Unix和Windows分別給出了例子.
RabbitMQ使用數據庫中的參數來定義虛擬主機,交換器,隊列,綁定,用戶和權限. 參數是通過管理插件的導出功能以及對象定義中導出的.
federation 和 shovel 插件會使用參數.
策略(Policies)
策略會自動匹配交換器和隊列,并幫助確定他們的行為. 每個交換器和隊列至少有一個策略匹配,并且每個策略都會在交換器或隊列上映射一系列的key-value對.
策略的行為有點像exchange.declare和queue.declare的參數, 除了它們會自動應用(不需要客戶端程序的干預),并且它們可在任何時候進行修改.請注意,策略控制的功能集合與參數控制的功能集合是不同的.
策略會在每次交換器或隊列創建的時候進行匹配,而不僅僅是在創建策略時。
策略可用來配置 federation plugin, mirrored queues, alternate exchanges, dead lettering, per-queue TTLs, 以及maximum queue length.
策略定義如下:
rabbitmqctl
rabbitmqctl set_policy federate-me "^amq\." '{"federation-upstream-set":"all"}' --priority 1 --apply-to exchangesrabbitmqctl (Windows)
rabbitmqctl set_policy federate-me "^amq\." "{""federation-upstream-set"":""all""}" --priority 1 --apply-to exchangesHTTP API
PUT /api/policies/%2f/federate-me {"pattern": "^amq\.", "definition": {"federation-upstream-set":"all"}, "priority": 1, "apply-to": "exchanges"}Web UI
- Navigate to Admin > Policies > Add / update a policy.
- Enter "federate-me" next to Name, "^amq\." next to Pattern, and select "Exchanges" next to Apply to.
- Enter "federation-upstream-set" = "all" in the first line next to Policy.
- Click Add policy.
鍵"federation-upstream-set"的值為"all",這將匹配虛擬主機"/"中的所有名稱以"amq."開頭的交換器.
"pattern" 參數是一個用來匹配交換器或隊列名稱的正則表達式.
當有多個策略匹配交換器或隊列時,則會應用優先級最高的策略.
"apply-to" 參數值可以是"exchanges", "queues" 或"all". "apply-to" 和 "priority"設置是可選的, 在這種情況下,其默認值是"all"和"0".
組合策略定義
在某些情況下,我們想要在資源上應用多個策略.例如,我們想讓一個隊列能同時聯合和鏡像. 任何時候,在資源上最多只能應用一個策略,但我們可在那個策略中應用多個定義.
聯合(federation)策略定義需要指定一個upstream 集合,因此在我們的定義中,我們需要federation-upstream-set 鍵.另一方面,要鏡像隊列,我們需要在策略中定義ha-mode鍵.由于策略定義只是一個JSON對象,在同一個策略中我們可以定義這兩個鍵.
這里是例子:
rabbitmqctl
rabbitmqctl set_policy ha-fed "^hf\." '{"federation-upstream-set":"all","ha-mode":"all"}' \ --priority 1 --apply-to queuesrabbitmqctl (Windows)
rabbitmqctl set_policy ha-fed "^hf\." "{""federation-upstream-set"":""all"", ""ha-mode"":""all""}" ^ --priority 1 --apply-to queuesHTTP API
PUT /api/policies/%2f/ha-fed {"pattern": "^hf\.", "definition": {"federation-upstream-set":"all", "ha-mode": "all"}, "priority": 1, "apply-to": "queues"}Web UI
- Navigate to Admin > Policies > Add / update a policy.
- Enter "ha-fed" next to Name, "^hf\." next to Pattern, and select "Queues" next to Apply to.
- Enter "federation-upstream-set" = "all" in the first line next to Policy.
- Enter "ha-mode" = "all" on the next line.
- Click Add policy.
這樣,所有匹配"^hf\."的隊列都會應用"federation-upstream-set"和"ha-mode" 定義.
.