Mise en mémoire cache de pages complètes et de fragments

La méthode selon laquelle WebSphere Application Server met en cache des fichiers JSP dépend du mode d'écriture de ces fichiers. Si une page, soumise à une instruction donnée de HCL Commerce, produit toujours le même résultat, basé sur les paramètres d'URL et les attributs de requête, ce résultat de page peut être mis en cache avec l'entrée de cache utilisant l'élément de propriété consume-subfragments (CSF) ainsi que le servlet de contrôleur de HCL Commerce (com.ibm.commerce.struts.ECActionServlet.class dans la version 9.0.0.x ou com.ibm.commerce.struts.v2.ECActionServlet.class dans la version 9.0.1+ et si vous utilisez la configuration Strut 2 com.ibm.commerce.struts.v2.ECActionStrutsServlet.class) comme nom de servlet. Lorsque l'entrée de cache est définie de cette façon, le résultat de la page est mis en cache selon la méthode appelée mise en cache de full page. L'avantage d'utiliser l'élément consume-subfragments avec le servlet de contrôleur est le gain de performances, mais si la page contient des informations personnalisées, tel un mini panier, la mise en cache full page avec fragments est admise.

Si le résultat de la page comporte des sections dépendantes de l'utilisateur, ce résultat est mis en cache selon la méthode appelée mise en cache de fragment. Cela signifie que les pages JSP sont mises en cache sous forme d'entrées de cache distinctes et qu'elles sont reconstituées lorsqu'elles sont demandées. Pour la mise en cache de fragment (JSP), HCL Commerce doit exécuter l'instruction afin de déterminer quel JSP doit être exécuté pour que le mécanisme de mise en mémoire dynamique puisse déterminer si le fichier JSP peut être présenté à partir du cache ou non. L'avantage de cette méthode est la souplesse car différentes entrées de cache peuvent être reconstituées pour former une page, en fonction des informations relatives à l'utilisateur.

Dans certains cas, il est pratique d'exclure certains fragments de la mise en cache avec une page complète. Au lieu d'être mis en cache avec la full page, les fragments sont mis en cache séparément. Par exemple, s'il existe un message de bienvenue personnalisé ou une page de commande en cours, la propriété do-not-consume est utilisée. L'entrée parent est marquée par la propriété consume-subfragments et le fragment enfant qui contient la zone de personnalisation doit être marqué par cette propriété do-not-consume. Grâce à cette combinaison, le gain de performance obtenu par une mise en cache de page entière demeure intact pour la page à l'exclusion du fragment enfant qui est mis en cache séparément.

Mise en cache de pages complètes

Lorsque l'élément de propriété consume-subfragments (CSF) est utilisé, l'entrée de cache de la page parent (identifiée par CSF) inclut tout le contenu de tous les fragments de son entrée de cache, produisant une seule entrée de cache volumineuse sans inclusion ni réacheminement et contenant toute l'arborescence des entrées.

Lorsqu'un servlet est mis en cache, seul le contenu de ce servlet est stocké. Le cache comporte des marques de réservation pour tous les autres fragments dans lesquels il effectue des inclusions ou des réacheminements. L'élément consume-subfragments (CSF) indique au cache de ne pas arrêter la sauvegarde de contenu lorsqu'il comporte un servlet enfant. L'entrée parent (identifiée par CSF) inclut tout le contenu de tous les fragments dans son entrée de cache, produisant une seule entrée de cache volumineuse sans inclusion ni réacheminement et contenant toute l'arborescence des entrées. Cet élément peut diminuer considérablement le traitement par le serveur d'applications mais il est généralement utile uniquement lorsque la requête HTTP externe contient toutes les informations nécessaires pour déterminer l'ensemble de l'arborescence des fragments inclus.

Par exemple, si le fichier <cache-entry> est défini comme suit :


<cache-entry>
  <class>servlet</class>
 
<name>strutsaction</name>
  <property name="consume-subfragments">true</property>
  <property name="save-attributes">false</property>
  <property name="store-cookies">false</property>

  <!-- StoreCatalogDisplay?storeId=<storeId> -->
  <cache-id>
     <component id="" type="pathinfo">
        <required>true</required>
           <value>/StoreCatalogDisplay</value>
     </component>
     <component id="storeId" type="parameter">
        <required>true</required>
     </component>
  </cache-id>
</cache-entry>

