Migration vers Liberty d'applications utilisant des modèles de programmation avec accès concurrent et asynchrone

Vous pouvez migrer des applications qui utilisent des beans Concurrency Utilities for Java™ EE, Asynchronous Beans, CommonJ Timer et Work Manager depuis WebSphere Application Server Traditional vers WebSphere Application Server Liberty.

Asynchronous Beans, CommonJ Timer et Work Manager ne sont pas disponibles dans Liberty. Lors de la migration vers Liberty, les applications doivent basculer vers le modèle de programmation Concurrency Utilities for Java EE. Pour plus d'informations, voir Exemple de tâches d'API implémentant Concurrency Utilities for Java EE.

Différences dans la configuration et l'utilisation d'unités d'exécution

WebSphere Application Server Traditional fournit un certain nombre d'options de configuration pour Concurrency Utilities for Java EE concernant la mise en pool des unités d'exécution, qui sont configurés différemment ou indisponibles dans Liberty. Liberty utilise un seul pool d'unités d'exécution commun à tous les programmes d'exécution gérés et à tous les programmes d'exécution planifiés gérés qui sont également partagés par les composants Liberty. Liberty peut ainsi optimiser la gestion des unités d'exécution. Dans WebSphere Application Server Traditional, chaque gestionnaire de travaux peut être configuré avec deux pools d'unités d'exécution. L'un des pools est destiné aux tâches soumises pour exécution le plus tôt possible (méthodes submit/execute/invoke de programme d'exécution géré) et comporte une file d'attente de demandes configurable et une action à engager quand la capacité de la file d'attente est dépassée. L'autre pool est destiné aux tâches planifiées (méthodes schedule de programme d'exécution d'éléments planifiés gérés).

Si vous prévoyez d'utiliser Concurrency Utilities for Java EE avec des pools d'unités d'exécution séparés dans Liberty, vous pouvez envisager plusieurs approches pour aboutir à un comportement similaire à celui des options de configuration disponibles dans WebSphere Application Server Traditional.

[17.0.0.4 and later]

Utilisation de la configuration de règle d'accès simultané

Utilisez l'élément concurrencyPolicy pour répliquer une partie du comportement à partir de WebSphere Application Server Traditional dans Liberty. Le tableau ci-après répertorie les options de configuration disponibles pour l'élément concurrencyPolicy indique de quelle manière cet élément est comparé à WebSphere Application Server Traditional. La configuration concurrencyPolicy ne s'applique pas aux tâches planifiées.

Tableau 1.
concurrencyPolicy pour les programmes d'exécution gérés Liberty Programmes d'exécution gérés et gestionnaire de travaux WebSphere Application Server Traditional
   
max Nombre maximal d'unités d'exécution
maxQueueSize Taille de la file d'attente de demandes de travail
maxWaitForEnqueue Action en cas de saturation de la file d'attente de demandes de travail = ATTENTE
runIfQueueFull = false Action en cas de saturation de la file d'attente de demandes de travail = ECHEC
startTimeout Délai de démarrage
longRunningPolicyRef + longrunning hint Travail de démon

L'élément expedite correspond au nombre cible minimal d'unités d'exécution qui sont accélérées sur le pool d'unités d'exécution global Liberty à la place d'un nombre minimal fixe d'unités d'exécution.

Construction d'un programme d'exécution Java SE autour d'une fabrique d'unités d'exécution gérée

Le package java.util.concurrent de Java SE permet de construire de plusieurs manières des pools d'unités d'exécution en tant que programmes d'exécution et programmes d'exécution planifiés autour d'une fabrique d'unités d'exécution spécifique. Une fabrique d'unités d'exécution gérée peut être fournie à la place d'une fabrique d'unités d'exécution non gérée, de façon à disposer d'un pool d'unités d'exécution réalisant des tâches sur des unités d'exécution gérées. Contrairement au programme d'exécution géré et au programme d'exécution d'éléments planifiés gérés, les unités d'exécution gérées mises en pool par ces programmes opèrent avec le contexte d'unité d'exécution obtenu lors de la recherche de la fabrique d'unités d'exécution gérée et non pas le contexte lors de la soumission ou la planification de la tâche. Le contexte d'unité d'exécution perdure également sur l'unité d'exécution pendant toute sa durée de vie, ce qui réduit la surcharge due au changement de contexte.

[17.0.0.4 and later]

Exemple de remplacement pour maximum d'unités d'exécution de travaux et configuration de file d'attente de travaux

<managedExecutorService jndiName="concurrent/execSvc">
    <concurrencyPolicy max="2" maxQueueSize="3" runIfQueueFull="false" maxWaitForEnqueue="0"/>
</managedExecutorService>

Exemple de remplacement pour maximum d'unités d'exécution d'alarme

int maxAlarms = 2;
ManagedThreadFactory threadFactory =
    (ManagedThreadFactory) new InitialContext().lookup(
        "java:comp/DefaultManagedThreadFactory");
ScheduledExecutorService executor =
    Executors.newScheduledThreadPool(maxAlarms, threadFactory);
Callable<Integer> task = new MyTask();
ScheduledFuture<Integer> future = executor.schedule(
    task, 50, TimeUnit.SECONDS);
int result = future.get();
[17.0.0.4 and later]

Application d'un délai d'attente au démarrage

<managedExecutorService jndiName="concurrent/execSvc">
    <concurrencyPolicy startTimeout="1m"/>
</managedExecutorService>

Application d'une expiration de délai de travail

Utilisez WebSphere Application Server Traditional pour configurer une expiration de délai de travail qui s'applique aux tâches que vous soumettez pour exécution dès que possible (méthodes submit/execute/invoke). Si une tâche s'exécute plus longtemps que le délai imparti, le programme tente de l'annuler en l'interrompant. Bien que Liberty ne dispose pas d'une option de configuration pour spécifier un tel délai, vous pouvez implémenter un comportement similaire en soumettant la tâche avec un programme d'écoute de tâche gérée. En réponse à la notification taskStarting, le programme d'écoute de tâche gérée planifie une tâche pour annuler la méthode Future. Vous pouvez également, lorsque vous utilisez un programme d'exécution de pool d'unités d'exécution où un programme d'écoute de tâche gérée n'est pas disponible, outrepasser la méthode beforeExecute du programme d'exécution de pool d'unités d'exécution afin de planifier une tâche qui interrompt l'unité d'exécution.

Exemple de remplacement d'une expiration de délai de travail

ManagedExecutorService executor =
    (ManagedExecutorService) new InitialContext().lookup(
        "java:comp/DefaultManagedExecutorService");
Callable<Long> slowTask = new SlowTask();
slowTask = ManagedExecutors.managedTask(
           slowTask, new WorkTimeout(5, TimeUnit.SECONDS));
Future<Long> future = executor.submit(slowTask);
try {
    long result = future.get(1, TimeUnit.MINUTES);
    // task successful...
} catch (CancellationException x) {
    // task was canceled, possibly due to timeout
}

public class WorkTimeout implements ManagedTaskListener {
    private final long timeout;
    private final TimeUnit unit;

    public WorkTimeout(long timeout, TimeUnit unit) {
        this.timeout = timeout;
        this.unit = unit;
    }

    public void taskSubmitted(Future<?> future,
        ManagedExecutorService executor, Object task) {}

    public void taskStarting(final Future<?> future,
        ManagedExecutorService executor, Object task) {
        try {
            ScheduledExecutorService scheduledExecutor =
                (ScheduledExecutorService) new InitialContext().lookup(
                    "java:comp/DefaultManagedScheduledExecutorService");
            scheduledExecutor.schedule(new Runnable() {
                @Override
                public void run() {
                    if (!future.isDone())
                        future.cancel(true);
                }
            }, timeout, unit);
        } catch (NamingException x) {
            x.printStackTrace(System.out);
        }
    }

    public void taskAborted(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}

    public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}
}
[17.0.0.4 and later]

Exemple de travail de démon

Configuration:
<concurrencyPolicy id="longRunning" max="2"/>
<managedExecutorService jndiName="concurrent/execSvc" longRunningPolicyRef="longRunning" />

Application code:
ManagedExecutorService executor =
 (ManagedExecutorService) new InitialContext().lookup(
   "concurrent/execSvc");
Map<String, String> props = Collections.singletonMap(ManagedTask.LONGRUNNING_HINT, 
Boolean.TRUE.toString());
Callable<Long> slowTask = ManagedExecutors.managedTask(new SlowTask(), props, null);
Future<Long> future = executor.submit(slowTask);

Icône indiquant le type de rubrique Rubrique de référence

Nom du fichier : rwlp_mig_workmgr.html