170 votes

Appel asynchrone jdbc est possible ?

Je me demande si il existe un moyen de faire appel asynchrone à une base de données?

Par exemple, imaginons que j'ai une grosse demande de prendre un temps très long processus, je veux envoyer la demande et recevoir une notification lorsque la demande va retourner une valeur (par le passage d'un Auditeur/rappel ou quelque chose). Je ne veux pas bloquer en attente pour la base de données de réponse.

Je ne considère pas que l'utilisation d'un pool de threads est une solution, car il n'a pas d'échelle, dans le cas de fortes demandes simultanées cela va lancer un très grand nombre de threads.

Nous sommes confrontés à ce genre de problème avec le serveur de réseau et nous avons trouvé des solutions à l'aide de select/poll/epoll appel système pour éviter d'avoir un thread par connexion. Je me demande juste comment faire pour avoir une fonctionnalité similaire avec demande de base de données?

Mise à jour:
Je suis conscient que l'utilisation d'un FixedThreadPool peut être un bon travail, mais je suis surpris que personne ne l'avons développé un système asynchrone (sans l'utilisation de fil supplémentaire).

Mise À Jour 2 (Décembre 2010):
Autant que je sache, il n'y a pas de solution pour faire de réel asynchrone jdbc appel, la meilleure solution de contournement consiste à encapsuler l'appel avec quelque chose comme un Acteur ou une Promesse.

170voto

johnlon Points 599

Je ne comprends pas comment l'autre de ces approches qui placent les appels JDBC en Acteurs, exécuteurs testamentaires ou quoi que ce soit d'autre peut vous aider ici - quelqu'un peut-il préciser.

Sûrement le problème de base est que le JDBC opérations de bloc sur socket IO. Quand il le fait il bloque le Fil de ses cours d'exécution sur la fin de l'histoire. Quelle que soit habillage de cadre que vous choisissez d'utiliser sa va finir avec un fil étant occupé/bloqué par requête simultanées.

Si le sous-jacent pilotes de base de données (MySql?) offre un moyen d'intercepter la création de la socket (voir SocketFactory) alors j'imagine qu'il serait possible de construire un async événement piloté par la base de données de la couche sur le dessus de l'api JDBC, mais nous aurions à encapsuler l'ensemble de JDBC derrière un événement piloté par la façade, et que la façade ne ressemblerait pas à JDBC (après il serait event driven). Le traitement de base de données arriverait asynchrone sur un thread différent de l'appelant, et vous auriez à travailler sur la façon de construire un gestionnaire de transactions qui ne repose pas sur le thread de l'affinité.

Quelque chose comme l'approche que j'ai mentionner permettrait même d'un seul thread d'arrière-plan pour traiter une charge de simultanées JDBC exec. Dans la pratique, vous auriez probablement exécuter un pool de threads à utiliser plusieurs cœurs.

