Reuso e agrupamento de conexões.
Reuso de conexão HTTP e conexão WebSocket juntando para cargas de trabalho de alta concorrência.
Reutilizar conexões reduz o consumo de recursos e melhora a produtividade. A estratégia depende do protocolo:
- ** APIs HTTP** (geração de texto, multimodal, incorporações): reutilizar conexões TCP via configuração de conjunto de conexão (Java) ou objetos de sessão (Python).
- ** WebSocket APIs** (TTS, fala em tempo real): objetos sintetizadores de piscina que possuem conexões WebSocket de longa duração.
Pré-requisitos
- Obter e configurar sua API Key como o
DASHSCOPE_API_KEYVariável ambiente. - Instale o mais recente DashScope SDK:
- Python SDK >= 1,25.2
- *Java SDK: >= 2,16.6
Reutilização de conexão HTTP
O ponto final do DashScope difere pelo tipo de modelo:
- ** Modelos de texto** (
qwen-plus,qwen-max, etc.): Use oGenerationclasse, que rotas para/services/aigc/text-generation/generation. - Modelos Multimodal
qwen3.7-plus,qwen3-vl-plus, etc.): Use oMultiModalConversationclasse, que rotas para/services/aigc/multimodal-generation/generation.
Java SDK
A conexão está ativada por padrão. Ajuste os seguintes parâmetros conforme necessário.
- Parâmetro Descrição *
| ----------------------------- | ----------------------------------------------------------------------------- | ------- | -------- | ------------------------------------------------------------------------- |
|
connectTimeoutTempo limite para estabelecer uma conexão. 120 segundos. Tempo limite mais curto reduz o tempo de espera em cenários de baixa latência. |readTimeoutTempo limite para ler dados. |writeTimeoutTempo limite para escrever dados. |connectionIdleTimeoutTempo limite para conexões ociosas. 300 segundos Tempo limite mais longo evitam religações frequentes sob alta concorrência. |connectionPoolSizeO máximo de conexões na piscina. 32 itens. Poucas conexões causam bloqueio. Muitas aumentam a carga do servidor. |maximumAsyncRequests..Requisitos simultâneos máximos em todos os hospedeiros. Deve ser o ≤connectionPoolSize32 pedidos |maximumAsyncRequestsPerHost.. Máximo de pedidos simultâneos por host. Deve ser o ≤maximumAsyncRequests32 itens
Configure parâmetros de conexão e chame um serviço de modelo:
// Recommended DashScope SDK version >= 2.12.0
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.protocol.ConnectionConfigurations;
import com.alibaba.dashscope.protocol.Protocol;
import com.alibaba.dashscope.utils.Constants;
public class Main {
public static MultiModalConversationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
MultiModalConversation conv = new MultiModalConversation(Protocol.HTTP.getValue(), "https://maas.qwencloudapi.com/api/v1");
Map<String, Object> textContent = new HashMap<>();
textContent.put("text", "Who are you?");
MultiModalMessage userMsg = MultiModalMessage.builder()
.role(Role.USER.getValue())
.content(Collections.singletonList(textContent))
.build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// If you have not configured the environment variable, replace with your API key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen3.7-plus")
.messages(Collections.singletonList(userMsg))
.build();
return conv.call(param);
}
public static void main(String[] args) {
// Connection pool configuration
Constants.connectionConfigurations = ConnectionConfigurations.builder()
.connectTimeout(Duration.ofSeconds(10)) // Timeout for establishing a connection, default 120s
.readTimeout(Duration.ofSeconds(300)) // Timeout for reading data, default 300s
.writeTimeout(Duration.ofSeconds(60)) // Timeout for writing data, default 60s
.connectionIdleTimeout(Duration.ofSeconds(300)) // Timeout for idle connections, default 300s
.connectionPoolSize(256) // Maximum connections in the connection pool, default 32
.maximumAsyncRequests(256) // Maximum concurrent requests, default 32
.maximumAsyncRequestsPerHost(256) // Maximum concurrent requests per host, default 32
.build();
try {
MultiModalConversationResult result = callWithMessage();
System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text"));
} catch (ApiException | NoApiKeyException | InputRequiredException e) {
System.err.println("An error occurred while calling the service: " + e.getMessage());
}
System.exit(0);
}
}
Python SDK
O Python SDK suporta o reuso da conexão através de uma sessão personalizada. Dois métodos estão disponíveis:#async-aiohttpE [sincronia:#sync-requests-session).
Async (aiohttp)
Use aiohttp.ClientSession com aiohttp.TCPConnector para a conexão de sincronização reutilizada.
- Parâmetro Descrição *
| ---------------- | ------------------------- | ------------- | ------------------------------------------------- |
|
limitLimite total de conexão 100 Valores mais altos melhoram a concorrência. |limit_per_hostLimite de conexão por hospede Previne carga excessiva em um único hospede. |sslConfiguração de contexto SSL Nenhuma validação de certificado SSL para conexões HTTPS
import asyncio
import aiohttp
import ssl
import certifi
from dashscope import AioMultiModalConversation
import dashscope
import os
async def main():
dashscope.base_http_api_url = 'https://maas.qwencloudapi.com/api/v1'
# If you have not configured the environment variable, replace with your API key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
# Configure connection parameters
connector = aiohttp.TCPConnector(
limit=100, # Total connection limit
limit_per_host=30, # Connection limit per host
ssl=ssl.create_default_context(cafile=certifi.where()),
)
# Create a custom Session and pass it to the call method
async with aiohttp.ClientSession(connector=connector) as session:
response = await AioMultiModalConversation.call(
model='qwen3.7-plus',
messages=[{'role': 'user', 'content': [{'text': 'Hello, please introduce yourself'}]}],
session=session, # Pass the custom Session
)
print(response)
asyncio.run(main())
Sincronia:
Use requests.Session para a conexão de sincronização reutilizada. Pedidos dentro da mesma sessão reutilizam a conexão TCP.
import requests
from dashscope import MultiModalConversation
import dashscope
import os
dashscope.base_http_api_url = 'https://maas.qwencloudapi.com/api/v1'
# If you have not configured the environment variable, replace with your API key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
# Use a with statement to ensure the Session closes correctly
with requests.Session() as session:
response = MultiModalConversation.call(
model='qwen3.7-plus',
messages=[{'role': 'user', 'content': [{'text': 'Hello'}]}],
session=session # Pass the custom Session
)
print(response)
Reutilize a mesma sessão em várias chamadas:
import requests
from dashscope import MultiModalConversation
import dashscope
import os
dashscope.base_http_api_url = 'https://maas.qwencloudapi.com/api/v1'
# If you have not configured the environment variable, replace with your API key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
# Create a Session object
session = requests.Session()
try:
# Reuse the same Session for multiple calls
response1 = MultiModalConversation.call(
model='qwen3.7-plus',
messages=[{'role': 'user', 'content': [{'text': 'Hello'}]}],
session=session
)
print(response1)
response2 = MultiModalConversation.call(
model='qwen3.7-plus',
messages=[{'role': 'user', 'content': [{'text': 'Introduce yourself'}]}],
session=session
)
print(response2)
finally:
# Ensure the Session closes correctly
session.close()
Conexão WebSocket em conjunto
Serviços TTS usam conexões WebSocket para streaming em tempo real. Na produção, criar uma nova conexão por solicitação desperdiça recursos e aumenta a latência. Esta seção cobre conexão, agrupamento de objetos e gerenciamento de pedidos simultâneos para cargas de trabalho TTS de alta produtividade.
Bloqueio de objetos
O Python SDK fornece SpeechSynthesizerObjectPool para gerenciar e reutilizar SpeechSynthesizer - Sim. - Sim. A piscina pré-cria objetos e estabelece conexões WebSocket na inicialização, eliminando conexão por solicitação.
- Copo-sizing - conjunto
max_sizePara 1,5x-2x sua concorrência máxima. Não exceda o limite de QPS da sua conta.
import os
import threading
import dashscope
from dashscope.audio.tts_v2 import *
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
dashscope.base_websocket_api_url = 'wss://maas.qwencloudapi.com/api-ws/v1/inference'
# Create a global object pool (one-time cost at startup)
pool = SpeechSynthesizerObjectPool(max_size=20)
def synthesize(text, task_id):
complete_event = threading.Event()
class Callback(ResultCallback):
def on_open(self):
self.file = open(f'result_{task_id}.mp3', 'wb')
def on_complete(self):
complete_event.set()
def on_error(self, message):
print(f'[task_{task_id}] Error: {message}')
def on_data(self, data):
self.file.write(data)
def on_close(self):
if hasattr(self, 'file'):
self.file.close()
callback = Callback()
# Borrow a pre-connected synthesizer from the pool
synth = pool.borrow_synthesizer(
model='cosyvoice-v3-flash',
voice='longanyang',
callback=callback
)
try:
synth.call(text)
complete_event.wait()
print(f'[task_{task_id}] First packet delay: '
f'{synth.get_first_package_delay()} ms')
# Return the synthesizer to the pool for reuse
pool.return_synthesizer(synth)
except Exception as e:
print(f'[task_{task_id}] Failed: {e}')
synth.close() # Do not return failed objects
# Run concurrent tasks
texts = ["First sentence.", "Second sentence.", "Third sentence."]
threads = [threading.Thread(target=synthesize, args=(t, i))
for i, t in enumerate(texts)]
for t in threads:
t.start()
for t in threads:
t.join()
pool.shutdown()
Nunca devolva um sintetizador para o grupo se a tarefa falhou ou ainda está em execução. Feche manualmente, ao invés disso.
Java: Conexão piscina + objeto piscina
O Java SDK usa o conjunto de conexões OkHttp3 (apto por padrão) mais um conjunto de objetos opcional Apache Commons Pool2 para SpeechSynthesizer - Sim. - Sim.
Passo 1: Configure o pool de conexão via variáveis de ambiente
- Variável * Recomendação padrão *
| ------------------------------------------- | ------- | -------------------------- |
|
DASHSCOPE_CONNECTION_POOL_SIZE32, 2x pico de concorrência |DASHSCOPE_MAXIMUM_ASYNC_REQUESTS32 ? ? ? tamanho da piscina de conexão |DASHSCOPE_MAXIMUM_ASYNC_REQUESTS_PER_HOST32 ? ? ? tamanho da piscina de conexão
export DASHSCOPE_CONNECTION_POOL_SIZE=2000
export DASHSCOPE_MAXIMUM_ASYNC_REQUESTS=2000
export DASHSCOPE_MAXIMUM_ASYNC_REQUESTS_PER_HOST=2000
Passo 2: Adicione dependência comum de piscina 2
Maven
```xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>the-latest-version</version>
</dependency>
```
Gradle
```gradle
implementation group: 'org.apache.commons',
name: 'commons-pool2', version: 'the-latest-version'
```
Passo 3: Crie e use o conjunto de objetos
- Variável * Recomendação padrão *
| ----------------------------------- | ------- | -------------------------------------------------------------- |
|
SAMBERT_OBJECTPOOL_SIZE500 , 1.5x-2x pico de concorrência, não deve exceder o tamanho da piscina de conexão
import com.alibaba.dashscope.audio.tts.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
// Factory
class SynthesizerFactory extends BasePooledObjectFactory<SpeechSynthesizer> {
public SpeechSynthesizer create() { return new SpeechSynthesizer(); }
public PooledObject<SpeechSynthesizer> wrap(SpeechSynthesizer obj) {
return new DefaultPooledObject<>(obj);
}
}
// Pool (global singleton)
GenericObjectPoolConfig<SpeechSynthesizer> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(1200);
config.setMaxIdle(1200);
config.setMinIdle(1200);
GenericObjectPool<SpeechSynthesizer> pool =
new GenericObjectPool<>(new SynthesizerFactory(), config);
// Usage in each task
SpeechSynthesizer synth = pool.borrowObject();
try {
// ... configure params and call synth
pool.returnObject(synth);
} catch (Exception e) {
synth = null; // Do not return on failure
}
Tamanho do servidor de referência: uma máquina GiB de 4 núcleos 8 pode lidar com tarefas Sambert TTS simultâneas com um conjunto de objetos de 1200 e uma piscina de conexão de 2000.
Boas práticas.
-
- Java SDK - Set
connectionPoolSizeemaximumAsyncRequestsbaseado na sua carga de trabalho concorrente. Poucas conexões causam bloqueio, muitas aumentam a carga do servidor.
- Java SDK - Set
- Python SDK: Use
withDeclarações para gerenciar o ciclo de vida da sessão e garantir a limpeza de recursos adequada. - Use as chamadas de assincronia para aplicações assincronia (como assincio ou FastAPI). Usem chamadas de sincronização para aplicações tradicionais.
- Nunca devolva um sintetizador para a piscina se a tarefa falhou ou ainda estiver em execução. Feche manualmente, ao invés disso.
Monitoramento de desempenho
Rastreie essas métricas para manter serviços de produção saudável TTS:
Ver a tabela estruturada nos quadros de referência desta página ↓
Acesse essas métricas do SDK:
# TTS
print(f"Request ID: {synthesizer.get_last_request_id()}")
print(f"First packet delay: {synthesizer.get_first_package_delay()} ms")
// TTS
System.out.println("Request ID: " + synthesizer.getLastRequestId());
System.out.println("First packet delay: " + synthesizer.getFirstPackageDelay() + " ms");
Lista de verificação de produção
Antes de ir ao vivo, verifique o seguinte:
- API Key armazenada em variável de ambiente, não codificada.
- Tamanhos de piscina e piscina de objetos configurados para carga máxima esperada.
- O tamanho da piscina não excede o limite de QPS da sua conta.
- Erro ao lidar com os retornos de objetos fracassados para descarte (não de volta para a piscina).
- Chamadas de desligamento graciosas
pool.shutdown()(Python) ou piscina perto (Java). - [ ] WebSocket conexões usar o ponto final correto (
wss://maas.qwencloudapi.com/...). - Monitoramento de painéis rastreiam atraso no primeiro pacote, taxa de erro e utilização do pool.
- Carga testada com 2x de máxima concorrência esperada.
- Tente novamente a lógica com retrocesso exponencial para falhas transitórias.
Relacionado
- [Texto para a fala] (/developer-guides/speech/tts) -- Modelos, parâmetros e modos de transmissão TTS.
- [Transmissão em tempo real] (/developer-guides/speech/realtime-streamingGuia de transmissão TTS em tempo real.
- [Melhorar precisão de reconhecimento] (/developer-guides/accuracy-tuning/speech-recognitionOtimização da ASR incluindo padrões de ASR de alta concorrência.
Quadros de referência
Tabelas restauradas a partir da referência original; a ordem das colunas e os valores técnicos foram preservados.
Quadro 1
| Parâmetro | Descrição | Padrão | Unidade. | Observações |
|---|---|---|---|---|
connectTimeout |
Tempo para estabelecer uma conexão. | 120 | segundos | Tempos mais curtos reduzem o tempo de espera em cenários de baixa latência. |
readTimeout |
Tempo para ler dados. | 300 | segundos | |
writeTimeout |
Tempo para escrever dados. | 60 | segundos | |
connectionIdleTimeout |
Tempo para conexões ociosas. | 300 | segundos | Tempos mais longos evitam reconexão frequente sob alta concorrência. |
connectionPoolSize |
Máximas conexões na piscina. | 32 | itens | Poucas conexões causam bloqueio, muitas aumentam a carga do servidor. |
maximumAsyncRequests |
Pedidos simultâneos em todos os hospedeiros. Deve ser o ≤connectionPoolSize. |
32 | pedidos | |
maximumAsyncRequestsPerHost |
Pedidos simultâneos por host. Deve ser o ≤maximumAsyncRequests. |
32 | itens |
Quadro 2
| Parâmetro | Descrição | Padrão | Observações |
|---|---|---|---|
limit |
Limite total de conexão. | 100 | Valores mais altos melhoram a concorrência. |
limit_per_host |
Limite de conexão por host | 0 (ilimitado) | Evita carga excessiva em um único hospedeiro. |
ssl |
Configuração de contexto SSL | Nenhum. | Validação de certificado SSL para conexões HTTPS. |
Quadro 3
| Variável | Padrão | Recomendação |
|---|---|---|
DASHSCOPE_CONNECTION_POOL_SIZE |
32 | 2x pico de concorrência |
DASHSCOPE_MAXIMUM_ASYNC_REQUESTS |
32 | Tamanho da piscina de conexão |
DASHSCOPE_MAXIMUM_ASYNC_REQUESTS_PER_HOST |
32 | Tamanho da piscina de conexão |
Quadro 4
| Variável | Padrão | Recomendação |
|---|---|---|
SAMBERT_OBJECTPOOL_SIZE(Sambert) |
500 | 1.5x-2x pico de concorrência, não deve exceder o tamanho da piscina de conexão |
Quadro 5
| Métrico | Descrição | Alvo |
|---|---|---|
| Primeiro atraso do pacote. | Tempo desde o pedido até o primeiro bloco de áudio. | < 500 ms |
| Lateza de ponta a ponta | Tempo total para síntese completa. | Depende do comprimento do texto. |
| Taxa de erro | Percentagem de pedidos fracassados | < 0.1% |
| Uso de piscina | Objetos emprestados, tamanho da piscina. | 60%-80% no pico |
| Relação de reaproveitamento da conexão | Reutilizar conexões / pedidos totais | > 95% |