Tous les produits
Search
Centre de documentation

Alibaba Cloud Service Mesh:Use dynamic subset load balancing to accelerate Model Service Mesh inference

Dernière mise à jour :Aug 11, 2026

Dans un déploiement Model Service Mesh multi-modèles, un service Kubernetes distribue les requêtes d'inférence de manière aléatoire sur tous les environnements d'exécution de modèles. Si une requête atteint un environnement qui n'héberge pas le modèle cible, Model Service Mesh la réachemine en interne jusqu'à ce qu'il trouve l'environnement approprié. Ce réacheminement ajoute de la latence.

L'équilibrage de charge par sous-ensemble dynamique résout ce problème en regroupant les environnements d'exécution selon les modèles qu'ils hébergent. Lorsqu'une requête d'inférence arrive sur la passerelle Service Mesh (ASM), celle-ci lit le nom du modèle dans l'en-tête de la requête et achemine directement la demande vers un environnement hébergeant ce modèle. Cette approche élimine le réacheminement et réduit la latence d'inférence.

Pour obtenir une vue d'ensemble du concept, consultez la rubrique Équilibrage de charge par sous-ensemble dynamique.

Fonctionnement

L'équilibrage de charge par sous-ensemble dynamique s'appuie sur deux ressources Istio : une DestinationRule définit quels environnements d'exécution regrouper, tandis qu'un VirtualService définit comment associer les requêtes à ces groupes.

  • DestinationRule permet de regrouper les environnements d'exécution en sous-ensembles. ASM étend la DestinationRule standard avec un champ dynamicSubset qui groupe les points de terminaison selon une clé de libellé. Model Service Mesh met automatiquement à jour les libellés des environnements d'exécution lors du chargement ou du déchargement des modèles, garantissant ainsi que les sous-ensembles restent actualisés sans intervention manuelle.

  • VirtualService associe les requêtes entrantes aux sous-ensembles. ASM étend le VirtualService standard avec un champ headerToDynamicSubsetKey qui mappe un en-tête de requête (tel que model) à la clé de libellé du sous-ensemble dynamique. La passerelle utilise ce mappage pour acheminer chaque requête vers le sous-ensemble approprié.

Si aucun sous-ensemble ne correspond à la requête, le paramètre fallbackPolicy détermine le comportement à adopter :

Politique de secours Comportement
ANY_ENDPOINT Achemine la requête vers n'importe quel environnement d'exécution disponible, indépendamment des libellés. Préserve la disponibilité au prix d'un réacheminement potentiel. Utilisé dans ce tutoriel.

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

Étape 1 : Déployer un second modèle

L'équilibrage de charge par sous-ensemble dynamique cible les scénarios multi-modèles. Cette étape ajoute un modèle tf-mnist (un modèle MNIST basé sur TensorFlow servi par l'environnement d'exécution Triton) aux côtés du modèle sklearn-mnist existant.

Remarque

Cette étape utilise la revendication de volume persistant (PVC) my-models-pvc créée dans la rubrique Utiliser Model Service Mesh pour déployer un service d'inférence multi-modèles. Le contenu du modèle tf-mnist correspond à tout ce qui se trouve dans le répertoire mnist.

Stocker le modèle sur le volume persistant

  1. Connectez-vous au cluster ACK avec kubectl, puis copiez le répertoire du modèle mnist sur le volume persistant :

    kubectl -n modelmesh-serving cp mnist pvc-access:/mnt/models/
  2. Vérifiez que le modèle existe bien sur le volume persistant :

    kubectl -n modelmesh-serving exec -it pvc-access -- ls -alr /mnt/models/

    Sortie attendue :

    -rw-r--r-- 1  502 staff 344817 Apr 23 08:17 mnist-svm.joblib
    drwxr-xr-x 3 root root    4096 Apr 23 08:23 mnist
    drwxr-xr-x 1 root root    4096 Apr 23 08:17 ..
    drwxrwxrwx 3 root root    4096 Apr 23 08:23 .

Déployer le service d'inférence

  1. Créez un fichier nommé tf-mnist.yaml avec le contenu suivant :

    apiVersion: serving.kserve.io/v1beta1
    kind: InferenceService
    metadata:
      name: tf-mnist
      namespace: modelmesh-serving
      annotations:
        serving.kserve.io/deploymentMode: ModelMesh
    spec:
      predictor:
        model:
          modelFormat:
            name: tensorflow
          storage:
            parameters:
              type: pvc
              name: my-models-pvc
            path: mnist
  2. Appliquez le manifeste :

    kubectl apply -f tf-mnist.yaml
  3. Attendez que l'image soit extraite, puis vérifiez que les deux modèles sont prêts :

    kubectl get isvc -n modelmesh-serving

    Sortie attendue :

    NAME            URL                                               READY
    sklearn-mnist   grpc://modelmesh-serving.modelmesh-serving:8033   True
    tf-mnist        grpc://modelmesh-serving.modelmesh-serving:8033   True

(Facultatif) Étape 2 : Évaluer la latence d'inférence avant optimisation

