Cassandra資料庫通過JMX方式對外提供監控和管理服務。本文講解如何配置和開啟Cassandra的JMX服務。 環境說明 本文是基於以下版本的系統和服務: cassandra 3.11.6 openjdk 1.8.0 mx4j 3.0.2 Ubuntu 18.04.4 LTS 需要說明的是,當 ...
Cassandra資料庫通過JMX方式對外提供監控和管理服務。本文講解如何配置和開啟Cassandra的JMX服務。
環境說明
本文是基於以下版本的系統和服務:
- cassandra 3.11.6
- openjdk 1.8.0
- mx4j 3.0.2
- Ubuntu 18.04.4 LTS
需要說明的是,當使用java 11以服務形式啟動cassandra,服務啟動後會進入 active(exited)
狀態:
$ systemctl status cassandra
● cassandra.service - LSB: distributed storage system for structured data
Loaded: loaded (/etc/init.d/cassandra; generated)
Active: active (exited) since Wed 2020-05-13 13:48:21 CST; 4s ago
Docs: man:systemd-sysv-generator(8)
Process: 23280 ExecStop=/etc/init.d/cassandra stop (code=exited, status=0/SUCCESS)
Process: 23298 ExecStart=/etc/init.d/cassandra start (code=exited, status=0/SUCCESS)
這是因為有參數不支持導致jvm啟動失敗。雖然根據Cassandra 3的文檔,java 1.8及以上版本都支持,但至少java 11並不支持。
Cassandra目錄和文件
安裝和數據目錄
Cassandra安裝在 /usr/share/cassandra
目錄下。這個目錄的子目錄 /lib
下是Cassandar的依賴包,後面安裝配置MX4J服務時,會用到這個目錄。
Cassandra的數據文件保存在 /var/lib/cassandra
目錄下。一般可以通過這個目錄來備份和恢複數據。
日誌文件在 /var/log/cassandra
目錄下。這個目錄有三種日誌文件 system.log
, debug.log
和gc.log
。多數情況下,通過查看system.log
可以瞭解系統的運行狀態和錯誤信息。
配置和運行腳本
在Ubuntu上通過Debian Packages方式安裝Cassandra之後,Cassandra可以以服務方式啟動。接下來的配置也都是基於服務方式操作Cassandra的情況。
Cassandra沒有提供Systemd服務的配置,所以服務操作還是通過 /etc/init.d/
目錄下的 cassandra
腳本來定義的。可以根據這個腳本來分析Cassandra服務的啟動過程。
根據服務啟動腳本,可以發現/etc/default/cassandra
配置腳本會用來設置運行時所需要的環境變數。比如,如果系統預設的java是不相容的版本,就可以在這個腳本中添加JAVA_HOME
和JRE_HOME
環境變數,比如:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export JRE_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre
註意,如果不是以系統服務的方式啟動Cassandra,則這個配置腳本中設置的環境變數不會生效。
最主要的配置文件和腳本在/etc/cassandra
目錄下。這個腳本會根據環境變數等參數動態的計算一些jvm啟動參數。這個目錄下的另外一個配置文件jvm.options
也可以用來設置jvm啟動參數,但是cassandra-env.sh
腳本設置的優先順序比較高,所以要註意確認jvm.options
中的設置不會被cassandra-env.sh
覆蓋。本文主要使用cassandra-env.sh
腳本來設置需要的參數。
配置MX4J HttpAdaptor
Cassandra可以與MX4J HttpAdaptor集成,通過Web控制台的方式提供JMX服務訪問。
為了開啟MX4J HttpAdaptor服務,需要安裝MX4J。MX4J可以從下載頁面下載需要的版本。下載並解壓後,在mx4j-3.0.2/lib
目錄下找到mx4j-tools.jar
,將這個jar包安裝到Cassandra的lib目錄/var/lib/cassandra
下,然後重啟Cassandra。
如果一切正常,可以看到system.log
中以下日誌內容:
INFO [main] 2020-05-14 09:29:24,963 Mx4jTool.java:61 - mx4j successfuly loaded
日誌里的拼寫錯誤是Cassandra的代碼問題,不是我弄錯了。
預設情況下MX4J HttpAdaptor監聽的是127.0.0.1
上的8081
埠。如果啟動正常,可以通過本地瀏覽器訪問Web控制台了:
8081
這個埠很有可能和其他服務衝突。當埠衝突時,可以在system.log
中看到以下錯誤信息:
WARN [main] 2020-05-14 15:52:41,847 Mx4jTool.java:70 - Could not start register mbean in JMX
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_252]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_252]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_252]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_252]
at org.apache.cassandra.utils.Mx4jTool.maybeLoad(Mx4jTool.java:60) ~[apache-cassandra-3.11.6.jar:3.11.6]
at org.apache.cassandra.service.CassandraDaemon.setup(CassandraDaemon.java:197) [apache-cassandra-3.11.6.jar:3.11.6]
at org.apache.cassandra.service.CassandraDaemon.activate(CassandraDaemon.java:630) [apache-cassandra-3.11.6.jar:3.11.6]
at org.apache.cassandra.service.CassandraDaemon.main(CassandraDaemon.java:757) [apache-cassandra-3.11.6.jar:3.11.6]
Caused by: java.net.BindException: Address already in use (Bind failed)
at java.net.PlainSocketImpl.socketBind(Native Method) ~[na:1.8.0_252]
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387) ~[na:1.8.0_252]
at java.net.ServerSocket.bind(ServerSocket.java:390) ~[na:1.8.0_252]
at java.net.ServerSocket.<init>(ServerSocket.java:252) ~[na:1.8.0_252]
at mx4j.tools.adaptor.PlainAdaptorServerSocketFactory.createServerSocket(PlainAdaptorServerSocketFactory.java:24) ~[mx4j-tools.jar:na]
at mx4j.tools.adaptor.http.HttpAdaptor.createServerSocket(HttpAdaptor.java:672) ~[mx4j-tools.jar:na]
at mx4j.tools.adaptor.http.HttpAdaptor.start(HttpAdaptor.java:478) ~[mx4j-tools.jar:na]
... 8 common frames omitted
另外,如果希望從遠程訪問,需要設置監聽地址。此時,可以在/etc/default/cassandra
腳本中將這兩個變數設置為期望的值,然後重啟Cassandra服務:
export MX4J_ADDRESS="-Dmx4jaddress=0.0.0.0"
export MX4J_PORT="-Dmx4jport=7081"
設置成功後,可以在system.log
日誌中看到mx4jaddress
和mx4jport
虛擬機參數:
INFO [main] 2020-05-14 16:04:19,007 CassandraDaemon.java:506 - JVM Arguments: [-Xloggc:/var/log/cassandra/gc.log, -ea, -XX:+UseThreadPriorities, -XX:ThreadPriorityPolicy=42, -XX:+HeapDumpOnOutOfMemoryError, -Xss256k, -XX:StringTableSize=1000003, -XX:+AlwaysPreTouch, -XX:-UseBiasedLocking, -XX:+UseTLAB, -XX:+ResizeTLAB, -XX:+UseNUMA, -XX:+PerfDisableSharedMem, -Djava.net.preferIPv4Stack=true, -XX:+UseParNewGC, -XX:+UseConcMarkSweepGC, -XX:+CMSParallelRemarkEnabled, -XX:SurvivorRatio=8, -XX:MaxTenuringThreshold=1, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -XX:CMSWaitDuration=10000, -XX:+CMSParallelInitialMarkEnabled, -XX:+CMSEdenChunksRecordAlways, -XX:+CMSClassUnloadingEnabled, -XX:+PrintGCDetails, -XX:+PrintGCDateStamps, -XX:+PrintHeapAtGC, -XX:+PrintTenuringDistribution, -XX:+PrintGCApplicationStoppedTime, -XX:+PrintPromotionFailure, -XX:+UseGCLogFileRotation, -XX:NumberOfGCLogFiles=10, -XX:GCLogFileSize=10M, -Xms3952M, -Xmx3952M, -Xmn600M, -XX:+UseCondCardMark, -XX:CompileCommandFile=/etc/cassandra/hotspot_compiler, -javaagent:/usr/share/cassandra/lib/jamm-0.3.0.jar, -Dcassandra.jmx.local.port=7199, -Dcom.sun.management.jmxremote.authenticate=false, -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password, -Djava.library.path=/usr/share/cassandra/lib/sigar-bin, -Dmx4jaddress=0.0.0.0, -Dmx4jport=7081, -XX:OnOutOfMemoryError=kill -9 %p, -Dlogback.configurationFile=logback.xml, -Dcassandra.logdir=/var/log/cassandra, -Dcassandra.storagedir=/var/lib/cassandra, -Dcassandra-pidfile=/var/run/cassandra/cassandra.pid, -XX:HeapDumpPath=/var/lib/cassandra/java_1589443456.hprof, -XX:ErrorFile=/var/lib/cassandra/hs_err_1589443456.log]
當然,直接在cassandra-env.sh
腳本設置這兩個環境變數也是可以的。
安全
雖然MX4J HttpAdaptor支持用基於戶名和密碼的基礎認證,但是Cassandra沒有使用這個特性,任何人都可以訪問Web控制台,所以要謹慎決定是否要開啟MX4J HttpAdaptor,以及監控的地址。
配置JMX
預設情況下,Cassandra開啟了JMX的本地訪問,監聽埠是7199
。在Cassandra所在伺服器中運行JConsole, 新建連接視窗中選擇 遠程進程 ,在地址中填入 127.0.0.1:7199
,用戶名和密碼留空,然後就可以連接了:
由於預設配置下使用的不是SSL連接,JConsole會有警告信息,選擇使用不安全連接就可以繼續了:
連接成功後,可以看到虛擬機的運行狀態以及其他JMX信息:
遠程訪問
開啟遠程訪問首先需要在/etc/default/cassandra
腳本中添加以下兩個環境變數:
export LOCAL_JMX=no
export JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=192.168.112.16"
其中,虛擬機參數java.rmi.server.hostname
用來設置JMX服務訪問的功能變數名稱或者地址。如果不顯試設置,可能會導致遠程訪問失敗。這個地址不一定是服務監聽的地址,比如如果cassandra運行在docker容器中,通過埠映射到宿主機上,那麼就需要設置為宿主機的地址或者功能變數名稱。
然後創建文件/etc/cassandra/jmxremote.password
,用來設置JMX訪問所需的用戶名和密碼,比如在文件中加入:
jmx 12345
這裡jmx
是用戶名,12345
是密碼,兩者之間用空格分隔。如果有多個用戶,則每個用戶一行。為了安全性,建議將這個文件設置為只有cassandra用戶可以訪問和修改。
如果配置成功,重啟Cassandra服務可以在system.log
中的jvm參數信息中看到java.rmi.server.hostname
, cassandra.jmx.remote.port
, com.sun.management.jmxremote.rmi.port
, com.sun.management.jmxremote.authenticate
, com.sun.management.jmxremote.password.file
等的值:
INFO [main] 2020-05-18 19:11:47,721 CassandraDaemon.java:506 - JVM Arguments: [-Djava.rmi.server.hostname=192.168.112.16, -Xloggc:/var/log/cassandra/gc.log, -ea, -XX:+UseThreadPriorities, -XX:ThreadPriorityPolicy=42, -XX:+HeapDumpOnOutOfMemoryError, -Xss256k, -XX:StringTableSize=1000003, -XX:+AlwaysPreTouch, -XX:-UseBiasedLocking, -XX:+UseTLAB, -XX:+ResizeTLAB, -XX:+UseNUMA, -XX:+PerfDisableSharedMem, -Djava.net.preferIPv4Stack=true, -XX:+UseParNewGC, -XX:+UseConcMarkSweepGC, -XX:+CMSParallelRemarkEnabled, -XX:SurvivorRatio=8, -XX:MaxTenuringThreshold=1, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -XX:CMSWaitDuration=10000, -XX:+CMSParallelInitialMarkEnabled, -XX:+CMSEdenChunksRecordAlways, -XX:+CMSClassUnloadingEnabled, -XX:+PrintGCDetails, -XX:+PrintGCDateStamps, -XX:+PrintHeapAtGC, -XX:+PrintTenuringDistribution, -XX:+PrintGCApplicationStoppedTime, -XX:+PrintPromotionFailure, -XX:+UseGCLogFileRotation, -XX:NumberOfGCLogFiles=10, -XX:GCLogFileSize=10M, -Xms3952M, -Xmx3952M, -Xmn600M, -XX:+UseCondCardMark, -XX:CompileCommandFile=/etc/cassandra/hotspot_compiler, -javaagent:/usr/share/cassandra/lib/jamm-0.3.0.jar, -Dcassandra.jmx.remote.port=7199, -Dcom.sun.management.jmxremote.rmi.port=7199, -Dcom.sun.management.jmxremote.authenticate=true, -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password, -Djava.library.path=/usr/share/cassandra/lib/sigar-bin, -Dmx4jaddress=0.0.0.0, -Dmx4jport=7081, -XX:OnOutOfMemoryError=kill -9 %p, -Dlogback.configurationFile=logback.xml, -Dcassandra.logdir=/var/log/cassandra, -Dcassandra.storagedir=/var/lib/cassandra, -Dcassandra-pidfile=/var/run/cassandra/cassandra.pid, -XX:HeapDumpPath=/var/lib/cassandra/java_1589800305.hprof, -XX:ErrorFile=/var/lib/cassandra/hs_err_1589800305.log]
接下來就可以遠程訪問Cassandra的JMX服務了:
除了地址需要改成遠程地址之後,還需要指定正確的用戶名和密碼。後面的操作就和上文中的例子一樣了。
在上面的日誌信息中,可以看到還有很多JMX相關的配置項。如果要調整這些配置,則需要修改cassandra-env.sh
腳本。比如如果希望修改JMX服務監聽的埠,需要在cassandra-env.sh
腳本中找到以下部分,然後將JMX_PORT
變數的值修改為期望的埠:
# Specifies the default port over which Cassandra will be available for
# JMX connections.
# For security reasons, you should not expose this port to the internet. Firewall it if needed.
JMX_PORT="7199"
修改保存後,重啟Cassandra服務,成功的話就可以看到日誌中的相關信息,並用新埠訪問了。
其它相關的配置可以參考cassandra-env.sh
腳本中的註釋說明和Cassandra文檔。