strutsaction se trouve com.ibm.commerce.struts.v2.ECActionServlet.class dans HCL Commerce versions 9.0.0.x, ou com.ibm.commerce.struts.v2.ECActionServlet.class dans versions 9.0.1 ou ultérieures et si vous utilisez la configuration Strut 2 com.ibm.commerce.struts.v2.ECActionStrutsServlet.class. Notez que lorsque la propriété save-attributes est définie sur false, les attributs de requête ne sont pas sauvegardés avec l'entrée de cache. Lorsque la propriété store-cookies est définie sur false, les cookies de requête ne sont pas sauvegardés avec l'entrée de cache.

Dans l'exemple précédent, l'entrée de servlet de cache contient une inclusion périmée de StoreCatalogDisplay.jsp, qui est le fichier JSP transmis par l'instruction StoreCatalogDisplay.

Mise en cache de fragments

Un fragment ne peut être mis en cache que s'il est exécutable par lui-même. L'entrée de chaque fichier JSP inclus dynamiquement doit être <cache-entry> définie dans le fichier cachespec.xml afin que le fichier soit présenté par la mémoire cache dynamique lorsqu'elle reçoit une requête. Faute de quoi, chaque fichier JSP dynamiquement inclus sera réexécuté pour chaque requête. Par exemple, considérons que StoreCatalogDisplay.jsp inclut dynamiquement CachedHeaderDisplay.jsp, CachedFooterDisplay.jsp et CachedStoreCatalogDisplay.jsp et vous définissez uniquement <cache-entry> pour CachedStoreCatalogDisplay.jsp. Ensuite, lorsque vous demandez la page StoreCatalogDisplay, les fichiers CachedStoreCatalogDisplay.jsp, CachedHeaderDisplay.jsp et CachedFooterDisplay.jsp seront exécutés s'ils ne sont pas mis en cache. Voici un exemple de définition de <cache-entry> pour CachedStoreCatalogDisplay.jsp :


<cache-entry>
  <class>servlet</class>
 
<name>/AdvancedB2BDirect/ShoppingArea/CatalogSection/CategorySubsection/CachedStoreCatalogDisplay.jsp</name>
  <property name="save-attributes">false</property>
                
  <cache-id>
     <component      id="storeId" type="parameter">
          <required>true</required>
     </component>
     <component      id="catalogId" type="parameter">
          <required>false</required>
     </component>                    
  </cache-id>
</cache-entry>
Remarque : Si consume-subfragments a pour valeur "true", il n'est pas nécessaire que chaque fichier JSP inclus dynamiquement possède son propre <cache-entry>. Prenons l'exemple d'une page Web. La figure suivante montre une page Item Display personnalisée pour le magasin B2B avancé, qui contient des informations spécifiques à l'utilisateur. La page entière ne comporte que peu de valeurs à mettre en cache.

Exemple d'image montrant une page d'affichage d'article personnalisée pour le magasin B2B avancé, qui contient des informations spécifiques à l'utilisateur.

Exemple de page personnalisée

La figure suivante illustre la même page scindée en fragments d'après leur capacité de réutilisation et de mise en cache. Dans cet exemple, la page peut être scindée en différents fragments :

  • En-tête et Liste préconfigurée - identique pour tous les clients.
  • Affichage de l'article - identique pour tous les clients pour cet ID produit.
  • Barre latérale et Demande de devis - identique pour tous les clients avec les mêmes rôles utilisateur.
  • Ajout à la commande - identique pour tous les clients avec les mêmes ID de contrat.

Exemple d'image montrant la même page d'affichage d'article personnalisée pour le magasin B2B avancé, décomposée en fragments en fonction de la capacité de réutilisation et de mise en cache.

Exemple de page personnalisée fragmentée pour une mise en cache

Dans ce cas, tous les fragments peuvent être réutilisables ou mis en cache pour un plus large public. Seuls les fragments qui ne peuvent pas être mis en cache doivent être extraits du système dorsal, ce qui permet de réduire la charge de travail côte serveur et d'améliorer les performances.

Mise en cache de pages entières en excluant certains fragments

Dans certains cas, il est pratique d'exclure certains fragments de la mise en cache avec une page complète. Au lieu d'être mis en cache avec la full page, les fragments sont mis en cache séparément. Par exemple, s'il existe un message de bienvenue personnalisé ou une page de commande en cours, la propriété do-not-consume est utilisée. L'entrée parent est marquée par la propriété consume-subfragments et le fragment enfant qui contient la zone de personnalisation doit être marqué par cette propriété do-not-consume. Grâce à cette combinaison, le gain de performance obtenu par une mise en cache de page entière demeure intact pour la page à l'exclusion du fragment enfant qui est mis en cache distinctement du parent.