Utilisez fortio pour mesurer la latence de référence avant d'activer l'équilibrage de charge par sous-ensemble dynamique. Pour obtenir l'adresse IP de la passerelle d'entrée ASM, consultez la rubrique Intégrer KServe à ASM pour implémenter des services d'inférence basés sur des modèles d'IA cloud-native.

  1. Définissez l'adresse IP de la passerelle et exécutez un test de charge de 60 secondes sur le modèle tf-mnist :

    ASM_GW_IP="<your-asm-gateway-ip>"
    fortio load -jitter=False -H 'model: tf-mnist' -c 1 -qps 100 -t 60s -payload '{"inputs": [{ "name": "inputs", "shape": [1, 784], "datatype": "FP32", "contents": { "fp32_contents": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01176471, 0.07058824, 0.07058824, 0.07058824, 0.49411765, 0.53333336, 0.6862745, 0.10196079, 0.6509804, 1.0, 0.96862745, 0.49803922, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.11764706, 0.14117648, 0.36862746, 0.6039216, 0.6666667, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.88235295, 0.6745098, 0.99215686, 0.9490196, 0.7647059, 0.2509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.19215687, 0.93333334, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.9843137, 0.3647059, 0.32156864, 0.32156864, 0.21960784, 0.15294118, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07058824, 0.85882354, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7764706, 0.7137255, 0.96862745, 0.94509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3137255, 0.6117647, 0.41960785, 0.99215686, 0.99215686, 0.8039216, 0.04313726, 0.0, 0.16862746, 0.6039216, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05490196, 0.00392157, 0.6039216, 0.99215686, 0.3529412, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.54509807, 0.99215686, 0.74509805, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04313726, 0.74509805, 0.99215686, 0.27450982, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.13725491, 0.94509804, 0.88235295, 0.627451, 0.42352942, 0.00392157, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.31764707, 0.9411765, 0.99215686, 0.99215686, 0.46666667, 0.09803922, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1764706, 0.7294118, 0.99215686, 0.99215686, 0.5882353, 0.10588235, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0627451, 0.3647059, 0.9882353, 0.99215686, 0.73333335, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.9764706, 0.99215686, 0.9764706, 0.2509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.18039216, 0.50980395, 0.7176471, 0.99215686, 0.99215686, 0.8117647, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.15294118, 0.5803922, 0.8980392, 0.99215686, 0.99215686, 0.99215686, 0.98039216, 0.7137255, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09411765, 0.44705883, 0.8666667, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7882353, 0.30588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09019608, 0.25882354, 0.8352941, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7764706, 0.31764707, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07058824, 0.67058825, 0.85882354, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7647059, 0.3137255, 0.03529412, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.21568628, 0.6745098, 0.8862745, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.95686275, 0.52156866, 0.04313726, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.53333336, 0.99215686, 0.99215686, 0.99215686, 0.83137256, 0.5294118, 0.5176471, 0.0627451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }}]}' -a ${ASM_GW_IP}:8008/v2/models/tf-mnist/infer

    Sortie attendue :

    Sortie attendue

    16:06:53.107 r1 [INF] scli.go:125> Starting, command="Φορτίο", version="1.63.7 h1:S6e+z36nV6o8RYQSUI9EWYxhCoPJy4VdAB2HQROUqMg= go1.22.2 amd64 linux", go-max-procs=8
    Fortio 1.63.7 running at 100 queries per second, 8->8 procs, for 1m0s: 192.168.0.7:8008/v2/models/tf-mnist/infer
    16:06:53.107 r1 [INF] httprunner.go:121> Starting http test, run=0, url="192.168.0.7:8008/v2/models/tf-mnist/infer", threads=1, qps="100.0", warmup="parallel", conn-reuse=""
    16:06:53.107 r1 [WRN] http_client.go:170> Assuming http:// on missing scheme for '192.168.0.7:8008/v2/models/tf-mnist/infer'
    Starting at 100 qps with 1 thread(s) [gomax 8] for 1m0s : 6000 calls each (total 6000)
    16:07:53.172 r1 [INF] periodic.go:851> T000 ended after 1m0.007662555s : 6000 calls. qps=99.98723070575699
    Ended after 1m0.007716622s : 6000 calls. qps=99.987
    16:07:53.172 r1 [INF] periodic.go:581> Run ended, run=0, elapsed=60007716622, calls=6000, qps=99.98714061718327
    Sleep times : count 5999 avg 0.0021861297 +/- 0.001025 min -0.011550303 max 0.003734337 sum 13.1145918
    Aggregated Function Time : count 6000 avg 0.0072130591 +/- 0.0007502 min 0.006125677 max 0.020551562 sum 43.2783545
    # range, mid point, percentile, count
    >= 0.00612568 <= 0.007 , 0.00656284 , 35.88, 2153
    > 0.007 <= 0.008 , 0.0075 , 90.85, 3298
    > 0.008 <= 0.009 , 0.0085 , 97.77, 415
    > 0.009 <= 0.01 , 0.0095 , 99.42, 99
    > 0.01 <= 0.011 , 0.0105 , 99.68, 16
    > 0.011 <= 0.012 , 0.0115 , 99.77, 5
    > 0.012 <= 0.014 , 0.013 , 99.90, 8
    > 0.014 <= 0.016 , 0.015 , 99.95, 3
    > 0.016 <= 0.018 , 0.017 , 99.97, 1
    > 0.018 <= 0.02 , 0.019 , 99.98, 1
    > 0.02 <= 0.0205516 , 0.0202758 , 100.00, 1
    # target 50% 0.00725682
    # target 75% 0.00771164
    # target 90% 0.00798454
    # target 99% 0.00974747
    # target 99.9% 0.014
    Error cases : no data
    # Socket and IP used for each connection:
    [0]   1 socket used, resolved to 192.168.0.7:8008, connection timing : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262
    Connection time histogram (s) : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262
    # range, mid point, percentile, count
    >= 0.00421826 <= 0.00421826 , 0.00421826 , 100.00, 1
    # target 50% 0.00421826
    # target 75% 0.00421826
    # target 90% 0.00421826
    # target 99% 0.00421826
    # target 99.9% 0.00421826
    Sockets used: 1 (for perfect keepalive, would be 1)
    Uniform: false, Jitter: false, Catchup allowed: true
    IP addresses distribution:
    192.168.0.7:8008: 1
    Code 200 : 6000 (100.0 %)
    Response Header Sizes : count 6000 avg 233.00067 +/- 0.02581 min 233 max 234 sum 1398004
    Response Body/Total Sizes : count 6000 avg 454.00067 +/- 0.02581 min 454 max 455 sum 2724004
    All done 6000 calls (plus 1 warmup) 7.213 ms avg, 100.0 qps
    Successfully wrote 11561 bytes of Json data to 2024-04-24-160653_192_168_0_7_8008_v2_models_tf_mnist_infer_iZbp1jfq2w26u2kpxa9r3dZ.json
  2. Consultez les résultats fortio dans un navigateur :

    fortio server

    Ouvrez localhost:8080, cliquez sur saved results, puis sélectionnez le fichier JSON pour afficher la distribution de la latence.

    Latency distribution before optimization

    Sans l'équilibrage de charge par sous-ensemble dynamique, certaines requêtes d'inférence présentent une latence accrue car elles sont réacheminées via Model Service Mesh avant d'atteindre l'environnement d'exécution correct.