(Bien sûr, je ne suis pas de commentaire sur la logique de la question d'origine seulement les réponses qui implique que la simultanéité dans un scénario avec blocage socket IO est possible sans que l'utilisateur d'un sélecteur de modèle plus simple de juste travailler sur votre typique JDBC de la simultanéité et de la mettre dans un pool de connexions de la bonne taille).


Ressemble à MySql n'a probablement quelque chose le long des lignes de je suggère --- http://code.google.com/p/async-mysql-connector/wiki/UsageExample

42voto

Vasil Remeniuk Points 12487

Il est impossible de faire un appel asynchrone à la base de données via JDBC, mais vous pouvez faire des appels asynchrones de JDBC avec Acteurs (p. ex., l'acteur fait des appels à la base de données via JDBC, et envoie des messages à des tiers, lorsque les appels sont plus), ou, si vous aimez la CPS, avec un pipeline à terme (promesses) (une bonne mise en œuvre est Scalaz Promesses)

Je ne considère pas que l'utilisation d'un pool de threads est une solution, car il n'a pas d'échelle, dans le cas de fortes demandes simultanées cela va lancer un très grand nombre de threads.

Scala acteurs par défaut sont basés sur les événements (pas de fil) - poursuite de la planification permet de créer des millions d'acteurs sur une JVM standard de l'installation.

Si vous ciblez Java, Akka Cadre est un Acteur de la mise en œuvre du modèle qui a une bonne API à la fois pour Java et Scala.


A côté de cela, la machine synchrone nature de JDBC est parfaitement logique pour moi. Le coût d'une session de base de données est beaucoup plus élevé que le coût de la Java thread bloqué (soit sur l'avant ou l'arrière-plan) et en attendant une réponse. Si vos requêtes exécutées depuis si longtemps que les capacités d'un exécuteur de service (ou l'emballage d'Acteur/fork-join/promesse de la simultanéité des cadres) ne sont pas assez pour vous (et que vous consommez trop de threads), vous devez tout d'abord penser à votre charge de base de données. Normalement, la réponse à partir d'une base de données est très rapide, et un exécuteur testamentaire service soutenu avec un pool de threads est une assez bonne solution. Si vous avez trop de requêtes de longue durée, vous devriez envisager à l'avance (pré)traitement - comme les soirs de recalcul des données ou quelque chose comme ça.

12voto

Tomas Narros Points 7280

Vous pourriez peut-être utiliser un JMS, messagerie asynchrone système qui adapte assez bien, à mon humble avis:

  • Envoyer un message à une File d'attente, où les abonnés pourront accepter le message, et de lancer le processus SQL. Vos principaux processus continuera de fonctionner et de l'acceptation ou de l'envoi de nouvelles demandes.

  • Lorsque le processus SQL se termine, vous pouvez exécuter le chemin inverse: envoyer un message à un ResponseQueue avec le résultat du processus, et un écouteur sur le côté client de l'accepter et d'exécuter le code de rappel.

9voto

Daryl Teo Points 3670

2013 et en ajoutant ma propre voix à cette conversation que je suis arrivé ici à plusieurs reprises.

Il y a 1 les exigences de base pour event-driven db accès: la base de données de fil de protocole doit être apatrides.

Traditionnelle wire protocol généralement ressembler à ceci:

  • ouverture / obtenir connexion
  • envoyer la commande (1)
  • en attente de traitement
  • de retour de réponse (2)
  • fermer / rendement de connexion

Un event-driven db accès doit être apatride, de sorte qu'aucune des hypothèses de chaque partie peut être faite. 1 et 2 est clé: vous ne pouvez pas supposer que le 2 est un résultat de 1. C'est aussi pourquoi traditionnelle jdbc est de bloquer et de plusieurs threads doivent être engendré comme un résultat.

Par conséquent, la seule façon de contourner cela est de savoir si le fil de protocole spécifiquement vous permet de spécifier la requête/réponse identifiants qui vous permettent de match 2 à 1. Actuellement en train de faire un peu de recherche sur ce sujet, et comme un exemple, avoir un regard sur MongoDB sur le fil de protocole [1], ce qui indique une iddemande dans le cadre de leur protocole. Si une base de données a ce, puis un événement piloté par le pilote peut être écrit pour elle [2].

Votre fil de protocole peut alors ressembler à ceci:

7voto

Pangea Points 36713

Il n'y a pas de soutien direct dans JDBC, mais vous avez plusieurs options comme MDB, Exécuteurs testamentaires à partir de Java 5.

"Je ne considère pas que l'utilisation d'un pool de threads est une solution, car il n'a pas d'échelle, dans le cas de fortes demandes simultanées cela va lancer un très grand nombre de fils."

Je suis curieux de savoir pourquoi un délimitée pool de threads ne va pas à l'échelle? C'est une piscine pas thread-par-requête pour frayer un thread pour chaque demande. J'ai été en utilisant cela pour un certain temps sur une lourde charge webapp et nous n'avons pas vu de problèmes jusqu'à présent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X