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.
| |
---|
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:
| LRUCache | CompositeKeyCache (=Standard im JWT) | empfohlene Werte |
---|
jadice.viewer.cache.maxNumberOfCacheEntries | 3000 | 3000 (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.1f | 0.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 | -1 | Nicht 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)); | | |
| jadice.viewer.cache.maxAgeExpiryEnabled=true | | true | expires all entries which are older than the defined age (age = latest access) | jadice.viewer.cache.maxAge=30 | | 60 |
| jadice.viewer.cache.maxAge.timeUnit=MINUTES | | 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:
// 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
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:
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
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);
|
---|