Configurar um teste de carga para endpoints de Pesquisa de AI
Esta página fornece orientações, código de exemplo e um Notebook de exemplo para teste de carga de endpoint do AI Search. O teste de carga ajuda a entender o desempenho e a prontidão de produção de um endpoint de pesquisa de IA antes de ser implantado na produção. O teste de carga pode informar sobre:
- Latência em diferentes níveis de dimensionamento
- Limites e gargalos de taxa de transferência (solicitações por segundo, detalhamento da latência)
- Taxas de erro sob carga sustentada
- Utilização de recursos e planejamento de capacidade
Para obter mais informações sobre testes de carga e conceitos relacionados, consulte Testes de carga para endpoints de serviço.
Requisitos
Antes de iniciar estes passos, você deve ter um endpoint de Pesquisa de AI implantado e uma entidade de serviço com permissões de Pode Consultar no endpoint. Consulte o passo 1: Configurar a autenticação da entidade de serviço.
Baixe e importe uma cópia dos arquivos a seguir e do Notebook de exemplo para o seu workspace do Databricks:
- input.json. Este é um exemplo do arquivo
input.jsonque especifica o payload enviado por todas as conexões concorrentes para seu endpoint. É possível ter vários arquivos, se necessário. Se você usar o Notebook de exemplo, este arquivo é gerado automaticamente a partir da tabela de entrada fornecida. - fast_vs_load_test_async_load.py. Faça upload deste script para o seu workspace (por exemplo,
/Workspace/Users/<your-username>/fast_vs_load_test_async_load.py) e defina o parâmetro do notebooklocust_script_pathpara o caminho dele. Este script lida com autenticação, entrega de carga útil e coleta de métricas de depuração. - O seguinte notebook de exemplo, que executa os testes de carga. Para obter o melhor desempenho, execute este Notebook em um cluster de nó único com um grande número de núcleos (o Locust é dimensionado para todas as CPUs disponíveis). É recomendada alta memória para consultas com incorporações pré-geradas.
Exemplo de notebook e início rápido
Utilize o seguinte Notebook de exemplo para começar. Ele oferece dois modos de exploração: uma varredura gradual que testa níveis específicos de concorrência que você define, e um modo de pesquisa binária que encontra automaticamente o QPS sustentável máximo (ponto de interrupção) em poucos passos. Todos os parâmetros são configurados usando widgets, de modo que o Notebook pode ser executado interativamente ou como um Job do Databricks sem edições de código.
Notebook de teste de carga Locust
Estrutura de teste de carga: Locust
Locust é um framework de teste de carga de código aberto que permite que você faça o seguinte:
- Variar o número de conexões de cliente concorrentes
- Controle a velocidade com que as conexões são estabelecidas
- Meça o desempenho do endpoint durante o teste
- Detectar automaticamente e usar todos os núcleos de CPU disponíveis
O exemplo de notebook usa o sinalizador --processes -1 para detectar automaticamente os núcleos da CPU e utilizá-los completamente.
Se o Locust estiver com gargalo na CPU, uma mensagem é exibida na saída.
o passo 1: configurar a autenticação da entidade de serviço
Para testes de desempenho em ambiente de produção, sempre use a autenticação de entidade de serviço OAuth. Entidades de serviço oferecem um tempo de resposta até 100 ms mais rápido e limites de taxa de solicitação mais altos em comparação com tokens de acesso pessoal (PATs).
Criar e configurar entidade de serviço
-
Crie uma entidade de serviço do Databricks. Para obter instruções, consulte Adicionar entidades de serviço à sua account.
-
Conceder permissões:
- Navegue para a página do endpoint de Pesquisa de IA.
- Clique em Permissões .
- Conceda à entidade de serviço as permissões Pode Consultar .
-
Criar segredo de OAuth.
- Ir para a página de detalhes da entidade de serviço
- Clique na guia Segredos .
- Clique em Gerar segredo .
- Defina a vida útil (recomenda-se 365 dias para testes de longo prazo).
- Copie a ID do cliente e o Segredo imediatamente.
-
Armazene as credenciais com segurança.
- Crie um Secret Scope do Databricks. Para obter instruções, consulte Tutorial: criar e usar um segredo do Databricks.
- Conforme mostrado no exemplo de código a seguir, armazene o ID do cliente da entidade de serviço como
service_principal_client_ide o segredo OAuth comoservice_principal_client_secret.
Python# 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>")
Passo 2: Configurar o teste de carga
Configuração de Notebook
Configure os parâmetros do Notebook usando os widgets no topo do Notebook. Ao executar o Notebook como um Job do Databricks, passar estes valores como parâmetros do Job. Não são necessárias edições de código.
Parâmetro | Descrição | Valor Recomendado |
|---|---|---|
| Nome do seu endpoint de Pesquisa de AI | Nome do endpoint |
| Nome completo do índice ( | Nome do índice |
| Tabela de origem para consultas de exemplo ( | Sua tabela de entrada do índice |
| Coluna de texto para incorporações gerenciadas | Deixe como |
| Coluna que contém incorporações vetoriais pré-computadas. Somente usado para incorporações autogerenciadas. | Deixe em branco para incorporações gerenciadas. |
| Número de queries a serem amostradas para o teste |
|
| Lista delimitada por vírgulas de contagens de clientes concorrentes para teste |
|
| Duração em segundos por nível de simultaneidade. Um valor se aplica a todos os níveis, ou forneça um por nível como uma lista separada por vírgulas. |
|
| Nome do seu Secret Scope do Databricks | Nome do Secret Scope |
| Caminho do workspace para o script |
|
| (Opcional) Tabela Delta para armazenar resultados em ( |
|
| Nome ou comentário para tag esta execução para análise posterior | Um rótulo descritivo |
|
|
|
| ( |
|
| ( |
|
| ( |
|
| Número de resultados a serem retornados por consulta |
|
| Lista de colunas separadas por vírgulas a serem retornadas nos resultados da consulta (por exemplo, | Deixe em branco para o padrão |
Incorporações gerenciadas versus autogerenciadas
O notebook suporta tanto incorporações gerenciadas (onde o Databricks gera incorporações no momento da consulta) quanto incorporações autogerenciadas (onde os vetores pré-computados são passados diretamente). Configurar os parâmetros adequados com base no tipo de índice.
Tipo de índice | Parâmetro a ser definido | Deixar desmarcado |
|---|---|---|
Incorporações gerenciadas (índice de sincronização Delta com modelo de incorporação gerenciado pelo Databricks) |
|
|
Incorporações autogerenciadas (Sincronização Delta ou índice de Acesso Direto ao Vetor com vetores pré-computados) |
|
|
Para índices de incorporações gerenciadas, o teste de carga mede a latência de ponta a ponta, incluindo o tempo de geração de incorporação. Se o seu endpoint de incorporação for dimensionado para zero, a sobrecarga de inicialização a frio será observada na primeira execução de teste. Consulte Identificar o gargalo do modelo de incorporação para isolar a latência de incorporação da latência de pesquisa.
Por que 5–10 minutos?
Uma duração mínima de teste de 5 minutos é fundamental.
- As consultas iniciais podem incluir sobrecarga de inicialização a frio.
- Os endpoints precisam de tempo para atingir o desempenho em estado estável.
- O escalonamento automático dos endpoints de servindo modelo (se ativado) leva tempo para ser ativado.
- Testes curtos não detectam comportamentos de limitação sob carga sustentada.
A tabela a seguir mostra as durações de teste recomendadas dependendo do seu objetivo de teste.
Tipo de teste | Duração do teste | Objetivos do teste |
|---|---|---|
Teste de fumaça rápido | 2–3 minutos | Verificar a funcionalidade básica |
Linha de base de desempenho | 5–10 minutos | Métricas confiáveis de estado estacionário |
Teste de estresse | 15–30 minutos | Identificar o esgotamento de recursos |
Teste de resistência | 1–4 horas | Degradação, estabilidade da latência |
Exploração de ponto de interrupção (modo de busca binária)
Além da varredura gradual (exploration_mode=gradual), o Notebook suporta um modo automático de pesquisa binária que localiza o QPS sustentável máximo sem a necessidade de especificar manualmente os níveis de concorrência.
Como funciona
Defina exploration_mode=binary_search e especifique max_target_qps (por exemplo, 500). O notebook usa Little's Law (concurrency = QPS × avg_latency_sec) para converter cada destino QPS em um nível de concorrência estimado e, em seguida, executa uma pesquisa binária da seguinte forma:
- Comece em
max_target_qps / 2(250 no exemplo). - Se a taxa de erro estiver abaixo de
error_rate_threshold(sucesso), deve-se aumentar o limite inferior e tentar um QPS maior (375, depois 500, e assim por diante). - Se a taxa de erro exceder o limite (falha), diminua o limite superior e tente a meio caminho entre o último sucesso e a falha.
- Repita por até
exploration_stepspassos (default 8) ou até que o intervalo de pesquisa se reduza a 5% demax_target_qps.
A tabela a seguir mostra como a pesquisa converge para um endpoint hipotético com um ponto de interrupção em torno de 430 QPS:
Passo | QPS alvo | Taxa de erros | Resultado | Novo intervalo |
|---|---|---|---|---|
1 | 250 | 0,1% | Sucesso | 250–500 |
2 | 375 | 0,3% | Sucesso | [375, 500] |
3 | 437 | 4,5% | Falha | [375, 437] |
4 | 406 | 0,8% | Sucesso | [406, 437] |
5 | 421 | 2,1% | Falha | 406–421 |
Após 5–8 passos a busca converge no ponto de ruptura — neste exemplo, aproximadamente 406–421 QPS — com muito menos execuções de teste do que uma varredura exaustiva.
Quando usar cada modo
Mode | Quando usar |
|---|---|
| Você já conhece o intervalo operacional esperado e deseja caracterizar o desempenho em níveis de concorrência específicos. |
| É desejável encontrar o QPS sustentável máximo rapidamente, sem saber os níveis de concorrência antecipadamente. |
O passo 3: Projetar o conjunto de consultas
Quando possível, o conjunto de consultas deve refletir o tráfego de produção esperado o mais próximo possível. Especificamente, é preciso procurar corresponder à distribuição esperada das consultas em termos de conteúdo, complexidade e diversidade.
-
Usar consultas realistas. Não use texto aleatório, como "test query 1234".
-
Corresponda à distribuição de tráfego de produção esperada. Se você espera 80% de consultas comuns, 15% de consultas de frequência média e 5% de consultas infrequentes, seu conjunto de consultas deve refletir essa distribuição.
-
Garanta que o tipo de consulta corresponda ao que se espera ver em produção. Por exemplo, se você espera que as consultas de produção usem pesquisa híbrida ou filtros, você também deve usá-los no seu conjunto de consultas.
Exemplo de consulta com filtros:
JSON{
"query_text": "wireless headphones",
"num_results": 10,
"filters": { "brand": "Sony", "noise_canceling": true }
}Exemplo de query usando busca híbrida:
JSON{
"query_text": "best noise canceling headphones for travel",
"query_type": "hybrid",
"num_results": 10
}
Diversidade de query e cache
Os Endpoints de Pesquisa de AI armazenam em cache vários tipos de resultados de consulta para melhorar o desempenho. Este armazenamento em cache pode afetar os resultados dos testes de carga. Por este motivo, é importante prestar atenção à diversidade do conjunto de queries. Por exemplo, se o mesmo conjunto de queries for enviado repetidamente, testa-se o cache, não o desempenho real da pesquisa.
Uso: | Quando: | Exemplo |
|---|---|---|
Consultas idênticas ou poucas |
| Um widget de recomendação de produtos que exibe "itens em alta" — a mesma consulta é executada milhares de vezes por hora. |
Consultas diversas |
| Uma pesquisa de e-commerce onde cada usuário digita diferentes pesquisas de produtos. |
Para recomendações adicionais, consulte Resumo das melhores práticas.
Opções para criar um conjunto de consultas
As tabs de código exibem três opções para criar um conjunto diversificado de consultas. Não existe uma solução única para todos. Opte pelo que melhor lhe convier.
- (Recomendado) Amostragem aleatória da tabela de entrada do índice. Este é um bom ponto de partida geral.
- Amostragem a partir de logs de produção. Este é um bom começo se você tiver logs de produção. Tenha em mente que as consultas geralmente mudam com o tempo, portanto, atualize o conjunto de testes regularmente para mantê-lo atualizado.
- Gerando queries sintéticas. Isto é útil se não houver logs de produção ou se forem utilizados filtros complexos.
- Random sampling from input table
- Sample from production logs
- Synthetic queries
O código a seguir extrai consultas aleatórias da sua tabela de entrada de índice.
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")
Os seguintes exemplos de código são extraídos proporcionalmente de consultas de produção.
# 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)
Se você não tem logs de produção ainda, você pode gerar queries sintéticas diversas.
# 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")
Passo 4. Teste seu payload
Antes de executar o teste de carga completo, valide a sua carga útil:
- No workspace do Databricks, navegue para o seu endpoint de Pesquisa de IA.
- Na barra lateral esquerda, clique em Disponibilização .
- Selecione o endpoint.
- Clique em Use → Query .
- Cole o conteúdo de
input.jsonna caixa de consulta. - Verifique se o endpoint retorna os resultados esperados.
Isso garante que o seu teste de carga medirá consultas realistas, e não respostas de erro.
Passo 5: execução do teste de carga
Verificação da conectividade e aquecimento
Antes do teste de carga começar, o Notebook executa duas os passos de configuração:
-
Verificação de conectividade : envia uma única consulta de sondagem usando as credenciais da entidade de serviço. Se o endpoint retornar um erro 401 ou 403, o Notebook falha imediatamente com um
PermissionErrorclaro, em vez de executar um teste de carga completo que produz apenas dados de erro. Isso economiza tempo quando as credenciais ou permissões estão configuradas incorretamente. -
Teste de aquecimento (1 minuto): Executa um teste curto de baixa simultaneidade que aquece os caches do endpoint e valida o fluxo de requisição de ponta a ponta. Os resultados do aquecimento não são utilizados para métricas de desempenho. No modo de busca binária, a latência de inicialização também é utilizada como a linha de base para a estimativa de simultaneidade da Lei de Little.
Série principal de teste de carga
O Notebook executa uma série de testes com concorrência de cliente crescente:
- Começar: baixa simultaneidade (por exemplo, 5 clientes concorrentes)
- Médio: concorrência média (por exemplo, 10, 20 ou 50 clientes)
- Fim: alta simultaneidade (por exemplo, mais de 100 clientes)
Cada teste tem a duração configurada em step_duration_seconds (5 a 10 minutos recomendados).
O que o Notebook mede
O Notebook mede e relata o seguinte:
Métricas de latência:
- P50 (mediana): Metade das consultas é mais rápida que este valor.
- P95: 95% das consultas são mais rápidas do que isso. Esta é uma métrica SLA chave.
- P99: 99% das consultas são mais rápidas que isso.
- Máx: latência de pior caso.
Métricas de taxa de transferência:
- RPS (solicitações por segundo): queries bem-sucedidas por segundo.
- Total de queries: número de queries concluídas.
- Taxa de sucesso: Porcentagem de consultas bem-sucedidas.
Erros:
- Falhas de consulta por tipo
- Mensagens de exceção
- Contagens de tempo esgotado
Armazenamento de resultados
Se o output_table parâmetro for definido, o notebook armazena uma linha por nível de concorrência (ou por passo de pesquisa binária) em uma tabela Delta do Unity Catalog. A tabela é criada automaticamente na primeira execução e anexada nas execuções subsequentes. Cada linha inclui run_name, exploration_mode, concorrência, taxas de sucesso/falha, percentis de latência, RPS e campos específicos de busca binária (bs_step, bs_target_qps, bs_outcome). Isso permite comparar execuções ao longo do tempo com ferramentas SQL ou de BI.
Executando como um job do Databricks
Todos os parâmetros de notebook são definidos como dbutils.widgets, que mapeiam diretamente para os parâmetros de Job do Databricks. Para programar ou automatizar testes de carga:
- Crie um job com o Notebook como a tarefa.
- Defina os valores do widget como parâmetros do Job. Não são necessárias edições de código.
- Anexe o Job a um cluster de nó único com muitos núcleos de CPU (Locust se beneficia de workers paralelos).
- Execute sob demanda ou em uma programação para testes de referência recorrentes.
Passo 6: Interpretar resultados
A tabela a seguir mostra as metas para um bom desempenho:
Métrica | Destino | Comentário |
|---|---|---|
Latência P95 | < 500ms | A maioria das consultas são rápidas |
Latência P99 | < 1s | Desempenho razoável em consultas de cauda longa |
Taxa de sucesso | > 99,5% | Baixa taxa de falha |
Latência ao longo do tempo | Estável | Nenhuma degradação observada durante o teste |
Queries por segundo | Atende à meta | O endpoint pode lidar com o tráfego esperado |
Os resultados a seguir indicam mau desempenho:
- P95 > 1s. Indica que as consultas são muito lentas para uso em tempo real.
- P99 > 3s. A latência em queries de cauda longa prejudicará a experiência do usuário.
- Taxa de sucesso < 99%. Fracassos em excesso.
- Aumento da latência. Indica esgotamento de recursos ou vazamento de memória.
- Erros de limitação de taxa (429). Indica que é necessária maior capacidade de endpoint.
Compensação entre RPS e latência
O RPS máximo não é o ponto ideal para a taxa de transferência de produção. A latência aumenta de forma não linear à medida que você se aproxima da Taxa de transferência máxima. Operar com RPS máximo frequentemente resulta em uma latência 2–5 vezes maior em comparação com a operação em 60–70% da capacidade máxima.
O exemplo a seguir mostra como analisar os resultados para encontrar o ponto de operação ideal.
- O RPS máximo é de 480 com 150 clientes concorrentes.
- O ponto operacional ideal é 310 RPS com 50 clientes concorrentes (65% da capacidade).
- A penalidade de latência máxima: P95 é 4,3 vezes maior (1,5s vs. 350ms)
- Neste exemplo, a recomendação é dimensionar o endpoint para uma capacidade de 480 RPS e operar em aproximadamente 310 RPS.
Concorrência | P50 | P95 | P99 | RPS | Sucesso | Capacidade |
|---|---|---|---|---|---|---|
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% ← Ponto ideal |
100 | 250 ms | 800 ms | 1,2s | 420 | 97,5% | 90% ⚠️ Aproximando Máx |
150 | 450 ms | 1,5s | 2,5s | 480 | 95,0% | 100% ❌ Máximo RPS |
Operar no RPS máximo pode levar aos seguintes problemas:
- Degradação da latência. No exemplo, P95 é 350 ms a 65% de capacidade, mas é 1,5 s a 100% de capacidade.
- Não há espaço para acomodar picos de tráfego. Com 100% de capacidade, qualquer pico causa um tempo esgotado. Com 65% de capacidade, um pico de 50% no tráfego pode ser suportado sem problemas.
- Taxas de erro aumentadas. No exemplo, a taxa de sucesso é de 99,2% com 65% da capacidade, mas de 95,0% — uma taxa de falha de 5% — com 100% da capacidade.
- Risco de esgotamento de recurso. Na carga máxima, as filas aumentam, a pressão da memória aumenta, os pools de conexão começam a saturar e o tempo de recuperação após incidentes aumenta.
A tabela a seguir mostra os pontos de operação recomendados para diferentes casos de uso.
Caso de uso | Capacidade alvo | Justificativa |
|---|---|---|
Sensível à latência (pesquisa, chat) | 50–60% do Máx. | Priorize a baixa latência P95/P99. |
Equilibradas (recomendações) | 60–70% do máximo | Bom equilíbrio entre custo e latência |
Custo otimizado (trabalhos em lote) | 70–80% de Máx | Maior latência aceitável |
Não recomendado | > 85% de máx. | Picos de latência, sem capacidade de pico |
Funções auxiliares para calcular o ponto de operação e o tamanho do endpoint
- Find the optimal point
- Size recommendation formula
O seguinte código grafica QPS vs. latência P95. No gráfico, identifique o ponto onde a curva começa a subir acentuadamente para cima. Este é o ponto ideal de operação.
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()
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
Identifique o gargalo do modelo de incorporação
Se o seu índice usar incorporações gerenciadas, o Notebook de teste de carga captura o tempo por componente através do parâmetro debug_level=1 em cada consulta. A tabela de resultados inclui:
ann_time— Tempo gasto em busca aproximada de vizinho mais próximoembedding_gen_time— tempo gasto gerando o embedding da consulta no endpoint de servindo modeloreranker_time— tempo gasto na reclassificação (se habilitado)response_time— o tempo total de resposta de ponta a ponta
Se embedding_gen_time for consistentemente grande em relação a ann_time, o endpoint de incorporação é o gargalo, e não o endpoint de Pesquisa de AI. Causas comuns:
- O endpoint de disponibilização de modelos de incorporação tem **Escala para zero** ativada. Desativar para teste de carga em produção. Ver Evitar a escala para zero para produção.
- O endpoint de inserção não tem concorrência provisionada suficiente para a taxa de consulta que está sendo testada.
- O endpoint de modelo de incorporação é compartilhado com outras cargas de trabalho. Utilize um endpoint dedicado para testes de carga.
Para isolar o desempenho da Pesquisa de AI do desempenho do modelo de incorporação, mude para **incorporações autogerenciadas** para teste de carga. Passe vetores pré-computados no parâmetro EMBEDDING_COLUMN em vez de consultas de texto. Isso elimina completamente a latência de incorporação da medição.
Passo 7: dimensionar seu endpoint
Utilize a recomendação do Notebook
Após analisar os resultados, o Notebook pede para:
- Selecione a linha que melhor atenda aos seus requisitos de latência.
- Introduza o RPS desejado da sua aplicação.
Em seguida, o Notebook exibe um tamanho de endpoint recomendado. Calcula a capacidade necessária com base no seguinte:
- Seu RPS de destino
- Latência observada em diferentes níveis de simultaneidade
- Limites da taxa de sucesso
- Margem de segurança (normalmente o dobro da carga de pico esperada)
Considerações de escalonamento
Endpoints padrão:
- Dimensiona automaticamente para suportar o tamanho do índice
- Dimensionar manualmente para suportar a taxa de transferência
- Escalar automaticamente para baixo quando os índices são excluídos.
- Reduza a escala manualmente para reduzir a capacidade.
Endpoints otimizados para armazenamento:
- Dimensiona automaticamente para suportar o tamanho do índice
- Escalar automaticamente para baixo quando os índices são excluídos.
Etapa 8: Validar configuração final
Após a atualização da configuração do seu endpoint:
- Aguardando o endpoint ficar pronto. Esse processo pode levar vários minutos.
- Execute o teste de validação final no Notebook.
- Confirme se o desempenho atende aos seus requisitos:
- RPS maior ou igual à meta de taxa de transferência
- Latência P95 atende ao SLA
- Taxa de sucesso > 99,5%
- Sem erros persistentes
Se a validação falhar, experimente o seguinte:
- Aumentar a capacidade do endpoint
- Otimizar a complexidade da query
- Revisar desempenho do filtro
- Verificar a configuração do endpoint de incorporação
Quando testar novamente
Para manter a visibilidade do desempenho, é uma boa ideia executar testes de carga de referência trimestralmente. Também é recomendável retestar quando forem feitas quaisquer das seguintes alterações:
- Alterar padrões de consulta ou complexidade
- Atualizar o Índice de Pesquisa de IA
- Modificar configurações de filtro
- Espere aumentos significativos de tráfego
- Implantar novos recursos ou otimizações
- Alterar os tipos de endpoint de padrão para otimizados para armazenamento
Solução de problemas
Todas as solicitações falham com cerca de 10 ms de latência e respostas de 240 bytes
Isso indica que a entidade de serviço está recebendo uma resposta 401/403. Verificar:
- A entidade de serviço tem permissões de Can Query no endpoint de Pesquisa de AI (não apenas o índice).
- O Secret Scope contém
service_principal_client_ideservice_principal_client_secretchaves válidas. - O segredo de OAuth não expirou.
O Notebook inclui uma verificação de conectividade que detecta isso antes de executar o teste de carga completo.
Execução de múltiplos jobs de teste de carga no mesmo cluster
Caso sejam executados dois jobs de teste de carga simultaneamente no mesmo cluster, um job poderá receber tokens OAuth desatualizados ou apresentar contenção de CPU com os workers Locust do outro job. Para resultados confiáveis, execute jobs de teste de carga um por vez em um cluster dedicado.
Os gráficos de tempos de componente estão vazios
Os gráficos de temporização do componente (ann_time, embedding_gen_time, reranker_time) exigem que o endpoint retorne debug_info em respostas de consulta. Se esses gráficos estiverem vazios:
- Verifique se você está usando o script
fast_vs_load_test_async_load.py(que analisadebug_infodas respostas) como olocust_script_path. - Algumas configurações de endpoint podem não retornar
debug_info. Índices de incorporação autogerenciados normalmente retornamann_timeeresponse_time, mas nãoembedding_gen_timeoureranker_time.
Tabela de resultados não pode ser consultada de um SQL warehouse
O Notebook grava resultados da sessão Spark do cluster. Se um SQL warehouse apresentar 0 linhas para uma tabela que o notebook relata como preenchida, o problema pode ser um atraso na sincronização de metadados do Unity Catalog. Aguarde alguns minutos e tente novamente, ou consulte a tabela diretamente de um notebook anexado ao mesmo cluster.
Resumo das melhores práticas
Teste de configuração
-
Executar testes por pelo menos 5 minutos com carga máxima.
-
Use OAuth para entidades de serviço para autenticação.
-
Criar cargas de consulta realistas que correspondam às consultas de produção esperadas.
-
Testar com filtros e parâmetros semelhantes aos de produção.
-
Incluir um período de aquecimento antes de medir.
-
Teste em múltiplos níveis de concorrência.
-
Monitore as latências P95/P99, não apenas as médias.
-
Testar o desempenho com e sem cache.
Python# 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)")
Design do conjunto de query
- Faça com que a diversidade da sua consulta de teste corresponda à distribuição real do tráfego (consultas frequentes e raras).
- Usar consultas reais de logs (anonimizadas).
- Incluir queries com diferentes complexidades.
- Teste os cenários com e sem cache e acompanhe os resultados separadamente.
- Teste com combinações de filtros esperadas.
- Use os mesmos parâmetros que serão usados na produção. Por exemplo, caso a pesquisa híbrida seja utilizada em produção, é necessário incluir consultas de pesquisa híbrida. Use um parâmetro similar
num_resultscomo em produção. - Não devem ser utilizadas queries que nunca ocorrerão em produção.
Otimização do desempenho
Se as latências estiverem muito altas, sugerimos o seguinte:
- Utilize entidades de serviço OAuth (não PATs) - 100 ms de melhoria
- Reduzir
num_results- Obter 100 resultados é mais lento do que 10 - Otimizar filtros - Filtros complexos ou excessivamente restritivos retardam as consultas
- Verifique o endpoint de incorporação: garanta que não esteja dimensionado para zero ou tenha largura de banda suficiente.
Caso esteja atingindo os limites de taxa, proceda da seguinte forma:
- Aumentar a capacidade do endpoint - Escalar o seu endpoint
- Implemente limitação de taxa no lado do cliente ou distribua consultas ao longo do tempo
- Utilize o pooling de conexões: reutilize as conexões
- Adicionar lógica de repetição — Usar backoff exponencial (já faz parte do Python SDK)