QwenCloudBRASIL
Tradução de apoio para consulta. Código e identificadores técnicos preservados. Consultar referência original ↗

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:

Pré-requisitos

Reutilização de conexão HTTP

O ponto final do DashScope difere pelo tipo de modelo:

Java SDK

A conexão está ativada por padrão. Ajuste os seguintes parâmetros conforme necessário.

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.

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.

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

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

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.

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:

Relacionado

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%