Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här sidan innehåller vägledning, exempelkod och en exempelanteckningsbok för slutpunkter för belastningstestning av vektorsökning. Belastningstestning hjälper dig att förstå prestanda och produktionsberedskap för en slutpunkt för vektorsökning innan den distribueras till produktion. Belastningstestning kan berätta om:
- Svarstid på olika skalningsnivåer
- Dataflödesgränser och flaskhalsar (begäranden per sekund, svarstidsuppdelning)
- Felfrekvenser under varaktig belastning
- Resursanvändning och kapacitetsplanering
Mer information om belastningstestning och relaterade begrepp finns i Belastningstestning för serveringsslutpunkter.
Kravspecifikation
Innan du påbörjar de här stegen måste du ha en distribuerad slutpunkt för vektorsökning och ett tjänsthuvudnamn med Can Query-behörigheter på slutpunkten. Se Steg 1: Konfigurera autentisering med tjänstprincip.
Ladda ned och importera en kopia av följande filer och en exempelanteckningsbok till din Azure Databricks-arbetsyta:
-
input.json. Det här är ett exempel på
input.jsonfilen som anger nyttolasten som skickas av alla samtidiga anslutningar till slutpunkten. Du kan ha flera filer om det behövs. Om du använder exempelanteckningsboken genereras den här filen automatiskt från den angivna indatatabellen. -
fast_vs_load_test_async_load.py. Ladda upp det här skriptet till din arbetsyta (till exempel
/Workspace/Users/<your-username>/fast_vs_load_test_async_load.py) och angelocust_script_pathnotebook-parametern till dess sökväg. Det här skriptet hanterar autentisering, leverans av nyttolast och insamling av felsökningsmetrik. - Följande notebook-exempel, som kör belastningstesterna. För bästa prestanda ska du köra den här notebooken på ett kluster med en enda nod och ett stort antal kärnor (Locust skalar över alla tillgängliga processorer). Högt minne rekommenderas för frågor med förgenererade inbäddningar.
Exempelnotebook och snabbstart
Kom igång med följande exempelanteckningsbok. Det stöder två utforskningslägen: en gradvis svepning som testar specifika samtidighetsnivåer som du definierar och ett binärt sökläge som automatiskt hittar den maximala hållbara QPS (brytpunkt) i några få steg. Alla parametrar konfigureras med widgetar, så notebook-filen kan köras interaktivt eller som ett Databricks-jobb utan kodredigeringar.
Anteckningsbok för Locust-belastningstest
Ramverk för belastningstestning: Gräshoppa
Locust är ett ramverk för belastningstestning med öppen källkod som gör att du kan göra följande:
- Variera antalet samtidiga klientanslutningar
- Kontrollera hur snabbt anslutningarna skapas
- Mäta slutpunktsprestanda under hela testet
- Identifiera automatiskt och använd alla tillgängliga CPU-kärnor
Exempelanteckningsboken använder --processes -1 flaggan för att automatiskt identifiera CPU-kärnor och utnyttja dem fullt ut.
Om Locust begränsas av processorn visas det ett meddelande i utdata.
Steg 1: Konfigurera autentisering med tjänstens huvudnamn
Viktigt!
För produktionsliknande prestandatestning bör du alltid använda autentisering med OAuth-huvudanvändare. Tjänsthuvudprinciper ger därigenom upp till 100 ms snabbare svarstid och högre överföringsgränser för en begäran jämfört med personliga åtkomsttoken (PAT).
Skapa och konfigurera tjänstens huvudnamn
Skapa ett huvudnamn för Databricks-tjänsten. Anvisningar finns i Lägga till tjänstens huvudnamn i ditt konto.
Bevilja behörigheter:
- Gå till slutpunktssidan för vektorsökning.
- Klicka på Behörigheter.
- Ge tjänstens huvudnamn Can Query-behörigheter .
Skapa OAuth-hemlighet.
- Gå till tjänsthuvudmannens detaljsida.
- Klicka på fliken Hemligheter .
- Klicka på Generera hemlighet.
- Ange livslängd (rekommendera 365 dagar för långsiktig testning).
- Kopiera både klient-ID och hemlighet omedelbart.
Lagra autentiseringsuppgifter på ett säkert sätt.
- Skapa ett Databricks-hemlighetsområde. Anvisningar finns i Självstudie: Skapa och använda en Databricks-hemlighet.
- Som du ser i följande kodexempel lagrar du klient-ID:t för tjänstens huvudnamn som
service_principal_client_idoch lagrar OAuth-hemligheten somservice_principal_client_secret.
# In a Databricks notebook dbutils.secrets.put("load-test-auth", "service_principal_client_id", "<CLIENT_ID>") dbutils.secrets.put("load-test-auth", "service_principal_client_secret", "<SECRET>")
Steg 2: Konfigurera belastningstestet
Notebook-konfiguration
Konfigurera anteckningsbokparametrarna med widgetarna överst i anteckningsboken. När du kör notebook-filen som ett Databricks-jobb skickar du dessa värden som jobbparametrar. Inga kodredigeringar krävs.
| Parameter | Description | Rekommenderat värde |
|---|---|---|
endpoint_name |
Namnet på vektorsökningens slutpunkt | Ditt slutpunktsnamn |
index_name |
Fullständigt indexnamn (catalog.schema.index) |
Ditt indexnamn |
test_table |
Källtabell för exempelfrågor från (catalog.schema.table) |
Din indextabell för indata |
query_column |
Textkolumn som ska användas för hanterade inbäddningar | Lämna som text eller ange som ditt kolumnnamn |
embedding_column |
Kolumn som innehåller förberäknade inbäddningsvektorer. Används endast för självhanterade inbäddningar. | Lämna tomt för hanterade inbäddningar |
sample_size |
Antal frågor som ska provas för testet | 1000 |
target_concurrencies |
Kommaavgränsad lista över samtidiga klientantal som ska testas | 5,10,20,50 |
step_duration_seconds |
Varaktighet i sekunder per samtidighetsnivå. Ett värde gäller för alla nivåer eller ger en per nivå som en kommaavgränsad lista. |
300 (5 minuter) |
secret_scope_name |
Namn på Databricks hemlighetsomfång | Ditt omfångsnamn |
locust_script_path |
Arbetsytans sökväg till skriptet fast_vs_load_test_async_load.py |
/Workspace/Users/<your-username>/fast_vs_load_test_async_load.py |
output_table |
(Valfritt) Deltatabell för lagring av resultat i (catalog.schema.table). Skapas automatiskt vid första körningen. |
catalog.schema.load_test_results |
run_name |
Ange ett namn eller en kommentar för att tagga den här körningen för senare analys | En beskrivande etikett |
exploration_mode |
gradual sveper igenom target_concurrencies i ordning.
binary_search hittar brytpunkten automatiskt (se Utforskning av brytpunkt). |
gradual |
max_target_qps |
(binary_search endast) Övre gräns för QPS-sökningen |
500 |
exploration_steps |
(binary_search endast) Maximalt antal binära sök iterationer |
8 |
error_rate_threshold |
(binary_search endast) Högsta godtagbara felfrekvens (%) för ett steg som ska räknas som en framgång |
1.0 |
num_results |
Antal resultat som ska returneras per fråga | 10 |
columns_to_return |
Kommaavgränsad lista över kolumner som ska returneras i frågeresultat (till exempel id,text). Lämna det tomt för att returnera alla kolumner. |
Lämna tomt som standard |
Förvaltade vs. självförvaltade inbäddningar
Notebook-filen stöder både hanterade inbäddningar (där Databricks genererar inbäddningar vid frågetillfället) och självhanterade inbäddningar (där du skickar förberäknade vektorer direkt). Konfigurera lämpliga parametrar baserat på din indextyp.
| Indextyp | Parameter som ska anges | Lämna oet |
|---|---|---|
| Hanterade inbäddningar (Delta Sync-index med Databricks-hanterad inbäddningsmodell) |
query_column – det textkolumnnamn som ska användas som fråga |
embedding_column (lämna tomt) |
| Självhanterade inbäddningar (Delta Sync eller Direct Vector Access-index med förberäknade vektorer) |
embedding_column — kolumnen som innehåller förkomputerade inbäddningsvektorer |
query_column |
Anmärkning
För hanterade inbäddningsindex mäter belastningstestet svarstid från slutpunkt till slutpunkt, inklusive inbäddningsgenereringstid. Om din inbäddningsslutpunkt skalas till noll, uppstår kallstartsfördröjning vid den första testkörningen. Se Identifiera flaskhalsen för inbäddningsmodellen för hur du isolerar svarstid för inbäddning från söksvarstid.
Varför 5-10 minuter?
En minsta testvaraktighet på 5 minuter är kritisk.
- De första frågorna kan omfatta kostnader för kallstart.
- Slutpunkter behöver tid för att uppnå prestanda med stabilt tillstånd.
- Automatisk skalning av modellen som betjänar slutpunkter (om den är aktiverad) tar tid att aktivera.
- Korta tester missar strypningsbeteenden under kontinuerlig belastning.
I följande tabell visas rekommenderade testvaraktigheter beroende på ditt testmål.
| Testtyp | Testlängd | Testmål |
|---|---|---|
| Snabb röktest | 2–3 minuter | Verifiera grundläggande funktioner |
| Prestandabaslinje | 5–10 minuter | Tillförlitliga mått för stabilt tillstånd |
| Stresstest | 15–30 minuter | Identifiera resursöverbelastning |
| Uthållighetstestning | 1–4 timmar | Degradering, svarstidsstabilitet |
Utforskning av brytpunkt (binärt sökläge)
Förutom den gradvisa svepningen (exploration_mode=gradual) stöder notebook-filen ett automatiskt binärt sökläge som letar upp maximalt hållbart QPS utan att du behöver ange samtidighetsnivåerna manuellt.
Så här fungerar det
Ange exploration_mode=binary_search och ange max_target_qps (till exempel 500). Notebook-filen använder Little's Law (concurrency = QPS × avg_latency_sec) för att konvertera varje QPS-mål till en uppskattad samtidighetsnivå och kör sedan en binär sökning enligt följande:
- Börja vid
max_target_qps / 2(250 i exemplet). - Om felfrekvensen är lägre
error_rate_thresholdän (lyckades) höjer du den lägre gränsen och provar en högre QPS (375, sedan 500 och så vidare). - Om felfrekvensen överskrider tröskelvärdet (fel) sänker du den övre gränsen och försöker halvvägs mellan den senaste lyckade och misslyckade åtgärden.
- Upprepa för upp till
exploration_stepssteg (standard 8) eller tills sökområdet begränsas till inom 5% avmax_target_qps.
Följande tabell visar hur sökningen konvergerar efter en hypotetisk slutpunkt med en brytpunkt runt 430 QPS:
| Steg | QPS-mål | Felfrekvens | Outcome | Nytt intervall |
|---|---|---|---|---|
| 1 | 250 | 0.1% | FRAMGÅNG | [250, 500] |
| 2 | 375 | 0,3% | FRAMGÅNG | [375, 500] |
| 3 | 437 | 4.5% | MISSLYCKANDE | [375, 437] |
| 4 | 406 | 0,8 % | FRAMGÅNG | [406, 437] |
| 5 | 421 | 2.1% | MISSLYCKANDE | [406, 421] |
Efter 5–8 steg konvergerar sökningen på brytpunkten – i det här exemplet ungefär 406–421 QPS – med betydligt färre testkörningar än en exhaustiv sökning.
När du ska använda varje läge
| Läge | När det bör användas |
|---|---|
gradual |
Du känner redan till det förväntade driftsintervallet och vill karakterisera prestanda på specifika samtidighetsnivåer. |
binary_search |
Du vill hitta maximalt hållbara QPS snabbt, utan att känna till samtidighetsnivåerna i förväg. |
Steg 3. Utforma frågeuppsättningen
När det är möjligt bör frågeuppsättningen återspegla den förväntade produktionstrafiken så nära som möjligt. Mer specifikt bör du försöka matcha den förväntade fördelningen av frågor när det gäller innehåll, komplexitet och mångfald.
Använd realistiska frågor. Använd inte slumpmässig text, till exempel "testfråga 1234".
Matcha produktionstrafikens förväntade distribution. Om du förväntar dig 80% vanliga frågor, 15% medelfrekventa frågor och 5% sällsynta frågor, bör frågeuppsättningen återspegla den fördelningen.
Matcha den typ av fråga som du förväntar dig att se i produktion. Om du till exempel förväntar dig att produktionsfrågor ska använda hybridsökning eller -filter bör du också använda dem i frågeuppsättningen.
Exempelfråga med filter:
{ "query_text": "wireless headphones", "num_results": 10, "filters": { "brand": "Sony", "noise_canceling": true } }Exempelfråga med hybridsökning:
{ "query_text": "best noise canceling headphones for travel", "query_type": "hybrid", "num_results": 10 }
Förfrågevariation och cachehantering
Slutpunkter för vektorsökning cachelagrar flera typer av frågeresultat för att förbättra prestandan. Den här cachelagringen kan påverka belastningstestresultatet. Därför är det viktigt att vara uppmärksam på frågeuppsättningens mångfald. Om du till exempel upprepade gånger skickar samma uppsättning frågor testar du cachen, inte den faktiska sökprestandan.
| Användning: | När: | Example |
|---|---|---|
| Identiska eller få frågor |
|
En produktrekommendationswidget som visar "trendande objekt" – samma fråga körs tusentals gånger per timme. |
| Olika frågor |
|
En e-handelssökning där varje användare skriver olika produktsökningar. |
Ytterligare rekommendationer finns i Sammanfattning av metodtips.
Alternativ för att skapa en frågeuppsättning
Kodflikarna visar tre alternativ för att skapa en mängd olika frågeuppsättningar. Det finns ingen one-size-fits-all. Välj den som fungerar bäst för dig.
- (Rekommenderas) Slumpmässig sampling från indexindatatabellen. Detta är en bra allmän utgångspunkt.
- Sampling från produktionsloggar. Det här är en bra början om du har produktionsloggar. Tänk på att frågor vanligtvis ändras med tiden, så uppdatera testuppsättningen regelbundet för att hålla den uppdaterad.
- Genererar syntetiska frågor. Detta är användbart om du inte har produktionsloggar eller om du använder komplexa filter.
Slumpmässig sampling från indatatabell
Följande kod tar exempel på slumpmässiga frågor från indexindatatabellen.
import pandas as pd
import random
# Read the index input table
input_table = spark.table("catalog.schema.index_input_table").toPandas()
# Sample random rows
n_samples = 1000
if len(input_table) < n_samples:
print(f"Warning: Only {len(input_table)} rows available, using all")
sample_queries = input_table
else:
sample_queries = input_table.sample(n=n_samples, random_state=42)
# Extract the text column (adjust column name as needed)
queries = sample_queries['text_column'].tolist()
# Create query payloads
query_payloads = [{"query_text": q, "num_results": 10} for q in queries]
# Save to input.json
pd.DataFrame(query_payloads).to_json("input.json", orient="records", lines=True)
print(f"Created {len(query_payloads)} diverse queries from index input table")
Exempel från produktionsloggar
Följande kodexempel hämtas proportionellt från produktionsfrågor.
# Sample proportionally from production queries
production_queries = pd.read_csv("queries.csv")
# Take stratified sample maintaining frequency distribution
def create_test_set(df, n_queries=1000):
# Group by frequency buckets
df['frequency'] = df.groupby('query_text')['query_text'].transform('count')
# Stratified sample
high_freq = df[df['frequency'] > 100].sample(n=200) # 20%
med_freq = df[df['frequency'].between(10, 100)].sample(n=300) # 30%
low_freq = df[df['frequency'] < 10].sample(n=500) # 50%
return pd.concat([high_freq, med_freq, low_freq])
test_queries = create_test_set(production_queries)
test_queries.to_json("input.json", orient="records", lines=True)
Syntetiska frågor
Om du inte har produktionsloggar ännu kan du generera syntetiska olika frågor.
# Generate diverse queries programmatically
import random
# Define query templates and variations
templates = [
"find {product} under ${price}",
"best {product} for {use_case}",
"{adjective} {product} recommendations",
"compare {product1} and {product2}",
]
products = ["laptop", "headphones", "monitor", "keyboard", "mouse", "webcam", "speaker"]
prices = ["500", "1000", "1500", "2000"]
use_cases = ["gaming", "work", "travel", "home office", "students"]
adjectives = ["affordable", "premium", "budget", "professional", "portable"]
diverse_queries = []
for _ in range(1000):
template = random.choice(templates)
query = template.format(
product=random.choice(products),
product1=random.choice(products),
product2=random.choice(products),
price=random.choice(prices),
use_case=random.choice(use_cases),
adjective=random.choice(adjectives)
)
diverse_queries.append(query)
print(f"Generated {len(set(diverse_queries))} unique queries")
Steg 4. Testa nyttolasten
Verifiera nyttolasten innan du kör det fullständiga lasttestet:
- I Databricks-arbetsytan navigerar du till vektorsökningens slutpunkt.
- I det vänstra sidofältet klickar du på Servering.
- Välj slutpunkten.
- Klicka på Använd → fråga.
- Klistra in innehållet
input.jsoni frågerutan. - Kontrollera att slutpunkten returnerar förväntade resultat.
Detta säkerställer att belastningstestet mäter realistiska frågor, inte felsvar.
Steg 5. Kör belastningstestet
Anslutningskontroll och uppvärmning
Innan belastningstestet börjar utför anteckningsboken två förberedelsesteg:
Anslutningskontroll: Skickar en enskild avsökningsfråga med autentiseringsuppgifterna för tjänsthuvudkontot. Om slutpunkten returnerar ett 401- eller 403-fel misslyckas notebooken omedelbart med ett tydligt
PermissionErroristället för att köra belastningstestet som bara resulterar i feldata. Detta sparar tid när autentiseringsuppgifter eller behörigheter är felkonfigurerade.Uppvärmningstest (1 minut): Kör ett kort test med låg samtidighet som värmer upp slutpunktscacheminnen och validerar ände-till-ände-flödet för begäran. Uppvärmningsresultaten används inte för prestandamått. I binärt sökläge används svarstiden för uppvärmning också som baslinje för Littles samtidighetsuppskattning för lag.
Testserie för huvudbelastning
Notebook-filen kör en serie tester med ökad samtidighet för klienten:
- Start: Låg samtidighet (till exempel 5 samtidiga klienter)
- Mellan: Medelhög samtidighet (till exempel 10, 20 eller 50 klienter)
- Slut: Hög samtidighet (till exempel över 100 klienter)
Varje test körs under den tid som konfigurerats i step_duration_seconds (5–10 minuter rekommenderas).
Vad notebooken mäter
Bärbara datorn mäter och rapporterar följande:
Svarstidsmått:
- P50 (median): Hälften av frågorna är snabbare än så här.
- P95: 95% av frågor är snabbare än så. Det här är ett viktigt SLA-mått.
- P99: 99% av frågor är snabbare än så här.
- Max: Värsta möjliga svarstid.
Dataflödesmått:
- RPS (begäranden per sekund): Lyckade frågor per sekund.
- Totalt antal frågor: Antal slutförda frågor.
- Lyckad frekvens: Procentandel lyckade frågor.
Fel:
- Frågefel efter typ
- Undantagsmeddelanden
- Antal tidsgränser
Resultatlagring
Om parametern output_table har angetts lagrar notebook-filen en rad per samtidighetsnivå (eller per binärt söksteg) i en Delta-tabell i Unity Catalog. Tabellen skapas automatiskt vid den första körningen och läggs till vid efterföljande körningar. Varje rad innehåller run_namefälten , exploration_mode, samtidighet, lyckade/misslyckade, svarstids percentiler, RPS och binära sökspecifika fält (bs_step, bs_target_qps, bs_outcome). På så sätt kan du jämföra körningar över tid med hjälp av SQL- eller BI-verktyg.
Körs som ett Databricks-jobb
Alla notebook-parametrar definieras som dbutils.widgets, som mappas direkt till Databricks-jobbparametrar. Så här schemalägger eller automatiserar du belastningstester:
- Skapa ett jobb med anteckningsboken som uppgift.
- Ange widgetvärdena som Jobbparametrar. Inga kodredigeringar krävs.
- Koppla jobbet till ett kluster med en nod med många CPU-kärnor (locust-fördelar från parallella arbetare).
- Kör på begäran eller enligt ett schema för återkommande baslinjetester.
Steg 6. Tolka resultat
I följande tabell visas mål för bra prestanda:
| Mätvärde | Target | Comment |
|---|---|---|
| P95-svarstid | < 500 ms | De flesta frågor är snabba |
| P99-svarstid | < 1 s | Rimlig prestanda för långsvansfrågor |
| Framgångsfrekvens | > 99,5% | Låg felfrekvens |
| Svarstid över tid | Stabil | Ingen försämring observerades under testet |
| Frågor per sekund | Uppfyller målet | Slutpunkten kan hantera förväntad trafik |
Följande resultat indikerar dålig prestanda:
- P95 > 1s. Anger att frågorna är för långsamma för användning i realtid.
- P99 > 3 sek. Svarstid på långa frågor skadar användarupplevelsen.
- Framgångsfrekvens < 99%. För många fel.
- Ökad svarstid. Anger resursöverbelastning eller minnesläcka.
- Hastighetsbegränsningsfel (429). Anger att högre slutpunktskapacitet krävs.
Kompromiss mellan RPS och svarstid
Maximal RPS är inte den optimala punkten för produktionseffektivitet. Svarstiden ökar icke-linjärt när du närmar dig maximalt dataflöde. Att arbeta med maximal RPS resulterar ofta i 2–5 gånger högre svarstid jämfört med 60–70% med maximal kapacitet.
I följande exempel visas hur du analyserar resultaten för att hitta den optimala driftpunkten.
- Den maximala RPS är 480 vid 150 samtidiga klienter.
- Den optimala driftpunkten är 310 RPS på 50 samtidiga klienter (65% kapacitet).
- Svarstidsstraffet vid maximum: P95 är 4,3x högre (1,5 sekunder jämfört med 350 ms)
- I det här exemplet är rekommendationen att storleksanpassa slutpunkten för 480 RPS-kapacitet och arbeta med ~310 RPS.
| Konkurens | P50 | P95 | P99 | RPS | Success | Capacity |
|---|---|---|---|---|---|---|
| 5 | 80 ms | 120 ms | 150 ms | 45 | 100 % | 10 % |
| 10 | 85 ms | 140 ms | 180 ms | 88 | 100 % | 20% |
| 20 | 95 ms | 180 ms | 250 ms | 165 | 99,8% | 35 % |
| 50 | 150 ms | 350 ms | 500 ms | 310 | 99.2% | 65% ← Optimal punkt |
| 100 | 250 ms | 800 ms | 1.2s | 420 | 97,5% | 90% ⚠️ Närmar sig max |
| 150 | 450 ms | 1,5 s | 2.5s | 480 | 95,0% | 100% ❌ högsta RPS |
Att arbeta med maximalT antal RPS kan leda till följande problem:
- Försämring av latens. I exemplet är P95 350 ms vid 65% kapacitet men är 1,5 s vid 100% kapacitet.
- Inget utrymme för att hantera trafiktoppar. Vid full kapacitet orsakar varje topp en timeout. Vid 65% kapacitet kan en trafiktoppar på 50% hanteras utan problem.
- Ökade felfrekvenser. I exemplet är framgångsgraden 99,2% med 65% kapacitet men 95,0% – en felfrekvens på 5% – med 100% kapacitet.
- Risk för resursöverbelastning. Vid maximal belastning ökar köerna, minnestrycket ökar, anslutningspoolerna börjar mättas och återställningstiden efter incidenter ökar.
I följande tabell visas rekommenderade driftpunkter för olika användningsfall.
| Användningsfall | Målkapacitet | Logisk grund |
|---|---|---|
| Svarstidskänslig (sökning, chatt) | 50–60% av max | Prioritera låg P95/P99-svarstid |
| Balanserad (rekommendationer) | 60-70% av max | Bra balans mellan kostnader och svarstider |
| Kostnadsoptimerade batchjobb | 70-80% av max. | Acceptabel högre svarstid |
| Rekommenderas inte | > 85% av det maximala | Latensspikar, ingen burstkapacitet |
Hjälpfunktioner för att beräkna driftpunkts- och slutpunktsstorlek
Hitta den optimala punkten
Följande kod ritar QPS jämfört med P95-svarstid. I diagrammet letar du efter den punkt där kurvan börjar böjas kraftigt uppåt. Det här är den optimala driftpunkten.
import matplotlib.pyplot as plt
# Plot QPS vs. P95 latency
qps_values = [45, 88, 165, 310, 420, 480]
p95_latency = [120, 140, 180, 350, 800, 1500]
plt.plot(qps_values, p95_latency, marker='o')
plt.axvline(x=310, color='green', linestyle='--', label='Optimal (65% capacity)')
plt.axvline(x=480, color='red', linestyle='--', label='Maximum (100% capacity)')
plt.xlabel('Queries Per Second (QPS)')
plt.ylabel('P95 Latency (ms)')
plt.title('QPS vs. Latency: Finding the Sweet Spot')
plt.legend()
plt.grid(True)
plt.show()
Formel för storleksrekommendation
def calculate_endpoint_size(target_qps, optimal_capacity_percent=0.65):
"""
Calculate required endpoint capacity
Args:
target_qps: Your expected peak production QPS
optimal_capacity_percent: Target utilization (default 65%)
Returns:
Required maximum endpoint QPS
"""
required_max_qps = target_qps / optimal_capacity_percent
# Add 20% safety margin for unexpected bursts
recommended_max_qps = required_max_qps * 1.2
return {
"target_production_qps": target_qps,
"operate_at_capacity": f"{optimal_capacity_percent*100:.0f}%",
"required_max_qps": required_max_qps,
"recommended_max_qps": recommended_max_qps,
"burst_capacity": f"{(1 - optimal_capacity_percent)*100:.0f}% headroom"
}
# Example
result = calculate_endpoint_size(target_qps=200)
print(f"Target production QPS: {result['target_production_qps']}")
print(f"Size endpoint for: {result['recommended_max_qps']:.0f} QPS")
print(f"Operate at: {result['operate_at_capacity']}")
print(f"Available burst capacity: {result['burst_capacity']}")
# Output:
# Target production QPS: 200
# Size endpoint for: 369 QPS
# Operate at: 65%
# Available burst capacity: 35% headroom
Identifiera flaskhalsen för inbäddningsmodellen
Om ditt index använder hanterade inbäddningar samlar notebook-filen för belastningstestet in tidsinställningen per komponent via parametern debug_level=1 för varje fråga. Resultattabellen innehåller:
-
ann_time— Tid som ägnas åt ungefärlig sökning efter närmaste granne -
embedding_gen_time— tid som ägnas åt att generera frågeinbäddning på modellens serverdelsslutpunkt -
reranker_time— Tid som ägnas åt att ändra rangordning (om den är aktiverad) -
response_time— Total svarstid från slutpunkt till slutpunkt
Om embedding_gen_time är konsekvent stor i förhållande till ann_timeär inbäddningsslutpunkten flaskhalsen, inte slutpunkten för vektorsökning. Vanliga orsaker:
- Den inbäddningsmodell som betjänar slutpunkten har Skala till noll aktiverat. Inaktivera den för testning av produktionsbelastning. Se Undvik skalning till noll för produktion.
- Inbäddningsslutpunkten har inte tillräckligt med etablerad samtidighet för den frågefrekvens som du testar.
- Slutpunkten för inbäddningsmodellen delas med andra arbetsbelastningar. Använd en dedikerad slutpunkt för belastningstestning.
Tips/Råd
Om du vill isolera prestanda för vektorsökning från inbäddningsmodellprestanda växlar du till självhanterade inbäddningar för belastningstestning . Skicka förkomputerade vektorer i parametern EMBEDDING_COLUMN i stället för textfrågor. Detta tar bort svarstid för inbäddning från mätningen helt och hållet.
Steg 7: Ändra storlek på slutpunkten
Använd notebookens rekommendation
Efter att ha analyserat resultaten, uppmanar anteckningsboken dig att:
- Välj den rad som bäst uppfyller dina svarstidskrav.
- Ange programmets önskade RPS.
Anteckningsboken visar sedan en rekommenderad slutpunktsstorlek. Den beräknar den kapacitet som krävs baserat på följande:
- Målvärde för RPS
- Observerade svarstider på olika samtidighetsnivåer
- Tröskelvärden för framgångsfrekvens
- Säkerhetsmarginal (vanligtvis 2x förväntad toppbelastning)
Att tänka på vid skalning
Standardslutpunkter:
- Skala upp automatiskt för att stödja indexstorlek
- Skala upp manuellt för att stödja genomströmning
- Skala ned automatiskt när index tas bort
- Skala ned manuellt för att minska kapaciteten
Lagringsoptimerade slutpunkter:
- Skala upp automatiskt för att stödja indexstorlek
- Skala ned automatiskt när index tas bort
Steg 8: Verifiera slutlig konfiguration
När du har uppdaterat slutpunktskonfigurationen:
- Vänta tills slutpunkten är klar. Det kan ta flera minuter.
- Kör det slutliga valideringstestet i notebook-filen.
- Bekräfta att prestanda uppfyller dina krav:
- RPS ≥ målgenomströmning
- P95-svarstid uppfyller SLA
- Framgångsfrekvens > 99,5%
- Inga varaktiga fel
Om verifieringen misslyckas kan du prova följande:
- Öka slutpunktskapaciteten
- Optimera frågekomplexitet
- Granska filterprestanda
- Kontrollera konfigurationen av inbäddningsslutpunkt
När du ska testa igen
För att upprätthålla prestandasynlighet är det en bra idé att köra baslinjebelastningstester kvartalsvis. Du bör också testa igen när du gör någon av följande ändringar:
- Ändra frågemönster eller komplexitet
- Uppdatera vektorsökningsindexet
- Ändra filterkonfigurationer
- Förvänta dig betydande trafikökningar
- Distribuera nya funktioner eller optimeringar
- Ändra från standard till lagringsoptimerade slutpunktstyper
Felsökning
Alla begäranden misslyckas med ~10 ms svarstid och svar på 240 byte
Detta anger att tjänstens principalkonto tar emot ett 401/403-svar. Kontrollera:
- Tjänstens huvudnamn har Can Query-behörigheter på vektorsökningsslutpunkten (inte bara indexet).
- Hemlighetsomfånget innehåller giltiga
service_principal_client_idnycklar ochservice_principal_client_secretnycklar. - OAuth-hemligheten har inte upphört att gälla.
Notebook-filen innehåller en anslutningskontroll som fångar upp detta innan du kör full belastningstestet.
Köra flera belastningstestjobb i samma kluster
Om du kör två belastningstestjobb samtidigt i samma kluster kan ett jobb få inaktuella OAuth-token eller uppleva CPU-konkurrens med det andra jobbets Locust-arbetare. För tillförlitliga resultat kör du belastningstestjobb en i taget på ett dedikerat kluster.
Diagram för komponenttidsscheman är tomma
Komponentens tidsschemadiagram (ann_time, embedding_gen_time, reranker_time) kräver att slutpunkten returneras debug_info i frågesvar. Om dessa diagram är tomma:
- Kontrollera att du använder skriptet
fast_vs_load_test_async_load.py(som parsardebug_infofrån svar) somlocust_script_path. - Vissa slutpunktskonfigurationer kanske inte returnerar
debug_info. Självhanterade inbäddningsindex returnerarann_timevanligtvis ochresponse_timemen inteembedding_gen_timeellerreranker_time.
Resultattabellen kan inte frågas från ett SQL-lager
Notebook-filen skriver resultat från klustrets Spark-session. Om ett SQL-lager visar 0 rader för en tabell som notebook-filen rapporterar som ifylld, kan problemet vara en fördröjning av synkroniseringen av Unity Catalog-metadata. Vänta några minuter och försök igen, eller fråga tabellen direkt från en notebook-fil som är kopplad till samma kluster.
Sammanfattning av metodtips
Testkonfiguration
Kör tester i minst 5 minuter vid hög belastning.
Använd OAuth-tjänstehuvuden för autentisering.
Skapa realistiska frågenyttolaster som matchar förväntade produktionsfrågor.
Testa med produktionsliknande filter och parametrar.
Inkludera en uppvärmningsperiod innan du mäter.
Testa på flera samtidighetsnivåer.
Spåra P95/P99-svarstider, inte bara medelvärden.
Testa både cachelagrade och ej cachelagrade prestanda.
# Conservative approach: Size endpoint for UNCACHED performance uncached_results = run_load_test(diverse_queries, duration=600) endpoint_size = calculate_capacity(uncached_results, target_rps=500) # Then verify cached performance is even better cached_results = run_load_test(repetitive_queries, duration=300) print(f"Cached P95: {cached_results['p95']}ms (bonus performance)")
Frågeuppsättningsdesign
- Matcha din testfrågas mångfald med verklig trafikdistribution (frekventa och sällsynta frågor).
- Använd faktiska frågor från loggar (anonymiserade).
- Inkludera olika frågekomplexiteter.
- Testa både cachelagrade och ej åtkomliga scenarier och spåra resultaten separat.
- Testa med förväntade filterkombinationer.
- Använd samma parametrar som du kommer att använda i produktion. Om du till exempel använder hybridsökning i produktion kan du inkludera hybridsökningsfrågor. Använd en liknande
num_resultsparameter som i produktion. - Använd inte frågor som aldrig inträffar i produktion.
Prestandaoptimering
Om svarstiderna är för höga kan du prova följande:
- Använda OAuth-tjänstens huvudnamn (inte PAT) – förbättring på 100 ms
- Minska
num_results– Hämtningen av 100 resultat är långsammare än 10 - Optimera filter – Komplexa eller alltför restriktiva filter gör frågor långsammare
- Kontrollera inbäddningsslutpunkten – Kontrollera att den inte skalas till noll eller har tillräckligt med bandbredd
Om du når hastighetsgränserna kan du prova följande:
- Öka slutpunktskapaciteten – Skala upp slutpunkten
- Implementera begränsning av förfrågningshastighet eller sprid ut förfrågningar över tid på klientsidan.
- Använda anslutningspooler – Återanvända anslutningar
- Lägg till logik för återförsök – Använd exponentiell backoff (redan en del av Python SDK)