Étape 3 : Activer l'équilibrage de charge par sous-ensemble dynamique

Les requêtes d'inférence atteignent Model Service Mesh via le service modelmesh-serving dans le namespace modelmesh-serving. Configurez une DestinationRule et un VirtualService sur ce service pour acheminer les requêtes directement vers l'environnement d'exécution de modèle approprié.

Créer la DestinationRule

Appliquez la DestinationRule suivante pour regrouper dynamiquement les environnements d'exécution de modèles selon les modèles qu'ils hébergent. Pour plus d'informations, consultez la rubrique Gérer les règles de destination.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: modelmesh-serving
  namespace: modelmesh-serving
spec:
  host: modelmesh-serving
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        subsetSelectors:
          - fallbackPolicy: ANY_ENDPOINT
            keys:
              - modelmesh.asm.alibabacloud.com

Champs clés :

Champ Objectif
dynamicSubset Active le regroupement dynamique des points de terminaison en fonction des libellés des environnements d'exécution, plutôt que de définir des sous-ensembles statiques
keys Clé de libellé utilisée pour regrouper les environnements d'exécution. Model Service Mesh définit le libellé modelmesh.asm.alibabacloud.com sur chaque environnement d'exécution pour indiquer quels modèles il héberge
fallbackPolicy: ANY_ENDPOINT Lorsqu'aucun sous-ensemble ne correspond, achemine la requête vers n'importe quel environnement d'exécution disponible au lieu de rejeter la demande

Mettre à jour le VirtualService

Appliquez le VirtualService suivant pour mapper l'en-tête de requête model à la clé de sous-ensemble dynamique. Pour plus d'informations, consultez la rubrique Gérer les services virtuels.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-modelmesh-serving-service
  namespace: modelmesh-serving
spec:
  gateways:
    - grpc-gateway
  hosts:
    - '*'
  http:
    - headerToDynamicSubsetKey:
        - header: model
          key: modelmesh.asm.alibabacloud.com
      match:
        - port: 8008
      name: default
      route:
        - destination:
            host: modelmesh-serving
            port:
              number: 8033

Le champ headerToDynamicSubsetKey est une extension ASM du VirtualService Istio standard. Lorsque la passerelle reçoit une requête avec un en-tête model: tf-mnist, elle recherche la valeur correspondante au libellé modelmesh.asm.alibabacloud.com et achemine la requête vers un environnement d'exécution appartenant au sous-ensemble dynamique correspondant.

(Facultatif) Étape 4 : Évaluer la latence d'inférence après optimisation

Exécutez le même test fortio que celui décrit à l'étape 2 pour comparer la latence.

Latency distribution after optimization

Après activation de l'équilibrage de charge par sous-ensemble dynamique, toutes les requêtes d'inférence sont acheminées directement vers l'environnement d'exécution approprié. La distribution de la latence se resserre considérablement, sans valeurs aberrantes dues à un réacheminement interne.