ich habe folgendes Problem:
Ein Service ruft meinen REST Service, dieser sammelt sseeeehr viele Daten aus der Datenbank. Das dauert weit über 5 Minuten und gibt die Daten als json zurück.
Das Problem dabei ist, ich habe es mit Tenanten aufgebaut, wenn sich nun ein Tenant zb in die Weboberfläche einlogged, oder dieser Tenant einen anderen Service anfragt, bekommt der solange keine Antwort, bis der obige fertig ist mit seiner Sucherei.
Habe vom REST Service 2 Instanzen laufen, bei der zweiten Instanz, sehe ich dass sie SELECTS auf die Datenbank gibt, aber scheinbar keine Antwort bekommt.
Ich vermute das hat was mit Transactions zu tun? Die "große Suchtransaktion" sperrt die neu ankommenden Requests aus, solange noch gesucht wird, kann das sein? Wir kann ich Meinen Service dazubringen, dass es nicht blocked? Habe einen Connection Pool mit 3 Connections pro Tenant.
Wenn der lang andauernde Service sucht und ich geht mit meinem SQL CLient auf die DB, ist alles iO also kann es schon mal keine Sperre von Mysql sein, sondern eher etwas von Spring?!
Ich würde zum Beispiel Accepted zurückgeben und eine neue url auf der das Ergebnis angefragt werden kann, wenn es fertig ist. Auf diese Url kann dann gepollt werden oder mit Callbacks gearbeitet werden.
Sonst würde ich mal untersuchen warum das Query 5 min+ dreht, das klingt nicht OK
Oh coole Idee! Danke! Hab es jetzt erstmal anders gelöst, dass ich immer 10 Einträge abfrage. Die Objeckte sind relartiv komlex und erstrecken sich über zig tabellen die angefragt werden müssen. Wo kann ich mehr zu deinem Vorschlag lesen? Wie wird das dann zwischengespeichert für die "Abholung"? Mit pollen meinst du, dass der anfragende Service dann immer wieder anfragt, bis er ein Ergebnis bekommt?
Danke das sieht gut aus. Mir fiel jetzt aber auf dass auch bei kurzen Requests, andere Requestst nicht bedient werden.
Folgendes fiel mir auf: Es kommt eine Anfrage rein, der tenant wird auf user x gesetzt und aus seiner DB werden Daten geholt. (Ich sehe in den Logs die entsprechenden Queries), nun logged sich der User ein, und ruft da zb Daten ab aus seiner DB. Dann wird der andere Request unterbrochen . Warum geht das nicht parallel? Das muss doch mit der Datenbank zu tun haben. Ist hier vielleicht was nicht ganz richtig konfiguriert?
Sind 3 Connections zu wenig?
Code:
HikariConfig config = new HikariConfig();
config.setJdbcUrl(tenantProperties.getProperty("datasource.url"));
config.setUsername(tenantProperties.getProperty("datasource.username"));
config.setPassword(tenantProperties.getProperty("datasource.password"));
config.setPoolName(tenantId);
config.setMaximumPoolSize(3);
HikariDataSource ds = new HikariDataSource(config);
Edit: wenn ich während eines Request die Datenbank manuell abfrage, geht das parallel. Also muss es ein Problem sein, dass Http Requests nicht parallel bedient werden
Meine Vermutung ins blaue ist, dass beim Poolwechsel offene Connections beendet werden.
Kenne mich aber mit HikariCP nicht aus, kann also auch komplett daneben sein
Also so ein Hikari-Pool ist durchaus sinnvoll! Eventuell kannst du noch überlegen, ob du diesen speziellen noch Asynchron machst. Wobei ich zugeben muss, dass ich hiermit beim nachträglichen einbauen in die Spring Boot Applikation auch so meine Probleme hatte (Async Timeouts u.s.w.)...
Würde auch erst mal noch schauen, wie man die Query optimieren kann - ich hatte z.B. auch schon Performance-Probleme mit ORM (Hibernate -könnt mich selbst prügeln, dass ich mich davon habe überzeugen lassen!) die ich am Ende mit Native Queries umgangen habe.
Auch solltest du dann wenige einzelne Requests absetzen - JDBC ist vergleichbar lahm.
Ich habe momentan mit einer Spring Boot-App auch so meine Probleme und werde, wenn ich sie nicht in den Griff bekomme, den Service wohl gegen eine (hoffentlich) schlankere Lösung mittels Ktor (Kotlin), HikariCP & Exposed zu Testzwecken austauschen...
Hey, ja hab mit Hibernate auch so meine Probleme, besonders wenn man die Objekt-Relationen nicht richtig miteinander hat, dann macht es statt einem einfachen UPDATE , ein UPDATE auf null und dann DELETE das null und dann ein neues INSERT...Muss man erstmal dahinter steigen Hast du Deinen Pool in einer Tenanten Umgebung?
Wenn du mir "Tenante Umgebung" definierst... Also was du darunter verstehst...
Wir haben eine relativ grosse Anwendung, die für X Kunden, kundenspezifische Daten aus der DB holt und per Rest zur Verfügung stellt, damit ein UI damit etwas anfangen kann und dass sich um die ganze Rechtegeschichte kümmert... Genügt dir das?
In der besagten Spring Boot-Anwendung gibt es allerdings kein HikariCP - die DB und die Connections dahin sind (vermutlich) nicht das Problem. Auch Rechteverwaltung kennt die Anwendung nicht, denn sie ist nur eine Rest-Middleware für diverse kleinere Anwendungen, die DB-Zugriff brauchen, die aber nicht relevant in Bezug auf Rechte uns so sind.