Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

Üdvözöljük mindenkit a blogban, és itt van a Quarkus sorozat negyedik bejegyzése!

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

Előző bejegyzés az volt, hogyan kapcsolja össze a Quarkus a MicroProfile-t és a Springet. Emlékezzünk arra, hogy Quarkus úgy pozicionálja magát, mint az „ultrasebességű szubatom Java”, a „Kubernetes-orientált Java stack, amely a GraalVM és az OpenJDK HotSpot köré épül, és a legjobb könyvtárakból és szabványokból áll össze”. Ma azt fogjuk megmutatni, hogyan lehet modernizálni a már meglévő Java alkalmazásokat a Quarkus lehetőségeit kihasználva, a helloworld alkalmazás példáján a Red Hat JBoss Enterprise Application Platform (JBoss EAP) Quickstart-ból, amely a Quarkus által támogatott technológiákat, mint például a CDI és a Servlet 3 használja.

Fontos megjegyezni, hogy a Quarkus és a JBoss EAP is arra törekszik, hogy a lehető legnagyobb mértékben szabványokon alapuló eszközöket használjon. Nincs alkalmazásod a JBoss EAP-n? Nem probléma, könnyen átvihető a jelenlegi alkalmazásszerverről JBoss EAP-re a Red Hat Application Migration Toolkitsegítségével. Ezt követően a modernizált kód végső és működő verziója elérhető lesz a github.com/mrizzi/jboss-eap-quickstarts/tree/quarkusrepozitoriumában, a helloworld.

bejegyzés írása közben a Quarkus útmutatóit használtuk, főként a Creating Your First Application és a Native Executable.

készítése.

Kód beszerzése Első lépésként hozzunk létre egy helyi klónt a repozitóriumból::

$ git clone https://github.com/jboss-developer/jboss-eap-quickstarts.git
Cloning into 'jboss-eap-quickstarts'...
remote: Enumerating objects: 148133, done.
remote: Total 148133 (delta 0), reused 0 (delta 0), pack-reused 148133
Receiving objects: 100% (148133/148133), 59.90 MiB | 7.62 MiB/s, done.
Resolving deltas: 100% (66476/66476), done.
$ cd jboss-eap-quickstarts/helloworld/

Nézzük meg, hogyan működik az alap helloworld.

Valójában az alkalmazás lényege a nevéből egyértelműen kiderül, de szigorúan tudományosan fogjuk modernizálni a kódját. Tehát először is nézzük meg ezt az alkalmazást az eredeti formájában.

Helloworld telepítése

1. Nyisd meg a terminált, és lépj a JBoss EAP mappájának gyökérébe (letöltheted itt), azaz az EAP_HOME mappába.

2. Indítsd el a JBoss EAP szervert az alapértelmezett profilal:

$ EAP_HOME/bin/standalone.sh

Megjegyzés: Windows esetén az EAP_HOMEbinstandalone.bat szkriptet használd az indításhoz.

Néhány másodpercen belül a naplóban a következőnek kell megjelennie:

[org.jboss.as] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.2.0.GA (WildFly Core 6.0.11.Final-redhat-00001) elindult 3315ms alatt - 306/527 szolgáltatás indult el (321 szolgáltatás késleltetett, passzív vagy igény szerint).

3. Nyisd meg a böngészőt a 127.0.0.1:8080 címen, és ezt látod:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

1. ábra. JBoss EAP kezdőlapja.

4. Kövesd az útmutatót a Build and Deploy the Quickstart: telepítsük a helloworld-ot, majd a projekt gyökérmappájából futtassuk a következő parancsot:

$ mvn clean install wildfly:deploy

A parancs sikeres végrehajtása után a naplóban körülbelül a következőket fogjuk látni:

[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD SUCCESS 
[INFO] ------------------------------------------------------------------------ 
[INFO] Total time: 8.224 s

Így az első helloworld alkalmazás telepítése a JBoss EAP alatt kicsit több mint 8 másodpercet vett igénybe.

Teszteljük a helloworld-ot

Szigorúan a kézikönyv szerint eljárva Hozzáférés az alkalmazáshoz, nyissuk meg a böngészőben 127.0.0.1:8080/helloworld, és ezt látjuk:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

Ábra 2. Az alap Hello World a JBoss EAP-ból.

Változtatásokat végzünk

Megváltoztatjuk a bemeneti paramétert createHelloMessage(String name) a World helyett Marco-ra:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Ismét végrehajtjuk a következő parancsot:

$ mvn clean install wildfly:deploy

Ezután frissítjük az oldalt a böngészőben, és látjuk, hogy a szöveg megváltozott:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

Ábra 3. Hello Marco a JBoss EAP-ban.

Visszavonjuk a helloworld telepítését és leállítjuk a JBoss EAP-t

Ez nem kötelező, de ha szeretné visszavonni a telepítést, azt a következő parancs végrehajtásával teheti meg:

$ mvn clean install wildfly:undeploy

A JBoss EAP példány leállításához egyszerűen nyomja meg a Ctrl+C billentyűt a terminál ablakban.

Modernizáljuk a helloworld-ot

Most a helloworld alkalmazás modernizálásával foglalkozunk.

Új ág létrehozása

Új munkához szükséges ágat hozunk létre a quickstart projekt futása után:

$ git checkout -b quarkus 7.2.0.GA

Megváltoztatjuk a pom.xml fájlt

Az alkalmazást a pom.xml fájl megváltoztatásával kezdjük. Ahhoz, hogy a Quarkus XML blokkokat tudjon beilleszteni, futtassuk a következő parancsot a helloworld mappában:

$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create

A cikk írása során a 0.23.2-es verziót használták. A Quarkus gyakran kiad új verziókat, a legfrissebb verziót az alábbi oldalon lehet megtekinteni: github.com/quarkusio/quarkus/releases/latest.

A fenti parancs a pom.xml-be az alábbi elemeket illeszti be:

  • A <quarkus.version> tulajdonság, amely a használandó Quarkus verziót határozza meg.
  • A <dependencyManagement> blokk a Quarkus BOM (anyagjegyzék) importálásához, hogy ne kelljen verziót adni minden Quarkus függőséghez.
  • A quarkus-maven-plugin, amely felelős az alkalmazás csomagolásáért és biztosítja a fejlesztési módot.
  • A natív profil az alkalmazás végrehajtható fájljainak létrehozásához.

Ezenkívül a pom.xml-ben manuálisan elvégezzük a következő módosításokat:

  1. Kivesszük a <groupId> címkét a <parent> blokkból és fölé helyezzük a <artifactId> címkét. Mivel a következő lépésben eltávolítjuk a <parent> blokkot, meg kell őriznünk a <groupId>-t.
  2. Eltávolítjuk a <parent> blokkot, mivel a Quarkus használata során ennek az alkalmazásnak már nincs szüksége a JBoss szülő pom fájljára.
  3. Hozzáadjuk a <version> taget, és elhelyezzük a <artifactId> tag alatt. A verziószámot bármilyen kívánt értékre megadhatjuk.
  4. Eltávolítjuk a <packaging> taget, mivel ez az alkalmazás már nem WAR, hanem egy szokványos JAR.
  5. A következő függőségeket módosítjuk:
    1. Megváltoztatjuk az javax.enterprise:cdi-api függőséget io.quarkus:quarkus-arc-ra, eltávolítva a <scope>provided</scope> elemet, mivel (a dokumentációk szerint) ez a Quarkus-kibővítés biztosítja a CDI függőségek injektálását.
    2. Megváltoztatjuk az org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec függőséget io.quarkus:quarkus-undertow-ra, eltávolítva a <scope>provided</scope> elemet, mivel (a dokumentációk szerint) ez a Quarkus-kibővítés támogatja a servlet-eket.
    3. Eltávolítjuk az org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec függőséget, mivel ez az újrafogalmazott függőségekkel együtt jár.

A pom.xml fájl verziója az összes módosítással itt található: github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Figyeljen arra, hogy a fenti mvn io.quarkus:quarkus-maven-plugin:0.23.2:create parancs nemcsak a pom.xml fájlt módosítja, hanem számos komponenst is hozzáad a projekthez, nevezetesen a következő fájlokat és mappákat:

  • mvnw és mvnw.cmd fájlok és a .mvn mappa: a Maven Wrapper lehetővé teszi a megadott Maven verziójú projektek futtatását anélkül, hogy telepítenie kellene a verziót.
  • docker mappa (a src/main/ könyvtárban): itt találhatók a Dockerfile példafájlok native és jvm üzemmódokhoz (a .dockerignore fájl mellett).
  • resources mappa (a src/main/ könyvtárban): itt található egy üres application.properties fájl, valamint a Quarkus index.html induló oldalának mintája (további információ a Modernizált helloworld futtatása című részben található).

Indítjuk a helloworld-ot
Az alkalmazás teszteléséhez a quarkus:dev parancsot használjuk, amely elindítja a Quarkust fejlesztési módban (további részletekért lásd a következő szakaszt a Fejlesztési mód).

Megjegyzés: ez a lépés várhatóan hibához vezet, mivel még nem végeztük el az összes szükséges módosítást.

Most kiadunk egy parancsot, hogy megnézzük, hogyan működik:

$ ./mvnw compile quarkus:dev
[INFO] Projekteket kutatása...
[INFO]
[INFO] ----------------< org.jboss.eap.quickstarts:helloworld >----------------
[INFO] Gyorsstart építése: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld ---
[INFO] 'UTF-8' kódolás használata a szűrt erőforrások másolásához.
[INFO] 2 erőforrás másolása
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld ---
[INFO] Nincs mit fordítani - az összes osztály naprakész
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld ---
Hallgatózás transport dt_socket címen: 5005
INFO  [io.qua.dep.QuarkusAugmentor] Quarkus augmentáció kezdete
INFO  [org.jbo.threads] JBoss Threads verzió 3.0.0.Final
ERROR [io.qua.dev.DevModeMain] A quarkus indítása sikertelen: java.lang.RuntimeException: io.quarkus.builder.BuildException: Építési hiba: Az építés hibákat észlelt
	[hiba]: Az io.quarkus.arc.deployment.ArcProcessor#validate lépés kivételt dobott: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Nem kielégítő függőség az org.jboss.as.quickstarts.helloworld.HelloService típushoz és a [@Default] kvalifikátorokhoz
	- java tag: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
	- osztály bean deklarálva [típusok=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], kvalifikátorok=[@Default, @Any], cél=org.jboss.as.quickstarts.helloworld.HelloWorldServlet]
	at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:841)
	at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:214)
	at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:106)
	at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:249)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:780)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:415)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
	at java.lang.Thread.run(Thread.java:748)
	at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Oka: javax.enterprise.inject.UnsatisfiedResolutionException: Nem kielégítő függőség az org.jboss.as.quickstarts.helloworld.HelloService típushoz és a [@Default] kvalifikátorokhoz
	- java tag: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
	- osztály bean deklarálva [típusok=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], kvalifikátorok=[@Default, @Any], cél=org.jboss.as.quickstarts.helloworld.HelloWorldServlet]
	at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:428)
	at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:371)
	at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:206)
	... 14 több

