Topik ini menjelaskan cara menggunakan fitur pemilihan subset dinamis dari Service Mesh (ASM) untuk mengarahkan permintaan ke lingkungan runtime yang tepat, sehingga mempercepat proses inferensi Layanan Model Mesh.
Informasi latar belakang
Layanan Model Mesh menyediakan infrastruktur yang dapat diskalakan dan berperforma tinggi untuk mengelola, menerapkan, dan menjadwalkan beberapa layanan model.
Ketika Anda menjalankan beberapa model berbeda di Layanan Model Mesh secara bersamaan, umumnya model tertentu dimuat ke runtime penyajian model tertentu. Namun, layanan Kubernetes secara acak mengirimkan permintaan inferensi ke runtime penyajian model mana pun. Permintaan inferensi ini mungkin dirutekan berkali-kali di dalam Layanan Model Mesh sebelum akhirnya dikirim ke runtime penyajian model yang benar.
Pemilihan subset dinamis dapat mengidentifikasi model yang sedang berjalan di setiap beban kerja runtime di Layanan Model Mesh. Gateway ASM mengidentifikasi model yang sesuai dengan permintaan inferensi dan merutekan permintaan tersebut ke beban kerja runtime yang benar. Dengan cara ini, keputusan perutean Layanan Model Mesh dioptimalkan untuk mempercepat respons terhadap permintaan inferensi. Untuk informasi lebih lanjut tentang pemilihan subset dinamis, lihat Pemilihan Subset Dinamis.
Prasyarat
Instansi ASM versi V1.21.6.47 atau lebih baru telah dibuat. Untuk informasi lebih lanjut, lihat Buat Instansi ASM.
Cluster Container Service for Kubernetes (ACK) telah ditambahkan ke instansi ASM. Untuk informasi lebih lanjut, lihat Tambahkan Cluster ke Instansi ASM.
Layanan Model Mesh telah diaktifkan dan model sklearn-mnist telah diterapkan. Untuk informasi lebih lanjut, lihat Gunakan Layanan Model Mesh untuk Meluncurkan Layanan Inferensi Multi-Model.
Langkah 1: Terapkan model tf-mnist di Layanan Model Mesh
Kemampuan perutean presisi pemilihan subset dinamis utamanya digunakan dalam skenario multi-model. Oleh karena itu, model tf-mnist tambahan diterapkan di Layanan Model Mesh dalam contoh ini. Model tf-mnist adalah model mnist yang diimplementasikan oleh TensorFlow, dan lingkungan runtimenya disediakan oleh Triton serving runtime.
Persistent volume claim (PVC) my-models-pvc yang dibuat dengan menjalankan langkah-langkah di Gunakan Layanan Model Mesh untuk Meluncurkan Layanan Inferensi Multi-Model digunakan untuk menyimpan model tf-mnist. Semua konten di direktori mnist adalah konten model.
Simpan model tf-mnist pada volume persisten.
Gunakan kubectl untuk terhubung ke cluster ACK berdasarkan informasi dalam file kubeconfig. Kemudian, jalankan perintah berikut untuk menyalin file model mnist-svm.joblib ke folder /mnt/models pod pvc-access:
kubectl -n modelmesh-serving cp mnist pvc-access:/mnt/models/Jalankan perintah berikut untuk memverifikasi bahwa model ada pada volume persisten:
kubectl -n modelmesh-serving exec -it pvc-access -- ls -alr /mnt/models/Output yang Diharapkan:
-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 .
Terapkan layanan inferensi.
Buat file tf-mnist.yaml dengan konten berikut:
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: mnistGunakan kubectl untuk terhubung ke cluster ACK berdasarkan informasi dalam file kubeconfig. Kemudian, jalankan perintah berikut untuk menerapkan layanan inferensi tf-mnist:
kubectl apply -f tf-mnist.yamlTunggu sejenak (waktu tunggu bergantung pada kecepatan penarikan gambar). Kemudian, jalankan perintah berikut untuk memeriksa apakah layanan inferensi tf-mnist telah diterapkan:
kubectl get isvc -n modelmesh-servingOutput yang Diharapkan:
NAME URL READY sklearn-mnist grpc://modelmesh-serving.modelmesh-serving:8033 True tf-mnist grpc://modelmesh-serving.modelmesh-serving:8033 TrueOutput yang diharapkan menunjukkan bahwa dua model dengan kerangka kerja berbeda, sklearn-mnist dan tf-mnist, telah diterapkan di Layanan Model Mesh.
(Opsional) Langkah 2: Uji latensi pemrosesan permintaan inferensi di Layanan Model Mesh
Instal alat uji stres fortio. Untuk informasi lebih lanjut, lihat petunjuk instalasi proyek fortio.
Gunakan alat uji stres fortio untuk mengirim permintaan inferensi ke model tf-mnist. Untuk informasi lebih lanjut tentang cara mendapatkan alamat IP gateway ingress ASM, lihat Integrasikan KServe dengan ASM untuk Mengimplementasikan Layanan Inferensi Berbasis Model AI Cloud-Native.
ASM_GW_IP="Alamat IP gateway ingress ASM" 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.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.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.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.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.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.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.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.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.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.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.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, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<p>Output yang diharapkan:</p><div><p></p><div><code code-type="xCode" data-tag="codeblock" id="c78eb19a0dpw0" outputclass="language-bash">16:06:53.107 r1 [INF] scli.go:125> Memulai, command="Φορτίο", version="1.63.7 h1:S6e+z36nV6o8RYQSUI9EWYxhCoPJy4VdAB2HQROUqMg= go1.22.2 amd64 linux", go-max-procs=8 Fortio 1.63.7 berjalan pada 100 permintaan per detik, 8->8 proses, selama 1m0s: 192.168.0.7:8008/v2/models/tf-mnist/infer 16:06:53.107 r1 [INF] httprunner.go:121> Memulai tes http, run=0, url="192.168.0.7:8008/v2/models/tf-mnist/infer", thread=1, qps="100.0", warmup="parallel", conn-reuse="" 16:06:53.107 r1 [WRN] http_client.go:170> Mengasumsikan http:// pada skema yang hilang untuk '192.168.0.7:8008/v2/models/tf-mnist/infer' Memulai pada 100 qps dengan 1 thread(s) [gomax 8] selama 1m0s : 6000 panggilan masing-masing (total 6000) 16:07:53.172 r1 [INF] periodic.go:851> T000 berakhir setelah 1m0.007662555s : 6000 panggilan. qps=99.98723070575699 Berakhir setelah 1m0.007716622s : 6000 panggilan. qps=99.987 16:07:53.172 r1 [INF] periodic.go:581> Run berakhir, run=0, elapsed=60007716622, calls=6000, qps=99.98714061718327 Waktu tidur : count 5999 avg 0.0021861297 +/- 0.001025 min -0.011550303 max 0.003734337 sum 13.1145918 Waktu Fungsi Agregat : count 6000 avg 0.0072130591 +/- 0.0007502 min 0.006125677 max 0.020551562 sum 43.2783545 # range, titik tengah, persentil, jumlah >= 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 Kasus kesalahan : tidak ada data # Soket dan IP yang digunakan untuk setiap koneksi: [0] 1 soket digunakan, diselesaikan ke 192.168.0.7:8008, waktu koneksi : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262 Histogram waktu koneksi (s) : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262 # range, titik tengah, persentil, jumlah >= 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 Soket yang digunakan: 1 (untuk keepalive sempurna, akan menjadi 1) Uniform: false, Jitter: false, Catchup diizinkan: true Distribusi alamat IP: 192.168.0.7:8008: 1 Kode 200 : 6000 (100.0 %) Ukuran Header Respons : count 6000 avg 233.00067 +/- 0.02581 min 233 max 234 sum 1398004 Ukuran Body/Total Respons : count 6000 avg 454.00067 +/- 0.02581 min 454 max 455 sum 2724004 Semua selesai 6000 panggilan (plus 1 pemanasan) 7.213 ms rata-rata, 100.0 qps Berhasil menulis 11561 byte data Json ke 2024-04-24-160653_192_168_0_7_8008_v2_models_tf_mnist_infer_iZbp1jfq2w26u2kpxa9r3dZ.jsonOutput yang Diharapkan:
Lihat hasil uji stres visual dari fortio.
Jalankan perintah berikut untuk membuka server fortio lokal:
fortio serverGunakan browser untuk mengakses localhost:8080. Klik
saved resultsdi antarmuka, dan pilih file JSON pada server fortio untuk melihat hasil visual dari uji stres.
Seperti yang ditunjukkan pada gambar di atas, latensi beberapa permintaan inferensi yang dikirim ke Model Service Mesh meningkat. Hal ini disebabkan karena permintaan tersebut dialihkan ulang di dalam Model Service Mesh, dan kecepatan respons menurun.
Langkah 3: Aktifkan penyeimbangan beban subset dinamis untuk Model Service Mesh
Permintaan inferensi mengakses semua model yang berjalan di Model Service Mesh melalui layanan modelmesh-serving di namespace modelmesh-serving. Bagian ini menunjukkan cara mengonfigurasi penyeimbangan beban subset dinamis untuk layanan modelmesh-serving guna merutekan permintaan inferensi secara tepat ke runtime penyajian model yang berbeda.
Gunakan konten berikut untuk mengonfigurasi subset dinamis untuk layanan modelmesh-serving di Model Service Mesh. Untuk informasi lebih lanjut, lihat Kelola Aturan Tujuan.
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.comAturan tujuan sebelumnya secara dinamis mengelompokkan runtime penyajian model berdasarkan label
modelmesh.asm.alibabacloud.com. Model Service Mesh memperbarui label runtime secara dinamis sesuai dengan model yang dimuat dalam runtime penyajian.Gunakan konten berikut untuk mengubah isi layanan virtual bernama
vs-modelmesh-serving-service. Untuk informasi lebih lanjut, lihat Kelola Layanan Virtual.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: 8033Bidang
headerToDynamicSubsetKeyditambahkan ke layanan virtual sebelumnya berdasarkan persyaratan penyeimbangan beban subset dinamis. Gateway ASM mengonversi header permintaanmodeldalam permintaan inferensi menjadi metadata permintaan untuk mencocokkan subset dinamis dari Model Service Mesh.
(Opsional) Langkah 4: Uji latensi pemrosesan permintaan inferensi di Model Service Mesh setelah optimasi
Gunakan fortio untuk menjalankan tes lagi dan lihat hasil visualnya. Untuk informasi lebih lanjut, lihat Langkah 2.

Hasil yang diharapkan menunjukkan bahwa setelah load balancing subset dinamis ASM diaktifkan untuk optimasi, latensi akses semua permintaan inferensi berada dalam rentang kecil, dan latensi pemrosesan permintaan inferensi sangat berkurang.