La page Web suivante représente une page de produit courante et sa barre d'options latérale dynamique comporte un fragment (MiniCurrentOrderDisplay.jsp) qui affiche une petite page personnalisée de la commande en cours.

Générez des règles d'ID de cache pour pouvoir mettre en cache la page produit et la page de commande en cours. La page de commande en cours étant unique pour chaque utilisateur, il est nécessaire, pour pouvoir la mettre en cache, d'utiliser l'ID de l'utilisateur comme ID de mise en cache. Créez un attribut de requête DC_userId afin que l'ID utilisateur soit utilisé comme ID de cache.

Voici un exemple de fichier cachespec.xml :


<cache-entry>        
        <class>servlet</class>         
       
<name>/AdvancedB2BDirect/ShoppingArea/CurrentOrderSection/MiniCurrentOrderDisplay.jsp</name>
   
        <property name="do-not-consume">true</property>
    
        <property
name="save-attributes">false</property>     
        <cache-id>         
                <component id="DC_userId" type="attribute">  
          
                        
<required>false</required>
                       
<not-value>-1002</not-value>
                </component> 
        </cache-id> 
</cache-entry> 

<cache-entry> 
        <class>servlet</class> 
       
<name>strutsaction</name>

        <property name="store-cookies">false</property>

        <property
name="save-attributes">false</property> 
        <property
name="consume-subfragments">true</property> 
        <cache-id> 
                <component id="" type="pathinfo"> 
                        <required>true</required> 
                       
<value>/StoreCatalogDisplay</value> 
                </component>
                <component id="storeId" type="parameter">
                        <required>true</required>
                </component>
                <component id="catalogId" type="parameter">
                        <required>true</required>
                </component>
        </cache-id>
</cache-entry>

strutsaction se trouve com.ibm.commerce.struts.v2.ECActionServlet.class dans HCL Commerce versions 9.0.0.x, ou com.ibm.commerce.struts.v2.ECActionServlet.class dans versions 9.0.1 ou ultérieures et si vous utilisez la configuration Strut 2 com.ibm.commerce.struts.v2.ECActionStrutsServlet.class. Lorsque l'attribut de requête DC_userId est utilisé pour constituer l'ID de mémoire cache de l'entrée de cache du fragment dans une full page avec un scénario de mise en cache de fragment, utilisez le fragment ci-dessus dans l'ID composant. Ceci évite que l'entrée de full page ne consomme le fragment de manière incorrecte suite à un échec de mise en cache du fragment que l'utilisateur générique peut mettre en cache. Si la full page consomme le fragment avec l'utilisateur générique, toutes les réussites en cache sur cette full page par d'autres utilisateurs généreront des échecs en cache sur la full page.

L'image suivante illustre les entrées de mise en cache :

Exemple illustrant de entrées de mise en cache pour l'exemple ci-dessus.

Le contenu de l'entrée de cache MiniCurrentOrderDisplay est illustré ci-après :

Exemple montrant le contenu de l'entrée MiniCurrentOrderDisplay.

Voici le MiniCurrentOrderDisplay qui est exclu dans l'entrée de cache StoreCatalogDisplay :

Exemple illustrant de entrées de mise en cache pour l'exemple ci-dessus.

Exemple montrant l'entrée StoreCatalogDisplay, avec exclusion de l'entrée MiniCurrentOrderDisplay.

Utilisation de DC_userId dans une mise en cache de page complète avec fragment

Lorsque l'attribut de requête DC_userId est utilisé pour constituer l'ID de mémoire cache de l'entrée de cache du fragment dans une full page avec un scénario de mise en cache de fragment, utilisez le fragment suivant dans l'ID composant. Ceci évite que l'entrée de full page ne consomme le fragment de manière incorrecte suite à un échec de mise en cache du fragment que l'utilisateur générique peut mettre en cache. Si la full page consomme le fragment avec l'utilisateur générique, toutes les réussites en cache sur cette full page par d'autres utilisateurs généreront des échecs en cache sur la full page. Ceci améliore également les performances du système puisque l'utilisateur générique peut alors bénéficier de réussites en cache dès la première requête, au lieu de la seconde lorsque DC_userId est renseigné avec la valeur -1002 provenant du cookie de la session.


<cache-entry>
<class>servlet</class>
<name>/path_to_JSP/mini-cart.jsp</name>
<property name="do-not-consume">true</property>
<property name="save-attributes">false</property>
<cache-id>
<component id="storeId" type="parameter">
<required>true</required>
</component>
<component id="DC_userId" type="attribute">
<required>false</required>
<not-value>-1002</not-value>
</component>