IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Serveur d'application / Session / Thread


Sujet :

avec Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut Serveur d'application / Session / Thread
    Bonjour,

    Je suis nouveau dans le développement web. Donc je m'excuse si c'est une question simple, et déjà posée à de multiples reprises.

    Est ce que Tomcat crée un thread par session user ?

    Par exemple, je crée une application web et la déploye sur tomcat.
    Maintenant, lorsque plusieurs utilisateurs se connectent à l'application web, est ce que tomcat crée un nouveau thread par utilisateur ?
    Si c'est le cas, je peux donc espérer créer de nouveaux threads dans l'appli qui seront donc des enfants du thread créé par tomcat ?
    Est ce que les données au niveau de la session restent synchronisées entre les threads ?

    Merci.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    c'est un thread par requête HTTP (c'est donc indépendant de la session). Il n'y a pas de lock sur la session, si plusieurs requetes http arrivent simultanément pour la même session, et qu'elle modifient toutes le même objet de la session, le résultat sera aléatoire.

    Vous pouvez créer vos propres thread, mais ce n'est pas recommandé en J2EE (mais parfois on est bien obligé )

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    J'ai beaucoup de mal à comprendre le fonctionnement des serveurs d'appli.

    On a le serveur d'appli.
    On a une appli qui est déployée (et donc une fois lancée qui à son propre thread / serveur (?)).

    Ensuite, y a un thread (par requete HTTP) qui arrive au serveur. Comment se fait le lien entre la requete et l'appli alors (et par rapport aux données déjà instanciées) ? la requête serait un thread enfant de l'appli ?

    Et les filters interviennent où dans tout cela ?

    (petite parenthèse)
    J'ai beaucoup de mal à appréhender tout cela.
    Et je pose toutes ces questions, d'une part histoire de comprendre comment fonctionne une appli J2EE, mais c'est aussi en rapport avec le framework logback pour faire des logs / user. (Cf post dans logging).

    Je voudrais faire un SiftAppender, pour une création "dynamique" de FileAppender pour faire un log / user. La valeur du user étant renseignée dans un MDC.

    Mon problème est de comprendre comment les sessions user sont gérées, et si je me retrouve avec un thread / user et donc un MDC / user ou si cela reste un MDC commun. A priori cela reste un MDC commun au vu de votre réponse........

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    l'application déployée, a priori, n'a pas de thread propre. tous les threads appartiennent au conteneur. En très gros, en cas de requete http, le conteneur va faire ceci:

    Code x : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    analyser la requete http
    localiser la webapp associée
    récupérer dans la webapp l'instance de Servlet qui correspond à la demande
    construite les objet httpserlvetrequest et httpservletresponse
    faire servlet.service(request,response);
    fin de la requete, on libère le thread

    Pour ce qui est d'associer des données au thread courant, ça se fait. Pour cela il faut implémenter un servletrequestlistener ou un filter. Ceux-ci recoivent la main au début de la requete http, et à la fin. Il peuvent donc service à initialiser et nettoyer des données en mémoire, fonction par exemple de l'utilisateur courant.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    J'avoue que je suis paumé.

    Je débarque sans connaissance sur une appli en architecture MVC utilisant un peu de spring, et beaucoup de Zk (qui est à la base surtout un framework pour faire de l'ajax mais qui au final est utilisé de partout, même pour faire les interfaces web classiques).

    Bref du coup, je ne comprends pas grand chose à l'ordre d'execution des elements, ni à la gestion des threads.

    En gros, cette appli a un web.xml qui declare un applicationContext.xml initialisant (via spring) un controleur.
    Ce controleur sert au démarrage de l'appli pour récupérer un certains nombre d'infos d'environnement.

    Ensuite, j'ai un fichier de config XXX-servlet.xml qui lui définit des mappings entre des pages html et des controleurs.

    Au démarrage d'une session utilisateur, y a une jsp appelée qui renvoie sur une page html elle même gérée par un controleur.
    De là, on en détermine les infos d'une class "User" qui servira au logger pour la création d'un log spécifique à cet utilisateur.

    "En théorie", d'après vos explications, ainsi que la doc de Logback, par un filter il serait possible de mettre à jour le MDC avec la valeur utile de la class User (récupérée de la session), et en fin de requête libérer le MDC pour éviter tout conflit et ainsi ajuster le MDC en fonction du USER qui execute la requete.

    Or, après de multiples tests, cela ne fonctionne pas.....j'ai tenté ceci dans le filter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MDC.put("user", userid);
     
    try {
        filterChain.doFilter();
    } finally {
        MDC.remove("user");
    }
    Soit mon fichier de log n'est jamais crée....pourtant j'ai fait afficher dans la console la liste des valeurs du MDC après le put, et ma valeur y est bien insérée ; soit il est créé mais avec une valeur par défaut définit dans le fichier de config de logback comme si le remove se faisait "trop tôt".

    Bref, je ne pige pas l'enchainement....il semblerait que l'architecture MVC telle qu'elle est utilisée dans cette appli n'est pas "conforme" pour une utilisation du filter et du MDC.

    Par contre, si dans le code, je fais des puts, trace et remove enchainé, cela fonctionne parfaitement (et heureusement :p).

    Donc je pensais que mon souci était cette histoire de gestion multithread/monothread par rapport au MDC, et donc qu'il y avait des conflits entre les sessions user executées.

    Des idées sur le fait que le filter ne fonctionne point ? :p

    Merci.

  6. #6
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    vous avez mappé comment votre filter?

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    Je n'ai rien inventé....j'ai carrément copié l'exemple de la doc Logback.

    Un truc similaire à cela (et où j'ai juste récupérer un objet User de la session courante, et je balance le nom du User).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    package chapters.mdc;
     
    import java.io.IOException;
    import java.security.Principal;
     
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
     
    import org.slf4j.MDC;
     
    public class UserServletFilter implements Filter {
     
      private final String USER_KEY = "username";
     
      public void destroy() {
      }
     
      public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
     
        boolean successfulRegistration = false;
     
        HttpServletRequest req = (HttpServletRequest) request;    
     
        if (principal != null) {
          String username = principal.getName();
          successfulRegistration = registerUsername(username);
        } 
     
        try {
          chain.doFilter(request, response);
        } finally {
          if (successfulRegistration) {
            MDC.remove(USER_KEY);
          }
        }
      }
     
      public void init(FilterConfig arg0) throws ServletException {
      }
     
      private boolean registerUsername(String username) {
        if (username != null && username.trim().length() > 0) {
          MDC.put(USER_KEY, username);
          return true;
        }
        return false;
      }
    }

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    ça ne répond pas à la question, vous l'avez mappé comment votre filtre?

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    C'est à dire.... ?

    Il est déclaré dans le web.xml, c'est le seul existant d'ailleurs.
    Et j'ai vérifié qu'on passe bien dedans.

    Qu'appelez vous "mapper" pour un filtre ?

    Par contre l'appli est bizarre. Une base spring, puis framework Zk qui prend le relais sans véritable lien entre les 2...Utilisation des Zk pas forcément adapté en plus (utilisation de "use" au lieu de "apply").

  10. #10
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    je n'avais pas bien lu la partie ou vous confirmer passer correctement dans le filtre, désolé.

    Si vous passez bien dans le filtre et que vous avez bien définis les données dans le MDC et que votre api de logging déconne toujours, je regarderais plutot par là dans ce cas, car visiblement elle ignore le MDC.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    Non mais vraiment je ne comprends pas du tout comment cela fonctionne.

    Deux possibilités :
    - soit je ne pige vraiment rien au fonctionnement du filter et à son périmètre d'utilisation
    - soit le problème est ailleurs (de l'architecture un peu bizarre du projet)


    Mais d'après votre explication :
    Pour ce qui est d'associer des données au thread courant, ça se fait. Pour cela il faut implémenter un servletrequestlistener ou un filter. Ceux-ci recoivent la main au début de la requete http, et à la fin. Il peuvent donc service à initialiser et nettoyer des données en mémoire, fonction par exemple de l'utilisateur courant.
    Mon filter aurait du avoir la main au debut de la requete, mettre à jour le MDC, rendre la main pour faire ce qu'il y a à faire et récupérer la main à la fin pour nettoyer le MDC.

    Le logger fonctionne pourtant parfaitement quand je mets à jour le MDC juste avant de faire appel à une méthode de tracage.
    Et l'exemple du filter est fourni dans la doc....bref normalement tout devrait ok.

    Bref j'ai abandonné l'idée de l'utiliser "proprement" avec le filter, et j'ai fait une class perso ("pourrie") qui "surcharge" les appels de tracage (error, warn, info, debug, trace) dans laquelle je mets chaque fois à jour le MDC (put & remove).
    C'est moche, mais ca fonctionne....ca permet d'utiliser le logger malgré tout avec les optimisations d'écriture (concaténation de chaine pour des appels non loggés par la config du Level par ex) du framework, ainsi que le fichier de config XML permettant de rajouter autant d'appender que souhaité.
    C'est toujours mieux que l'existant (une class perso qui écrivait dans un fichier :p).

    Merci pour ton aide Tchize_

Discussions similaires

  1. [Serveur J2EE] Faire tourner un thread dans un serveur d'applications
    Par Pierre-Yves VAROUX dans le forum Java EE
    Réponses: 3
    Dernier message: 13/10/2005, 14h10
  2. Debug application multi thread
    Par Razowsky dans le forum MFC
    Réponses: 1
    Dernier message: 03/05/2005, 18h14
  3. Différence entre SGBD et Serveur d'application
    Par WOLO Laurent dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/06/2003, 08h47
  4. Serveur d'applications Java
    Par foxrol dans le forum Java EE
    Réponses: 3
    Dernier message: 17/05/2003, 00h49
  5. serveur d'application
    Par nass_03 dans le forum JBuilder
    Réponses: 3
    Dernier message: 20/01/2003, 16h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo