Obsah
1. Sledování činnosti systému Apache Kafka přes JMX i metriky Promethea (dokončení)
2. Přístup z lokální JConsole na službu běžící na lokálním JVM
3. Přístup z lokální JConsole na vzdálený počítač
4. Jednoduché zabezpečení přístupu přes jmxremote.password
5. Omezení přístupu definované v souboru jmxremote.access
6. Chování jconsole pro uživatele s rolemi readonly a readwrite
7. Použití SSL v reálném provozu
8. Metriky, které je vhodné sledovat
10. Metriky vztažené k producentům
11. Vytvoření jednoduchého producenta zpráv naprogramovaného v JVM jazyce
12. Metriky vztažené ke konzumentům
13. Vytvoření jednoduchého konzumenta zpráv naprogramovaného v JVM jazyce
14. Metriky virtuálního stroje Javy
16. Povolení „four-letter words“ ZooKeepera
17. Repositář s demonstračními příklady
18. Odkazy na relevantní články na Rootu
1. Sledování činnosti systému Apache Kafka přes JMX i metriky Promethea (dokončení)
Na úvodní článek, v němž jsme si popsali základní technologie, které lze využít pro sledování činnosti systému Apache Kafka, dnes navážeme. Již víme, že jak Kafka brokeři, tak i ZooKeeper nabízí své metriky přes rozhraní nazvané JMX neboli Java Management Extensions. Takové metriky lze přes JMX zpracovávat několika nástroji, mezi než patří i standardní nástroj nazvaný jconsole, který je dodávaný společně s JDK (ovšem nikoli se samotným JRE, tedy s běhovým prostředím Javy). Existuje ovšem i knihovna nazvaná JMX Exporter, která dokáže tyto metriky zpřístupnit i ve formátu kompatibilním s Prometheem a nepřímo tak i s Grafanou, tedy s technologiemi, jež se v současnosti velmi často používají v praxi, například pro monitoring mikroslužeb, databází, message brokerů atd. (stručně řečeno – metriky budou dostupné přes běžné HTTP se všemi výhodami, které to přináší).
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-1-prev.png)
Obrázek 1: ZooKeeper i Apache Kafka běžící lokálně lze sledovat právě přes nástroj jconsole.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-2-prev.png)
Obrázek 2: Příklad „dashboardu“ vytvořeného pro účely sledování Apache Kafky v Grafaně. Důležitými metrikami jsou frekvence příchozích zpráv i celkový „lag“, tedy zpoždění konzumentů zpráv oproti producentům.
2. Přístup z lokální JConsole na službu běžící na lokálním JVM
Minule jsme si ukázali, jakým způsobem je možné se připojit nástrojem jconsole k vybranému lokálnímu virtuálnímu stroji Java, na němž běží sledovaná aplikace nabízející své metriky přes JMX. Celý postup si připomeneme na několika screenshotech, v němž je sledován běžící demonstrační příklad:
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/592/kafka-jmx-1-prev.png)
Obrázek 3: Po spuštění nástroje jconsole se zobrazí všechny nalezené aplikace běžící nad JVM. Vybereme aplikaci Main.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/592/kafka-jmx-2-prev.png)
Obrázek 4: Povolíme připojení bez SSL (ostatně jedná se o lokální JVM).
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/592/kafka-jmx-3-prev.png)
Obrázek 5: Následně se zobrazí základní informace o sledované aplikaci (obsazení paměti apod.).
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/592/kafka-jmx-4-prev.png)
Obrázek 6: Na listu MBeans se kromě standardních MBeans objeví i jmenný prostor pojmenovaný „cz.root.app“.
3. Přístup z lokální JConsole na vzdálený počítač
Nyní si ukážeme, jak lze nakonfigurovat vzdálené připojení. Princip je jednoduchý – použijeme lokální instalaci nástroje jconsole (je součástí JDK) a připojíme se s ní k virtuálnímu stroji Javy, který ovšem běží vzdáleně (na jiném počítači). Nejprve si připravíme náš testovací příklad na vzdáleném počítači (může jít samozřejmě o virtuální počítač, pokud ovšem správně nastavíte mapování portů). Připojíme se k tomuto počítači, získáme (stáhneme) zdrojové kódy příkladu a přeložíme ho:
$ javac Main.java
Spuštění ovšem bude vypadat odlišně, protože budeme muset povolit vzdálený přístup k JMX a taktéž budeme muset nastavit port, na němž bude JXM dostupné. Vybereme port 1099, ovšem pochopitelně je možné v případě potřeby zvolit i jiný port:
$ java -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.port=1099 \ Main
Nyní na lokálním počítači spustíme nástroj jconsole:
$ export _JAVA_OPTIONS="-Dawt.useSystemAAFontSettings=on -Dswing.aatext=true -Dsun.java2d.xrender=true" $ jconsole
Samotné připojení ovšem vypadá odlišně, protože je nutné (logicky) ručně specifikovat jméno vzdáleného počítače i port, na kterém je JMX dostupné:
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-3-prev.png)
Obrázek 7: Specifikace jména či IP adresy vzdáleného počítače a portu, na kterém je JMX dostupné (seznam lokálních JVM tedy v tomto případě ignorujeme).
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-4-prev.png)
Obrázek 8: Připojování ke vzdálené JVM, resp. k aplikaci, které v rámci této JVM běží.
4. Jednoduché zabezpečení přístupu přes jmxremote.password
Řešení ukázané v předchozí kapitole je vhodné využít pouze v těch případech, kdy je nutné sledovat Kafku běžící například v testovacím prostředí. Problém tohoto řešení spočívá v tom, že kdokoli, kdo „odhadne“ port používaný JMX, se může vzdáleně připojit a sledovat metriky, popř. volat metody dostupné přes MBeans. Ukažme si proto alespoň minimální způsoby zabezpečení. První z nich spočívá v tom, že se vytvoří soubor pojmenovaný (typicky) jmxremote.password, který bude obsahovat dvojice jméno+heslo, a to v čitelné podobě (!). Tento soubor, resp. přesněji řečeno jeho ukázková varianta, je součástí instalace JRE. Například na mém systému je tento soubor umístěn v adresáři /usr/lib/jvm/java/jre/lib/management (ovšem tato cesta může být na jiných systémech odlišná, ostatně i zde je složena ze symlinků nastavovaných pomocí alternatives):
$ ls -l /usr/lib/jvm/java/jre/lib/management total 28 -rw-r--r--. 1 root root 3998 Nov 1 2018 jmxremote.access -r--r--r--. 1 root root 2856 Nov 1 2018 jmxremote.password.template -rw-r--r--. 1 root root 14630 Nov 1 2018 management.properties -r--r--r--. 1 root root 3376 Nov 1 2018 snmp.acl.template
Soubor jmxremote.password.template zkopírujte pod jménem jmxremote.password do adresáře s demonstračním příkladem. V dalším kroku nastavíme práva souboru na u+r tedy -r-------- (žádná jiná – je to kontrolováno při inicializaci JMX!). Na konec souboru lze přidat uživatelská jména a hesla:
# ---------------------------------------------------------------------- # Template for jmxremote.password # # o Copy this template to jmxremote.password # o Set the user/password entries in jmxremote.password # o Change the permission of jmxremote.password to read-only # by the owner. # # See below for the location of jmxremote.password file. # ---------------------------------------------------------------------- ############################################################## # Password File for Remote JMX Monitoring ############################################################## # # Password file for Remote JMX API access to monitoring. This # file defines the different roles and their passwords. The access # control file (jmxremote.access by default) defines the allowed # access for each role. To be functional, a role must have an entry # in both the password and the access files. # # Default location of this file is $JRE/lib/management/jmxremote.password # You can specify an alternate location by specifying a property in # the management config file $JRE/lib/management/management.properties # or by specifying a system property (See that file for details). ############################################################## # File permissions of the jmxremote.password file ############################################################## # Since there are cleartext passwords stored in this file, # this file must be readable by ONLY the owner, # otherwise the program will exit with an error. # # The file format for password and access files is syntactically the same # as the Properties file format. The syntax is described in the Javadoc # for java.util.Properties.load. # Typical password file has multiple lines, where each line is blank, # a comment (like this one), or a password entry. # # # A password entry consists of a role name and an associated # password. The role name is any string that does not itself contain # spaces or tabs. The password is again any string that does not # contain spaces or tabs. Note that passwords appear in the clear in # this file, so it is a good idea not to use valuable passwords. # # A given role should have at most one entry in this file. If a role # has no entry, it has no access. # If multiple entries are found for the same role name, then the last one # is used. # # In a typical installation, this file can be read by anybody on the # local machine, and possibly by people on other machines. # For # security, you should either restrict the access to this file, # or specify another, less accessible file in the management config file # as described above. # # Following are two commented-out entries. The "measureRole" role has # password "QED". The "controlRole" role has password "R&D". # monitorRole nbusr123 controlRole nbusr789
Příklad se posléze spustí s těmito volbami:
$ java -Dcom.sun.management.jmxremote.authenticate=true \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.password.file=jmxremote.password \ -Dcom.sun.management.jmxremote.port=1099 \ Main
Do připojovacího dialogu je nyní nutné jméno i heslo zapsat:
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-5-prev.png)
Obrázek 9: Zadání jména a hesla při připojování ke vzdálené JVM.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-6-prev.png)
Obrázek 10: Stav po přihlášení ke vzdálené JVM.
5. Omezení přístupu definované v souboru jmxremote.access
Dalším důležitým souborem, který naleznete v adresáři /usr/lib/jvm/java/jre/lib/management, je soubor nazvaný jmxremote.access:
$ ls -l /usr/lib/jvm/java/jre/lib/management total 28 -rw-r--r--. 1 root root 3998 Nov 1 2018 jmxremote.access -r--r--r--. 1 root root 2856 Nov 1 2018 jmxremote.password.template -rw-r--r--. 1 root root 14630 Nov 1 2018 management.properties -r--r--r--. 1 root root 3376 Nov 1 2018 snmp.acl.template
V tomto souboru jsou pro jednotlivé uživatele definovány přístupové role, které jsou pouze dvě: readonly a readwrite. Ukázková varianta tohoto souboru vypadá takto:
###################################################################### # Default Access Control File for Remote JMX(TM) Monitoring ###################################################################### # # Access control file for Remote JMX API access to monitoring. # This file defines the allowed access for different roles. The # password file (jmxremote.password by default) defines the roles and their # passwords. To be functional, a role must have an entry in # both the password and the access files. # # The default location of this file is $JRE/lib/management/jmxremote.access # You can specify an alternate location by specifying a property in # the management config file $JRE/lib/management/management.properties # (See that file for details) # # The file format for password and access files is syntactically the same # as the Properties file format. The syntax is described in the Javadoc # for java.util.Properties.load. # A typical access file has multiple lines, where each line is blank, # a comment (like this one), or an access control entry. # # An access control entry consists of a role name, and an # associated access level. The role name is any string that does not # itself contain spaces or tabs. It corresponds to an entry in the # password file (jmxremote.password). The access level is one of the # following: # "readonly" grants access to read attributes of MBeans. # For monitoring, this means that a remote client in this # role can read measurements but cannot perform any action # that changes the environment of the running program. # "readwrite" grants access to read and write attributes of MBeans, # to invoke operations on them, and optionally # to create or remove them. This access should be granted # only to trusted clients, since they can potentially # interfere with the smooth operation of a running program. # # The "readwrite" access level can optionally be followed by the "create" and/or # "unregister" keywords. The "unregister" keyword grants access to unregister # (delete) MBeans. The "create" keyword grants access to create MBeans of a # particular class or of any class matching a particular pattern. Access # should only be granted to create MBeans of known and trusted classes. # # For example, the following entry would grant readwrite access # to "controlRole", as well as access to create MBeans of the class # javax.management.monitor.CounterMonitor and to unregister any MBean: # controlRole readwrite \ # create javax.management.monitor.CounterMonitorMBean \ # unregister # or equivalently: # controlRole readwrite unregister create javax.management.monitor.CounterMBean # # The following entry would grant readwrite access as well as access to create # MBeans of any class in the packages javax.management.monitor and # javax.management.timer: # controlRole readwrite \ # create javax.management.monitor.*,javax.management.timer.* \ # unregister # # The \ character is defined in the Properties file syntax to allow continuation # lines as shown here. A * in a class pattern matches a sequence of characters # other than dot (.), so javax.management.monitor.* matches # javax.management.monitor.CounterMonitor but not # javax.management.monitor.foo.Bar. # # A given role should have at most one entry in this file. If a role # has no entry, it has no access. # If multiple entries are found for the same role name, then the last # access entry is used. # # # Default access control entries: # o The "monitorRole" role has readonly access. # o The "controlRole" role has readwrite access and can create the standard # Timer and Monitor MBeans defined by the JMX API. monitorRole readonly controlRole readwrite \ create javax.management.monitor.*,javax.management.timer.* \ unregister
Tento soubor si opět můžete zkopírovat do adresáře s demonstračním příkladem a specifikovat ho při spuštění:
$ java -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.password.file=jmxremote.password -Dcom.sun.management.jmxremote.access.file=jmxremote.access -Dcom.sun.management.jmxremote.port=1099 Main
6. Chování jconsole pro uživatele s rolemi readonly a readwrite
Vzhledem k tomu, že v souboru s hesly již máme specifikována dvě jména:
monitorRole nbusr123 controlRole nbusr789
… s příslušnými rolemi nastavenými v souboru jmxremote.access:
monitorRole readonly controlRole readwrite
… si můžeme odzkoušet chování v jconsoli po přihlášení těchto uživatelů.
Nejprve pro uživatele s rolí readonly:
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-7-prev.png)
Obrázek 11: Přihlášení uživatele s rolí readonly.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-8-prev.png)
Obrázek 12: Všechny atributy dostupné přes MBeans jsou čitelné.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-9-prev.png)
Obrázek 13: Dostupná (resp. přesněji řečeno viditelná) je i metoda definovaná v MBeanu.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-10-prev.png)
Obrázek 14: Ovšem ve skutečnosti ji nemůžeme zavolat, což přesně odpovídá vybrané roli.
Následně provedeme tytéž operace, ovšem pro uživatele s rolí readwrite:
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-11-prev.png)
Obrázek 15: Přihlášení uživatele s rolí readwrite.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-12-prev.png)
Obrázek 16: Dostupná (resp. viditelná) je i metoda definovaná v MBeanu.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-13-prev.png)
Obrázek 17: Tuto metodu lze nyní bez problémů zavolat, což opět přesně odpovídá zvolené roli.
7. Použití SSL v reálném provozu
V reálném provozu je navíc nutné zajistit, aby se jméno a heslo přenášelo přes zabezpečený komunikační kanál. Ten zajišťuje SSL (Secure Sockets Layer). Nejprve je nutné nástrojem keytool s přepínačem -genkeypair (ten je dodáván společně s JDK) vygenerovat dvojici klíčů. Následně si vyžádat certifikát od některé důvěryhodné certifikační autority. Tento certifikát se naimportuje, a to opět nástrojem keytool (přepínač –import). Cesty k souboru s klíči a certifikátem se použijí při spuštění aplikace (volby javax.new.ssl…).
Vlastní spuštění sledované aplikace, která má přes JMX poskytovat metriky, nyní proběhne takto:
$ java -Dcom.sun.management.jmxremote.authenticate=true\ -Dcom.sun.management.jmxremote.ssl=true \ -Dcom.sun.management.jmxremote.password.file=jmxremote.password \ -Dcom.sun.management.jmxremote.port=1099 \ -Dcom.sun.management.jmxremote.ssl.need.client.auth=true \ -Djavax.net.ssl.keyStore=/home/${USER}/.keystore -Djavax.net.ssl.keyStorePassword=${PASSWORD} -Djava.security.manager -Djava.security.policy=jmx.policy Main
8. Metriky, které je vhodné sledovat
Již minule jsme si ve stručnosti řekli, že Apache Kafka, resp. přesněji řečeno její jednotlivé části (tedy typicky ZooKeeper a jednotliví brokeři) vytváří a „vystavují“ poměrně velké množství metrik. Ty je možné rozdělit do čtyř skupin:
- Metriky samotného brokera
- Metriky vztažené k producentům
- Metriky vztažené ke konzumentům
- Metriky ZooKeepera (což je samostatný proces)
Jednotlivé důležité metriky budou zmíněny v navazujících kapitolách.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-14-prev.png)
Obrázek 18: MBeans poskytované Kafka brokerem.
9. Metriky samotného brokera
Důležité metriky, které se vztahují přímo k činnosti brokeru (každý běží ve vlastní JVM), jsou vypsány v následující tabulce:
# | Jméno metriky | Označení MBeanu | Stručný popis metriky |
---|---|---|---|
1 | UnderReplicatedPartitions | kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions | zvyšuje se nad nulu, pokud není nějaký broker dostupný (ideálně se zde očekává nulová hodnota) |
2 | IsrShrinksPerSec | kafka.server:type=ReplicaManager,name=IsrShrinksPerSec | změna v počtu replik, které jsou synchronizovány, nutno sledovat společně s IsrExpandsPerSec |
3 | IsrExpandsPerSec | kafka.server:type=ReplicaManager,name=IsrExpandsPerSec | tato hodnota typicky následuje (s časovým zpožděním) předchozí hodnotu. Nutno sledovat rozdíly, tj. stav, kdy se počet replik opět nezvýší na původní hodnotu. |
4 | ActiveControllerCount | kafka.controller:type=KafkaController,name=ActiveControllerCount | počet aktivních controllerů (což je typicky první uzel, který je spuštěn). Pouze jediný broker by měl mít hodnotu nastavenou na 1, ostatní na nulu (jiné hodnoty značí možné problémy se ZooKeeperem). |
5 | OfflinePartitionsCount | kafka.controller:type=KafkaController,name=OfflinePartitionsCount | počet oddílů bez leadera. Nenulová hodnota značí potenciální problém. |
6 | LeaderElectionRateAndTimeMs | kafka.controller:type=ControllerStats,name=LeaderElectionRateAndTimeMs | čas, který byl stráven změnou leadera v případě, že předchozí leader je z nějakého důvodu nedostupný. Typické hodnoty jsou v řádu milisekund. |
7 | TotalTimeMs | kafka.network:type=RequestMetrics,name=TotalTimeMs | čtyři metriky s časy, které byly stráveny čekáním požadavků ve frontě, v leaderu, čekáním na další požadavek atd. Většinou nemá smysl sledovat absolutní hodnoty, ale spíše velikosti změn. |
8 | PurgatorySize | kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize | čas strávený vyřízením požadavku. Jedná se o dvě metriky: jedna pro čekající požadavky (nejsou k dispozici data), druhá pro požadavky čekající na ack |
9 | BytesInPerSec | kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec | tato metrika sleduje síťové přenosy, konkrétně počet bajtů přijatých za sekundu (síť může být úzkým hrdlem, ovšem méně často, než diskové operace) |
10 | BytesOutPerSec | kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec | tato metrika taktéž sleduje síťové přenosy, konkrétně počet bajtů odeslaných za sekundu |
10 | RequestsPerSecond | kafka.network:type=RequestMetrics,name=RequestsPerSec | počet požadavků od producentů a konzumentů. Vysoké hodnoty (nebo jejich změna) může znamenat připojení špatně naprogramovaného klienta. |
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-15-prev.png)
Obrázek 19: MBeans dostupné v prostoru kafka.server.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-16-prev.png)
Obrázek 20: MBeans dostupné v prostoru kafka.controller.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-17-prev.png)
Obrázek 21: MBeans dostupné v prostoru kafka.network.
10. Metriky vztažené k producentům
Každý producent zpráv, který je naprogramován v Javě, Scale, Clojure atd. (tedy v jazyku běžícím nad JVM) a který komunikuje s Apache Kafkou, nabízí následující důležité metriky, které lze přes JMX sledovat:
# | Jméno metriky | Označení MBeanu | Stručný popis metriky |
---|---|---|---|
1 | compression-rate-avg | kafka.producer:type=producer-metrics,client-id=([-.w]+) | míra komprimace zpráv posílaných producentem |
2 | response-rate | kafka.producer:type=producer-metrics,client-id=([-.w]+) | rychlost odpovědí od brokera, ke kterému je producent připojen (ovlivněno volbou request.required.acks, měla by být víceméně stabilní) |
3 | request-rate | kafka.producer:type=producer-metrics,client-id=([-.w]+) | rychlost požadavků producenta, lze omezit pomocí technologie rate-limit |
4 | request-latency-avg | kafka.producer:type=producer-metrics,client-id=([-.w]+) | časové zpoždění mezi posláním zprávy a odpovědí brokeru (měla by být stabilní) |
5 | outgoing-byte-rate | kafka.producer:type=producer-metrics,client-id=([-.w]+) | měří míru využití sítě, resp. rychlost přenosu dat |
6 | io-wait-time-ns-avg | kafka.producer:type=producer-metrics,client-id=([-.w]+) | čekání způsobené tím, že producent posílá více zpráv, než broker dokáže zpracovat (hodnota by měla být co nejnižší) |
7 | batch-size-avg | kafka.producer:type=producer-metrics,client-id=([-.w]+) | velikost bloku, který se posílá (16 kB je výchozí hodnota), pokud producent čeká na brokera |
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-18-prev.png)
Obrázek 22: Sledování metrik producenta zpráv.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-19-prev.png)
Obrázek 23: Graf zobrazený u vybrané metriky.
11. Vytvoření jednoduchého producenta zpráv naprogramovaného v JVM jazyce
Metriky související s producenty zpráv jsou (pochopitelně) nabízeny těmi producenty, které jsou naprogramovány v nějakém jazyce, který generuje bajtkód zpracovávaný virtuálním strojem Javy. Pro zajímavost si tedy vytvoříme producenta nikoli přímo v Javě (takový producent je použitý v každém tutoriálu), ale v jazyce Clojure. Využijeme přitom informace, které jsou zmíněny v článku Pokročilý streaming založený na projektu Apache Kafka, jazyku Clojure a knihovně Jackdaw (streamy a kolony).
Do projektového souboru se doplní závislost na knihovně jackdaw:
(defproject produce-messages-1 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" :url "https://www.eclipse.org/legal/epl-2.0/"} :dependencies [[org.clojure/clojure "1.10.1"] [fundingcircle/jackdaw "0.7.6"]] :main ^:skip-aot produce-messages-4.core :target-path "target/%s" :profiles {:uberjar {:aot :all :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
Samotný producent zpráv generuje 1000 zpráv s frekvencí přibližně jedna zpráva za sekundu:
(ns produce-messages-4.core (:require [jackdaw.client :as jc] [clojure.pprint :as pp])) (def producer-config {"bootstrap.servers" "localhost:9092" "key.serializer" "org.apache.kafka.common.serialization.StringSerializer" "value.serializer" "org.apache.kafka.common.serialization.StringSerializer" "acks" "all" "client.id" "foo"}) (defn -main [& args] (with-open [producer (jc/producer producer-config)] (doseq [i (range 1 1000)] (Thread/sleep 1000) (let [key (str i) value (str "Message #" i)] (println "Publishing message with key '" key "' and value '" value "'") (let [record-metadata (jc/produce! producer {:topic-name "test3"} key value)] (pp/pprint @record-metadata))) )))
Tento projekt naleznete na adrese https://github.com/tisnik/message-queues-examples/tree/master/kafka/clojure/produce-messages-4.
12. Metriky vztažené ke konzumentům
Další důležité metriky, o nichž se v dnešním článku zmíníme, jsou metriky vztažené ke konzumentům. Opět platí, že tyto metriky jsou dostupné ve chvíli, kdy je klient naprogramován v Javě nebo v jiném jazyku, který produkuje bajtkód zpracovávaný virtuálním strojem Javy:
# | Jméno metriky | Označení MBeanu | Stručný popis metriky |
---|---|---|---|
1 | records-lag | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+),topic=([-.w]+),partition=([-.w]+) | jedna z nejdůležitějších metrik vůbec – ukazuje, jak opožděn je konzument zpráv oproti nejnovější zprávě v tématu |
2 | records-lag-max | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+),topic=([-.w]+),partition=([-.w]+) | největší hodnota získaná předchozí metrikou za dobu života konzumenta |
3 | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+) | dtto, ovšem neomezeno na klienta a téma | |
4 | bytes-consumed-rate | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+),topic=([-.w]+) | rychlost přenosu dat ke konzumentovi (měří tedy rychlost přenosu po síti) |
5 | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+) | dtto, opět bez omezení | |
6 | records-consumed-rate | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+),topic=([-.w]+) | opět měření rychlosti konzumace zpráv, ovšem měřeno v počtu zpráv (ty nemusí mít konstantní velikost) |
7 | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+) | dtto, opět bez omezení | |
8 | fetch-rate | kafka.consumer:type=consumer-fetch-manager-metrics,client_id=([-.w]+) | rychlost konzumace zpráv, pokud se blíží k nule, může to znamenat problémy na straně konzumenta (například pomalá databáze atd.) |
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-20-prev.png)
Obrázek 24: Sledování metrik konzumenta zpráv.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-21-prev.png)
Obrázek 25: Graf zobrazený u vybrané metriky.
13. Vytvoření jednoduchého konzumenta zpráv naprogramovaného v JVM jazyce
Opět si ukážeme jednoduchého konzumenta zpráv, kterého lze spustit a sledovat jeho metriky s využitím MBeans a technologie JMX. Zdrojový kód tohoto demonstračního příkladu, který je naprogramován v Clojure, je dostupný na adrese https://github.com/tisnik/message-queues-examples/tree/master/kafka/clojure/consume-messages-3. Po vytvoření Clojure projektu se do projektového souboru project.clj přidala knihovna jackdaw:
(defproject consume-messages-2 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" :url "https://www.eclipse.org/legal/epl-2.0/"} :dependencies [[org.clojure/clojure "1.10.1"] [fundingcircle/jackdaw "0.7.6"]] :main ^:skip-aot consume-messages-3.core :target-path "target/%s" :profiles {:uberjar {:aot :all :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
Samotný konzument zpracovává zprávy v nekonečné smyčce, takže po zpracování celého tématu čeká na příchod nových zpráv:
(ns consume-messages-3.core (:require [jackdaw.client :as jc] [jackdaw.client.log :as jl] [clojure.pprint :as pp])) (def consumer-config {"bootstrap.servers" "localhost:9092" "key.deserializer" "org.apache.kafka.common.serialization.StringDeserializer" "value.deserializer" "org.apache.kafka.common.serialization.StringDeserializer" "auto.offset.reset" "earliest" "group.id" "group-A"}) (defn -main [& args] (with-open [consumer (-> (jc/consumer consumer-config) (https://github.com/tisnik/message-queues-examples/tree/master/kafka/clojure/consume-messages-3))] (doseq [{:keys [key value partition timestamp offset]} (jl/log consumer 10)] (println "key: " key) (println "value: " value) (println "partition: " partition) (println "timestamp: " timestamp) (println "offset: " offset))))
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-22-prev.png)
Obrázek 26: Sledování vybraných metrik tohoto konzumenta zpráv.
14. Metriky virtuálního stroje Javy
V některých situacích může být důležité sledovat i vybrané metriky poskytované samotným virtuálním strojem Javy (JVM). Kritickým místem bývá správce paměti, který sice běží na pozadí (v samostatných vláknech), ovšem při „úklidu“ Old Generation budou ostatní vlákna brokera či ZooKeepera na určitý okamžik pozastaveny. Kafka používá správce paměti G1, takže se vyplatí sledovat tyto metriky:
# | Jméno metriky | Označení MBeanu | Stručný popis metriky |
---|---|---|---|
1 | CollectionCount | java.lang:type=GarbageCollector,name=G1 Young Generation | celkový počet úklidů Young generation (bývá velký, ovšem čas úklidu malý) |
2 | CollectionTime | java.lang:type=GarbageCollector,name=G1 Young Generation | celkový čas strávený úklidem Young generation |
3 | CollectionCount | java.lang:type=GarbageCollector,name=G1 Old Generation | celkový počet úklidů Old generation (bývá malý, ovšem čas úklidu delší) |
4 | CollectionTime | java.lang:type=GarbageCollector,name=G1 Old Generation | celkový čas strávený úklidem Old generation |
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-23-prev.png)
Obrázek 27: Sledování metrik správce paměti Kafka brokeru.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-24-prev.png)
Obrázek 28: Sledování metrik správce paměti Kafka brokeru.
15. Metriky ZooKeepera
Většina metrik ZooKeepera je dostupná přes takzvané „four-letter words“ zmíněné v navazující kapitole. Sledovat je vhodné zejména následující metriky:
# | Jméno metriky | Stručný popis metriky |
---|---|---|
1 | outstanding_requests | počet požadavků, které nebyly vyřízeny (mělo by se blížit k nule) |
2 | avg_latency | čas (vyjádřený v milisekundách) na vyřízení požadavku ZooKeeperem |
3 | num_alive_connections | počet klientů, kteří jsou v daný okamžik k ZooKeeperu přihlášeni |
4 | followers | počet aktivních followerů (bez leadera) |
5 | pending_syncs | ZooKeeper musí ukládat transakční logy na disk, zde je zobrazen počet čekajících zápisů (čím menší, tím lépe) |
6 | open_file_descriptor_count | počet otevřených souborů se stavovými informacemi (musí být menší, než povolený počet deskriptorů nastavený v systému) |
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-25-prev.png)
Obrázek 29: Metriky ZooKeepera.
16. Povolení „four-letter words“ ZooKeepera
V předchozí kapitole jsme se zmínili o tzv. „four-letter words“. Jedná se o příkazy (každý se skládá ze čtyř písmen – odtud jejich název), které je možné ZooKeeperu posílat přes telnet či nc a získávat tak další informace. Ovšem jednotlivé příkazy je nejprve zapotřebí povolit, a to buď specifikací jednotlivých příkazů, nebo lze využít žolíkového znaku *:
$ export KAFKA_OPTS="-Dzookeeper.4lw.commands.whitelist=*" $ ./zookeeper.sh
Po tomto spuštění ZooKeepera se můžeme k jeho instanci připojit telnetem:
$ telnet localhost 2181 Trying ::1... Connected to localhost. Escape character is '^]'.
Dostupné jsou příkazy popsané zde. Zajímat nás bude příkaz mntr. Ten vypíše základní metriky ZooKeepera a ukončí připojení:
mntr zk_version 3.5.6-c11b7e26bc554b8523dc929761dd28808913f091, built on 10/08/2019 20:18 GMT zk_avg_latency 0 zk_max_latency 0 zk_min_latency 0 zk_packets_received 1 zk_packets_sent 0 zk_num_alive_connections 1 zk_outstanding_requests 0 zk_server_state standalone zk_znode_count 5 zk_watch_count 0 zk_ephemerals_count 0 zk_approximate_data_size 44 zk_open_file_descriptor_count 125 zk_max_file_descriptor_count 4096 Connection closed by foreign host.
![Autor: tisnik, podle licence: <a href="https://creativecommons.org/licenses/by/4.0/legalcode.cs">CC-BY</a>](https://i.iinfo.cz/images/433/kafka-jmx-2-26-prev.png)
Obrázek 30: Další ukázka „dashboardu“ zobrazujícího vybrané metriky Apache Kafky.
17. Repositář s demonstračními příklady
Zdrojové soubory naprogramované v Javě a použité v předchozím i v dnešním článku byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/presentations/. V případě, že nebudete chtít klonovat celý repositář, můžete namísto toho použít odkazy na jednotlivé soubory, které naleznete v následující tabulce:
18. Odkazy na relevantní články na Rootu
- Použití nástroje Apache Kafka v aplikacích založených na mikroslužbách
https://www.root.cz/clanky/pouziti-nastroje-apache-kafka-v-aplikacich-zalozenych-na-mikrosluzbach/ - Apache Kafka: distribuovaná streamovací platforma
https://www.root.cz/clanky/apache-kafka-distribuovana-streamovaci-platforma/ - Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw/ - Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw (2. část)
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw-2-cast/ - Pokročilý streaming založený na projektu Apache Kafka, jazyku Clojure a knihovně Jackdaw (streamy a kolony)
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-projektu-apache-kafka-jazyku-clojure-a-knihovne-jackdaw-streamy-a-kolony/ - Vývoj služeb postavených na systému Apache Kafka v jazyku Go
https://www.root.cz/clanky/vyvoj-sluzeb-postavenych-na-systemu-apache-kafka-v-jazyku-go/ - Práce s Kafkou z příkazové řádky: nástroje Kafkacat a Kcli
https://www.root.cz/clanky/prace-s-kafkou-z-prikazove-radky-nastroje-kafkacat-a-kcli/ - Apache ActiveMQ – další systém implementující message brokera
https://www.root.cz/clanky/apache-activemq-dalsi-system-implementujici-message-brokera/#k12 - Sledování činnosti systému Apache Kafka přes JMX i metriky Promethea
https://www.root.cz/clanky/sledovani-cinnosti-systemu-apache-kafka-pres-jmx-i-metriky-promethea/
19. Odkazy na Internetu
- The Java™ Tutorials – Introducing MBeans
https://docs.oracle.com/javase/tutorial/jmx/mbeans/index.html - Standard MBeans
https://docs.oracle.com/javase/tutorial/jmx/mbeans/standard.html - JMX Exporter
https://github.com/prometheus/jmx_exporter - Monitor Apache Kafka with Prometheus and Grafana
https://computingforgeeks.com/monitor-apache-kafka-with-prometheus-and-grafana/ - Kafka Monitoring Using Prometheus
https://www.metricfire.com/blog/kafka-monitoring-using-prometheus/ - Collecting Kafka Performance Metrics with OpenTelemetry
https://www.splunk.com/en_us/blog/devops/monitoring-kafka-performance-metrics-with-splunk-infrastructure-monitoring.html - Monitoring Kafka performance metrics
https://www.datadoghq.com/blog/monitoring-kafka-performance-metrics/ - Kcli: is a kafka read only command line browser.
https://github.com/cswank/kcli - Kcli: a kafka command line browser
https://go.libhunt.com/kcli-alternatives - Awesome Go
https://github.com/avelino/awesome-go - Real-Time Payments with Clojure and Apache Kafka (podcast)
https://www.evidentsystems.com/news/confluent-podcast-about-apache-kafka/ - Microservices: The Rise Of Kafka
https://movio.co/blog/microservices-rise-kafka/ - Building a Microservices Ecosystem with Kafka Streams and KSQL
https://www.confluent.io/blog/building-a-microservices-ecosystem-with-kafka-streams-and-ksql/ - An introduction to Apache Kafka and microservices communication
https://medium.com/@ulymarins/an-introduction-to-apache-kafka-and-microservices-communication-bf0a0966d63 - kappa-architecture.com
http://milinda.pathirage.org/kappa-architecture.com/ - Questioning the Lambda Architecture
https://www.oreilly.com/ideas/questioning-the-lambda-architecture - Lambda architecture
https://en.wikipedia.org/wiki/Lambda_architecture - Kafka – ecosystem (Wiki)
https://cwiki.apache.org/confluence/display/KAFKA/Ecosystem - The Kafka Ecosystem – Kafka Core, Kafka Streams, Kafka Connect, Kafka REST Proxy, and the Schema Registry
http://cloudurable.com/blog/kafka-ecosystem/index.html - A Kafka Operator for Kubernetes
https://github.com/krallistic/kafka-operator - Kafka Streams
https://cwiki.apache.org/confluence/display/KAFKA/Kafka+Streams - Kafka Streams
http://kafka.apache.org/documentation/streams/ - Kafka Streams (FAQ)
https://cwiki.apache.org/confluence/display/KAFKA/FAQ#FAQ-Streams - Event stream processing
https://en.wikipedia.org/wiki/Event_stream_processing - Part 1: Apache Kafka for beginners – What is Apache Kafka?
https://www.cloudkarafka.com/blog/2016–11–30-part1-kafka-for-beginners-what-is-apache-kafka.html - What are some alternatives to Apache Kafka?
https://www.quora.com/What-are-some-alternatives-to-Apache-Kafka - What is the best alternative to Kafka?
https://www.slant.co/options/961/alternatives/~kafka-alternatives - A super quick comparison between Kafka and Message Queues
https://hackernoon.com/a-super-quick-comparison-between-kafka-and-message-queues-e69742d855a8?gi=e965191e72d0 - Kafka Queuing: Kafka as a Messaging System
https://dzone.com/articles/kafka-queuing-kafka-as-a-messaging-system - Apache Kafka Logs: A Comprehensive Guide
https://hevodata.com/learn/apache-kafka-logs-a-comprehensive-guide/ - Microservices – Not a free lunch!
http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html - Microservices, Monoliths, and NoOps
http://blog.arungupta.me/microservices-monoliths-noops/ - Microservice Design Patterns
http://blog.arungupta.me/microservice-design-patterns/ - REST vs Messaging for Microservices – Which One is Best?
https://solace.com/blog/experience-awesomeness-event-driven-microservices/ - Kappa Architecture Our Experience
https://events.static.linuxfound.org/sites/events/files/slides/ASPgems%20-%20Kappa%20Architecture.pdf - Apache Kafka Streams and Tables, the stream-table duality
https://towardsdatascience.com/apache-kafka-streams-and-tables-the-stream-table-duality-ee904251a7e?gi=f22a29cd1854 - Alertmanager
https://prometheus.io/docs/alerting/alertmanager/ - Grafana support for Prometheus
https://prometheus.io/docs/visualization/grafana/ - Prometheus: from metrics to insight
https://prometheus.io/ - Java Management Extensions (JMX)
https://en.wikipedia.org/wiki/Java_Management_Extensions - JConsole
https://en.wikipedia.org/wiki/JConsole - Using JConsole
https://docs.oracle.com/javase/8/docs/technotes/guides/management/jconsole.html - Overview of Java SE Monitoring and Management
https://docs.oracle.com/en/java/javase/15/management/overview-java-se-monitoring-and-management.html - Using jconsole (JMX) with SSL encryption
https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/configuration/secureJconsoleSSL.html - Step by step instructions for securing JMX authentication for nodetool utility, OpsCenter and JConsole
https://support.datastax.com/hc/en-us/articles/204226179-Step-by-step-instructions-for-securing-JMX-authentication-for-nodetool-utility-OpsCenter-and-JConsole - Enabling remote JMX with password authentication only
https://docs.oracle.com/javadb/10.10.1.2/adminguide/radminjmxenablepwd.html - Enabling remote JMX with password authentication and SSL
https://docs.oracle.com/javadb/10.10.1.2/adminguide/radminjmxenablepwdssl.html