Hát, nem működik... Miért van ez?

A UnsatisfiedResolutionException exception indicates the HelloService class, which is a member of the HelloWorldServlet class (java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). The issue is that HelloWorldServlet needs an injected instance of HelloService, but it cannot be found (even though both classes are in the same package).

It's time to go back to dokumentáció and read about how it works in Quarkus Inject, and therefore, also Contexts and Dependency Injection (CDI). So, let's open the Contexts and Dependency Injection guide and in the section Bean Discovery we read: "A bean class that does not have a defining bean annotation is not searched for."

Looking at the HelloService class, it indeed lacks such an annotation. Therefore, we need to add it so Quarkus can search for and find the bean. Since this is a stateless object, we can simply add the @ApplicationScoped annotation as follows:

@ApplicationScoped
public class HelloService {

Megjegyzés: Here, the development environment may prompt you to add the required package (see the line below), and this must be done manually, like this:

import javax.enterprise.context.ApplicationScoped;

If in doubt about which scope to use when none is specified for the original bean, study the documentation JSR 365: Contexts and Dependency Injection for Java 2.0—Default scope.

Now let's try to run the application again with the command ./mvnw compile quarkus:dev:

$ ./mvnw compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------
[INFO] Building Quickstart: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld ---
Listening for transport dt_socket at address: 5005
INFO  [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
INFO  [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 576ms
INFO  [io.quarkus] (main) Quarkus 0.23.2 started in 1.083s. Listening on: http://0.0.0.0:8080
INFO  [io.quarkus] (main) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (main) Installed features: [cdi]

Now everything goes without errors.

We launch the upgraded helloworld
As written in the log, we open in the browser 0.0.0.0:8080 (the default Quarkus start page) and see the following:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

Fig. 4. Start page of Quarkus dev.

In the WebServlet annotation of this application, the following context definition is set:

@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {

Ezért a böngészőben a következő címre lépünk: 0.0.0.0:8080/HelloWorld, és ezt látjuk:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

5. ábra: A Quarkus fejlesztői oldal Hello World alkalmazás számára.

Na, most már működik.

Most módosítjuk a kódot. Vegyük észre, hogy a . /mvnw compile quarkus:dev parancs még mindig működik, és nem szándékozunk leállítani. Most próbáljunk meg ugyanolyan – teljesen triviális – módosításokat alkalmazni a kódra, és nézzük meg, hogyan könnyíti meg a Quarkus a fejlesztők életét:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Mentjük a fájlt, majd frissítjük a weboldalt, hogy lássuk a Hello Marco feliratot, ahogy az az alábbi képernyőképen látható:

Quarkus: alkalmazások korszerűsítése a JBoss EAP Quickstart helloworld példáján

6. ábra: A Hello Marco oldal a Quarkus fejlesztői módban.

Most ellenőrizzük a terminál kimenetét:

INFO  [io.qua.dev] (vert.x-worker-thread-3) Változott forrásfájlok észlelve, újrafordítás [ /home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/src/main/java/org/jboss/as/quickstarts/helloworld/HelloWorldServlet.java]
INFO  [io.quarkus] (vert.x-worker-thread-3) A Quarkus 0,003 s alatt leállt
INFO  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) A quarkus bővítés elindítása
INFO  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) A quarkus bővítés 232 ms alatt befejeződött
INFO  [io.quarkus] (vert.x-worker-thread-3) A Quarkus 0.23.2 0,257 s alatt elindult. Figyel a következő címen: http://0.0.0.0:8080
INFO  [io.quarkus] (vert.x-worker-thread-3) A dev profil aktiválva. Élő kódolás aktiválva.
INFO  [io.quarkus] (vert.x-worker-thread-3) Telepített funkciók: [cdi]
INFO  [io.qua.dev] (vert.x-worker-thread-3) A forró csere teljes ideje: 0,371 s

Az oldal frissítése észlelte a forráskód változásait, és a Quarkus automatikusan végrehajtotta a 'stop-start' eljárást. Mindez mindössze 0,371 másodperc alatt megtörtént (itt van az a klasszikus „szupergyors, szubatomikus Java”).

A helloworld csomagolása JAR csomagba
Most, hogy a kód helyesen működik, csomagoljuk a következő paranccsal:

$ ./mvnw clean package

Ez a parancs kettő JAR fájlt hoz létre a /target mappában: a helloworld-.jar fájl, amely a Maven parancs által összeszerelt standard artefakt, valamint a hello—runner.jar fájl, amely egy végrehajtható JAR-t képvisel.

Ne feledje, hogy ez nem egy uber-jar, mivel minden függőség egyszerűen átmásolva lett a /target/lib mappába (és nem csomagolták a JAR fájlba). Ezért, ha ezt a JAR-t egy másik mappából vagy másik hoszton kívánja futtatni, mind a JAR fájlt, mind a /lib mappát át kell másolni, figyelembe véve, hogy a MANIFEST.MF fájlban található Class-Path elem egyértelműen felsorolja a lib mappában található JAR fájlokat.
Ha Ön uber-jar alkalmazásokat szeretne létrehozni, kérjük, nézze meg a kézikönyvet Uber-Jar létrehozása.

A helloworld elindítása, csomagolva JAR formátumban

Most elindíthatjuk a JAR-t a következő standard java parancs segítségével:

$ java -jar ./target/helloworld--runner.jar
INFO  [io.quarkus] (main) Quarkus 0.23.2 elindult 0.673s alatt. Figyel a következő címen: http://0.0.0.0:8080
INFO  [io.quarkus] (main) A prod profil aktiválva.
INFO  [io.quarkus] (main) Telepített funkciók: [cdi]

Miután mindez megtörtént, lépjen be a böngészőbe a következő címen: 0.0.0.0:8080 és ellenőrizze, hogy minden megfelelően működik.

A helloworld összegyűjtése natív végrehajtható fájllá

Tehát a helloworld alkalmazásunk standalone Java alkalmazásként működik, kihasználva a Quarkus függőségeit. De van lehetőség tovább lépni, és natív végrehajtható fájlra konvertálni.

GraalVM telepítése
Elsősorban a szükséges eszközöket kell telepíteni:

1. Töltse le a GraalVM 19.2.0.1 verziót a következő címen: github.com/oracle/graal/releases/tag/vm-19.2.0.1.

2. Csomagolja ki a letöltött archívumot:

$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz

3. Menjen az untar mappába.

4. Futassa az alábbi parancsot, hogy letöltse és hozzáadja a natív képet:

$ ./bin/gu install native-image

5. Állítsa be a 2. lépésben létrehozott mappa elérési útját a GRAALVM_HOME környezeti változóban:

$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)

További információk és telepítési utasítások más operációs rendszerekhez a következő útmutatóban találhatók: Building a Native Executable—Prerequisites.

A helloworld natív végrehajtható fájlba való összegyűjtése
Olvassa el az útmutatót Building a Native Executable—Producing a native executable: „Most létrehozunk egy natív végrehajtható fájlt az alkalmazásunkhoz, amely csökkenti a betöltési időt és a lemezméretet. A végrehajtható fájl tartalmazni fog mindent, ami szükséges az alkalmazás futtatásához, beleértve a JVM keretrendszert (pontosabban annak csökkentett verzióját, amely csak az alkalmazás futtatásához szükséges elemeket tartalmazza) és magát az alkalmazást.”

A natív végrehajtható fájl létrehozásához aktiválni kell a Maven natív profilt:

$ ./mvnw package -Pnative

Az összesítés 1 perc 10 másodpercet vett igénybe, és a helloworld-runner végrehajtható fájl a /target mappában jött létre.

Futtatjuk a helloworld natív végrehajtható fájlt

Az előző lépésben a /target/helloworld-runner végrehajtható fájlt kaptuk. Most indítsuk el:

$ ./target/helloworld--runner
INFO  [io.quarkus] (main) Quarkus 0.23.2 elindult 0.006s alatt. Figyel a következő címen: http://0.0.0.0:8080
INFO  [io.quarkus] (main) A prod profil aktiválva.
INFO  [io.quarkus] (main) Telepített funkciók: [cdi]

Ismét nyissa meg a böngészőt 0.0.0.0:8080 és ellenőrizze, hogy minden megfelelően működik.

Folytatás következik!

Úgy véljük, hogy a bejegyzésben bemutatott (még ha egy egyszerű példán keresztül is) Java-alkalmazások Quarkus képességeivel történő modernizálásának módszerét aktívan érdemes alkalmazni a való életben. E közben valószínűleg számos problémával is találkozni fog, amelyek megoldásait részben a következő bejegyzésben tárgyaljuk, ahol arról lesz szó, hogyan mérhetjük a memóriafogyasztást a teljesítményjavítás, a modernizálási folyamat fontos részének értékelésére.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster