Dimensionierung und Konfiguration des jadice web toolkit bei Inbetriebnahme

Gültig ab jadice web toolkit 5.10.6.1

Zur Inbetriebnahme einer Installation des jadice web toolkit sind verschiedene Einstellungen vorzunehmen.

Die meisten Werte sind bereits sinnvoll voreingestellt - jedoch mindestens die grundsätzliche Dimensionierung der Server sowie die Konfiguration der Caches müssen anhand der erwarteten Last passend eingestellt werden - gerne auch in Rücksprache mit levigo.

In der nachfolgenden Tabelle sind die verschiedenen Parameter zusammengestellt.

Stellgrößen für Dimensionierung und Performance im jadice web toolkit

Bereich

Details

Pods/VM
  • Erfahrungswerte für 500-1000 Concurrent User:
    • 2-4 Server-Instanzen (mit 2 Instanzen starten, bei Bedarf hochskalieren)
    • 4 logische Kerne/Prozessoren → bitte Abschnitt "Docker, Kubernetes & OpenShift" in Thread Pools and Concurrency beachten
    • (6-)8 GB RAM,
    • (4-)6 GB max. Heap
      • z.B. auch über -XX:MaxRAMPercentage=75.0 möglich
    • Region Size des Garbage-Collectors unbedingt erhöhen
      • z.B. -XX:G1HeapRegionSize=8m bei 8 GB RAM
      • Dadurch wird der RAM wesentlich besser ausgereizt
  • Java 17/11 (z.B. Adopt Open JDK 11) empfohlen (Java 8 wird zwar noch unterstützt, aber für Neuinstallationen nicht mehr empfohlen)
  • Geeignete Dimensionierung ist abhängig von Dokumenten:
    • PDF kostet gegenüber anderen Formaten mehr Rechenzeit → weniger User bzw. mehr Prozessoren pro Pod
    • große Dokumente (PDFs mit vielen Seiten, in großen Formaten (DIN A0), mit hoher Auflösung) erfordern größeren serverseitigen Heap Space 
Tile-Rendering

PNG statt WebP im Container: 

  • Im Container-Betrieb empfehlen wir (bis Version 5.10 und ab Version 6 Default-Einstellung) empfehlen wir den "Tile-Compression-Type" auf PNG zu stellen
  • In Version 5.10 des jadice web toolkit wurde eingeführt, dass Tiles standardmäßig als WebP-Images und nicht mehr als PNG an den Client geliefert werden. Dies bringt Vorteile im Bezug auf Geschwindigkeit und Dateigröße. Jedoch hat sich herausgestellt, dass dies im Containerumfeld weniger gut geeignet ist. Die Erzeugung von WebP-Bildern erfordert Off-Heap-Speicher, was im Monitoring nicht gut überwachbar und steuerbar ist. Die Erzeugung von PNG ermöglicht es jadice auch besser mit dem Cache umzugehen, zudem kann so die Memory-Lücke zwischen Container- und JVM-Speicherlimit deutlich kleiner ausfallen, ohne dass es zu OOM-Killed-Fehlern seitens des Containers kommt.



  • Weitere Informationen zur Wahl des Tile-Compression-Types sind hier zu finden.

    Um die Einstellung zu ändern:
    In der application.yml folgendes einstellen:
    webtoolkit:
      tile-compression-type: WEBP_LOSSY_HIGH_QUALITY
    alternativ programmatisch
    ConfigurationManager.getServerConfiguration().setTileCompressionType(ServerConfiguration.TileCompressionType.WEBP_LOSSY_HIGH_QUALITY);

Connection

Verbindungstyp setzen: Websocket, Server Sent Events oder Longpoll (siehe Connection Framework

  • falls möglich, ist Websocket empfohlen
  • programmatisch über die ServerConfiguration :
    z.B. new ServerConnectionBuilder().setWebSocketEnabled(false).setServerSentEventsEnabled(false).setLongpollEnabled(true).build();
  • alternativ in der application.yml bei Nutzung von Spring Boot
Deployment
  • Wenn das webtoolkit als Spring-Boot Anwendung gebaut wird, sollte das packaging unbedingt als JAR erfolgen und nicht als WAR (WAR sollte nur bei "Traditional Deployment", also wenn das WAR auf einem App-Server läuft, gewählt werden). Hintergrund ist, dass Spring wohl eine Unterscheidung beim Classpath-Scanning macht (dieser wird bei jedem PDF-Dokument durchgeführt, vermutlich da DefaultMetadataFactory intern auf Xerces setzt, welches dynamisch Klassen sucht)
Performance 
  • Tile-Preloading-Range: beschleunigte Anzeige benachbarter Seiten (empfohlen: 0-3)
    pageView.setPreloadingPageRange(new PreloadingPageRange(2));
  • Generierung der Tiles als PNG/WEBP-Images (Tradeoff zwischen Rechengeschwindigkeit und Bandbreite): → siehe Tile-images file-formats
    ConfigurationManager.getServerConfiguration().setTileCompressionType(...)
  • Thread Pools - sind auf Basis der Prozessorzahl sinnvoll voreingestellt (siehe Thread Pools and Concurrency)
    • ServerConfiguration.setTileRendererPoolCoreSize(int)
    • ServerConfiguration.setTileRendererPoolMaxSize()
    • ServerConfiguration.setTileRendererMaxParallelRenderingPerClient() 
    • ServerConfiguration.setGeneralPoolCoreSize(int)
    • ServerConfiguration.setGeneralPoolMaxSize(int)
Cache

Serverseitiges Tile-Caching: an/aus
Stellt man fest, dass der Server-Cache einen Engpass darstellt (also Dokumente zu häufig aus dem Cache expired werden und erneut geladen werden müssen), empfiehlt sich das Ausschalten des serverseitigen Tile-Cachings.
ConfigurationManager.getServerConfiguration().setTileCachingEnabled(false), Default: false

Clientseitiger Cache (Browser): immer aktiv 

Serverseitiger Cache - typische Richtwerte:


LRUCacheCompositeKeyCache
(=Standard im JWT)
empfohlene Werte
jadice.viewer.cache.maxNumberOfCacheEntries30003000
(in JWT 90000)
90000 → siehe Berechnung

Berechnung:

  • je Dokument wird ca. 2,5-4,5 MB im Cache belegt (JWT-Dokument, JWT-PageSegmente, Strukturinformationen aus der docpv) - haben wir empirisch ermittelt mit der Enterprise Demo und versch. Dokumenten
  • im Mittel werden 10 Dokumente pro Minute geladen (Annahme)
  • wir wollen erreichen, dass die Dokumente möglichst 30min im Cache bleiben
    --> 10Doc*30min*2,5 MB = 750 MB bis 10*30*4,5 MB = 1350 MB
  • im Cache werden ca. 150-300 Entries pro Dokument erzeugt (aus Stichproben ermittelt) -> 10Doc*30min*300 = 90.000 Entries
    • Hier würde ich tendenziell sogar höher gehen, so dass der Speicher der limitierende Faktor ist und nicht die Anzahl der Elemente
"jadice.viewer.cache.maximumExpiryObjectCountRatio"0.1f0.1f für LRUExpiryStrategy
10 für TileExpiryStrategy

0.1f bzw. 10 (Achtung: Die TileExpiryStrategy im jadice web toolkit erwartet eine Prozentangabe!)

"jadice.viewer.cache.minimumExpiryAge"-1

-1
(LRUExpiryStrategy +TileExpiryStrategy)

(in JWT 60000)

60000 // lifetime for cache entries. (in milliseconds)
jadice.viewer.cache.sizeHighwaterMark"-1-1Nicht empfohlen. Stattdessen lieber sizeHighwaterMarkPercent nutzen.
jadice.viewer.cache.sizeHighwaterMarkPercent"-1

-1

(in JWT 25)

25 // entspricht 2 GB bei 8 GB Heap
// configure an adaptive size management strategy with default parameters
cache.setSizeManagementStrategy(new AdaptiveSizeManagementStrategy(cache));
(Haken)(Minus)
jadice.viewer.cache.maxAgeExpiryEnabled=true(Minus)trueexpires all entries which are older than the defined age (age = latest access)
jadice.viewer.cache.maxAge=30(Minus)60
jadice.viewer.cache.maxAge.timeUnit=MINUTES(Minus)MINUTES
jadice.viewer.cache.type=CompositeKeyCache--Irrelevant im JWT, da hart codiert!

Empfehlung: Serverseitig ggf. auf LRUCache umstellen, falls man sieht, dass trotz geringer Belegung des Caches häufig aufgeräumt wird. Das macht man wie folgt:

Überschreiben des Caches im ConfigurationContextListener
// Im WebtoolkitServerContext wurde folgendes bereits statisch vorgenommen:
// CacheManager.setDefault(DefaultCacheProvider.getDefaultServerCache());

// Das überschreiben wir hier:
LRUCache cache = new LRUCache(120000);
cache.setSizeHighwaterMark(1000 * 1024 * 1024);
CacheManager.setDefault(cache);

// ConfigurationManager.getServerConfiguration().setTileCachingEnabled(false);
BufferManager

Es wird empfohlen, den BufferManager zu aktivieren.
→ siehe Aufräumen gecachter Dateien im Server-Dateisystem des jadice web toolkit

Einstellungen in den jadice.properties
bufferManager.enabled=true
# bufferManager.bufferSize=65536
# bufferManager.fileStoreStrategy=AUTO
# bufferManager.fileStoreMode=PLAIN
# bufferManager.bufferStoreFile=C:\\User\\Temp
# The default is 80 buffers, i.e. ~5MB of memory buffers.
# We increase this value since we want to be on the safe side for larger/multiple streams.
# (2000 buffers = 125 MB, which may still be too low)
bufferManager.memoryBuffers=2000

Durch FileCacheInputStreams temporär erzeugte Dateien löschen:

Einstellungen in den jadice.properties
jadice.viewer.delete-overaged-tmps=true
jadice.viewer.overaged-tmps-lifetime=0

Formatinterpretation der jadice document platform

Format-Einstellungen:

  • Abhängig vom Dokumentenbestand ggf. auf den Lesemodus LENIENT_ON_ERROR umstellen, um PDFs tolerant zu lesen, so dass Dokumente trotz gewisser syntaktischer Fehler angezeigt werden. → Zu Risiken und Nebenwirkungen siehe PDF-Struktur Lesestrategien

    Einstellung im DocumentDataProvider, direkt vor reader.read(inputStream)
    PDFStructureReaderSettings settings = reader.getSettings(PDFStructureReaderSettings.class);
    settings.setPDFStructureReadStrategy(PDFStructureReadStrategy.LENIENT_ON_ERROR);
  • Embedded MO:DCA-Annotationen anzeigen:
    jadice.viewer.afp-show-inline-annotation=true
UX
  • Qualität der Client-Icons: ClientConfigurationManager.getClientConfiguration().setIsIconFontUsed(true);

Weiterführende Informationen