Este guia explica como usar o Java SDK para chamar serviços de modelo do Elastic Algorithm Service (EAS) e fornece exemplos de entrada/saída e um programa de amostra.
Para casos de uso e princípios do SDK, consulte SDK de invocação de serviço.
Pré-requisitos
Para usar o Java SDK do EAS em seu projeto Maven, adicione a dependência eas-sdk à seção <dependencies> do arquivo pom.xml. Para obter a versão mais recente, verifique o repositório Maven.
<dependency>
<groupId>com.aliyun.openservices.eas</groupId>
<artifactId>eas-sdk</artifactId>
<version>2.0.20</version>
</dependency>
O EAS SDK 2.0.5 e versões posteriores incluem a funcionalidade de cliente QueueService para o serviço de fila assíncrona com múltiplas prioridades. Para utilizar esse recurso e evitar conflitos de dependência, adicione as duas dependências a seguir e ajuste as versões conforme necessário:
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
Início rápido
Para chamar um serviço com o Java SDK, siga estas três etapas:
Obtenha as informações de chamada: Na página de detalhes do serviço no console EAS, acesse a aba Call Information para obter o endpoint, o nome do serviço e o token.
-
Escolha um tipo de solicitação e escreva o código: Selecione a classe Request/Response apropriada com base no formato dos dados de entrada do modelo e escreva o código usando o exemplo mínimo abaixo.
NotaSe você implantou o serviço com um Processor integrado, o SDK fornece classes de entrada e saída correspondentes. Por exemplo, o TensorFlow Processor integrado corresponde a
TFRequest. Para mais informações, consulte a documentação de cada processor em Processors Integrados. Execute e verifique: Execute o programa cliente e verifique a resposta. Se ocorrer um erro, consulte o guia de Solução de problemas.
O código a seguir é um exemplo mínimo de ponta a ponta de uma solicitação de string. Para mais exemplos, consulte Exemplos de programas:
import com.aliyun.openservices.eas.predict.http.PredictClient;
import com.aliyun.openservices.eas.predict.http.HttpConfig;
public class TestString {
public static void main(String[] args) throws Exception {
PredictClient client = new PredictClient(new HttpConfig());
// To use a VPC direct connection, call the setDirectEndpoint method. The format is typically {uid}.vpc.{region-id}.pai-eas.aliyuncs.com.
client.setDirectEndpoint("182848887922****.vpc.cn-shanghai.aliyuncs.com");
// The public endpoint for the EAS service. The format is typically {uid}.{region-id}.pai-eas.aliyuncs.com.
// client.setEndpoint("182848887922****.cn-shanghai.pai-eas.aliyuncs.com");
// The name of the EAS service.
client.setModelName("your_service_name");
client.setToken("YOUR_SERVICE_TOKEN");
// The request path. The complete request URL is http://<endpoint>/api/direct/<modelName>/<requestPath>.
client.setRequestPath("your_custom_path");
// Construct the request body. The supported input classes depend on the SDK. This example uses a String.
String request = "[{}]";
String response = client.predict(request);
System.out.println(response);
client.shutdown();
}
}
Referência da API
O Java SDK fornece as seguintes classes:
Grupo | Descrição da classe |
Classe Principal do Cliente |
|
Configuração de conexão |
|
Entrada/saída |
|
Serviço de fila |
|
Classe PredictClient
Classe principal do cliente. Configure as informações do serviço, envia solicitações e recebe resultados de previsão.
API | Descrição |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Defina uma URL de solicitação personalizada. |
|
|
|
|
|
|
|
|
|
|
|
|
Classe HttpConfig
Configure parâmetros subjacentes de conexão HTTP, como timeouts, contagem de threads e pool de conexões.
API | Descrição |
|
|
|
Importante Este timeout se aplica somente após o estabelecimento da conexão. Difere do timeout de solicitação definido pelo método |
|
Importante Este timeout abrange todo o ciclo de vida da solicitação, incluindo estabelecimento de conexão, transferência de dados e processamento pelo servidor. Difere do timeout de leitura definido pelo método |
|
|
|
|
|
|
|
|
| Retorna o código de status da última chamada de API. |
| Retorna a mensagem de status da última chamada de API. |
Classe TFRequest
Constrói os dados de entrada para um modelo TensorFlow.
API | Descrição |
|
|
|
|
|
|
Classe TFResponse
Analisa e acessa os dados de saída de uma previsão de modelo TensorFlow.
API | Descrição |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Classe QueueClient
Interage com o serviço de fila do EAS para produzir, consumir e gerencie dados.
API | Descrição |
|
|
|
|
|
|
|
|
|
|
|
|
|
Importante Ao chamar
|
|
|
|
|
| Fecha a conexão com o serviço de fila. |
Classe DataFrame
Um wrapper para um item de dados do serviço de fila.
API | Descrição |
|
|
|
|
|
|
Exemplos de código
Exemplos de inferência síncrona
Escolha o exemplo correspondente ao formato de entrada e saída do seu serviço.
String
Se você implantou um serviço com um processor personalizado, normalmente usa strings para chamá-lo. Essa prática é comum para serviços de modelo PMML, conforme mostra o exemplo a seguir.
import com.aliyun.openservices.eas.predict.http.PredictClient;
import com.aliyun.openservices.eas.predict.http.HttpConfig;
public class TestString {
public static void main(String[] args) throws Exception {
// Initialize the client. The client object should be shared. Do not create a new client object for each request.
PredictClient client = new PredictClient(new HttpConfig());
client.setToken("YWFlMDYyZDNmNTc3M2I3MzMwYmY0MmYwM2Y2MTYxMTY4NzBkNzdj****");
// To use a direct network connection, call the setDirectEndpoint method.
// Example: client.setDirectEndpoint("182848887922****.vpc.cn-shanghai.aliyuncs.com");
// To enable a direct network connection, you must enable it in the EAS console and provide the source vSwitch used to access the EAS service. This bypasses the gateway, allowing you to directly access service instances via software load balancing for improved stability and performance.
// Note: For standard gateway access, use the endpoint that starts with your user ID. You can find this endpoint in the "Call Information" of the service in the EAS console. For direct network connections, use a domain name in the format 182848887922****.vpc.{region_id}.aliyuncs.com.
client.setEndpoint("182848887922****.vpc.cn-shanghai.pai-eas.aliyuncs.com");
client.setModelName("scorecard_pmml_example");
// Define the input string.
String request = "[{\"money_credit\": 3000000}, {\"money_credit\": 10000}]";
System.out.println(request);
// Get the response string from EAS.
try {
String response = client.predict(request);
System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
}
// Shut down the client.
client.shutdown();
return;
}
}
TensorFlow
Se você usar um modelo TensorFlow, utilize as classes TFRequest e TFResponse para entrada e saída, conforme demonstra o exemplo a seguir.
import java.util.List;
import com.aliyun.openservices.eas.predict.http.PredictClient;
import com.aliyun.openservices.eas.predict.http.HttpConfig;
import com.aliyun.openservices.eas.predict.request.TFDataType;
import com.aliyun.openservices.eas.predict.request.TFRequest;
import com.aliyun.openservices.eas.predict.response.TFResponse;
public class TestTF {
public static TFRequest buildPredictRequest() {
TFRequest request = new TFRequest();
request.setSignatureName("predict_images");
float[] content = new float[784];
for (int i = 0; i < content.length; i++) {
content[i] = (float) 0.0;
}
request.addFeed("images", TFDataType.DT_FLOAT, new long[]{1, 784}, content);
request.addFetch("scores");
return request;
}
public static void main(String[] args) throws Exception {
PredictClient client = new PredictClient(new HttpConfig());
// To use a direct network connection, call the setDirectEndpoint method. The endpoint format is {uid}.vpc.{region_id}.aliyuncs.com.
// client.setDirectEndpoint("182848887922****.vpc.cn-shanghai.aliyuncs.com");
// For standard gateway access, use the endpoint that starts with your user ID. You can find this endpoint in the "Call Information" of the service in the EAS console.
client.setEndpoint("182848887922****.vpc.cn-shanghai.pai-eas.aliyuncs.com");
client.setModelName("mnist_saved_model_example");
client.setToken("YTg2ZjE0ZjM4ZmE3OTc0NzYxZDMyNmYzMTJjZTQ1YmU0N2FjMTAy****");
long startTime = System.currentTimeMillis();
int count = 1000;
for (int i = 0; i < count; i++) {
try {
TFResponse response = client.predict(buildPredictRequest());
List<Float> result = response.getFloatVals("scores");
System.out.print("Predict Result: [");
for (int j = 0; j < result.size(); j++) {
System.out.print(result.get(j).floatValue());
if (j != result.size() - 1) {
System.out.print(", ");
}
}
System.out.print("]\n");
} catch (Exception e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("Spend Time: " + (endTime - startTime) + "ms");
client.shutdown();
}
}
Exemplo de serviço de fila
Para acessar o serviço de fila, use a interface QueueClient. O exemplo a seguir mostra como fazer isso.
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.eas.predict.http.HttpConfig;
import com.aliyun.openservices.eas.predict.http.QueueClient;
import com.aliyun.openservices.eas.predict.queue_client.QueueUser;
import com.aliyun.openservices.eas.predict.queue_client.WebSocketWatcher;
public class DemoWatch {
public static void main(String[] args) throws Exception {
/** Create a queue service client. */
String queueEndpoint = "18*******.cn-hangzhou.pai-eas.aliyuncs.com";
String inputQueueName = "test_queue_service";
String sinkQueueName = "test_queue_service/sink";
String queueToken = "test-token";
/** The input queue. The inference service automatically reads request data from this queue. */
QueueClient inputQueue =
new QueueClient(queueEndpoint, inputQueueName, queueToken, new HttpConfig(), new QueueUser());
/** The output queue. After the inference service processes the input data, it writes the results to this queue. */
QueueClient sinkQueue =
new QueueClient(queueEndpoint, sinkQueueName, queueToken, new HttpConfig(), new QueueUser());
/** Clear queue data. Use with caution. */
inputQueue.clear();
sinkQueue.clear();
/** Add data to the input queue. */
int count = 10;
for (int i = 0; i < count; ++i) {
String data = Integer.toString(i);
inputQueue.put(data.getBytes(), null);
/** The queue service supports multiple priorities. You can use the put method to set the data priority. The default priority is 0. */
// inputQueue.put(data.getBytes(), 0L, null);
}
/** Use the watch method to subscribe to data from the output queue. The window size is 5. */
WebSocketWatcher watcher = sinkQueue.watch(0L, 5L, false, true, null);
/** Use the WatchConfig parameter to customize the number of retries, retry interval (in seconds), and whether to retry indefinitely. If you do not configure WatchConfig, the system defaults to 3 retries with a 5-second interval. */
// WebSocketWatcher watcher = sink_queue.watch(0L, 5L, false, true, null, new WatchConfig(3, 1));
// WebSocketWatcher watcher = sink_queue.watch(0L, 5L, false, true, null, new WatchConfig(true, 10));
/** Get the output data. */
for (int i = 0; i < count; ++i) {
try {
/** The getDataFrame() method retrieves DataFrame data. This call blocks until data is available. */
byte[] data = watcher.getDataFrame().getData();
System.out.println("[watch] data = " + new String(data));
} catch (RuntimeException ex) {
System.out.println("[watch] error = " + ex.getMessage());
break;
}
}
/** Close the watcher object. Each client instance supports only one watcher object. If you do not close the watcher, an error occurs on the next run. */
watcher.close();
Thread.sleep(2000);
JSONObject attrs = sinkQueue.attributes();
System.out.println(attrs.toString());
/** Shut down the clients. */
inputQueue.shutdown();
sinkQueue.shutdown();
}
}
A chamada de um serviço com o Java SDK envolve as seguintes etapas:
Use a interface
QueueClientpara criar um objeto cliente do serviço de fila. Se você criar um serviço de inferência, também deverá criar objetos de fila de entrada e fila de saída.-
Use a função
put()para enviar dados para a fila de entrada e a funçãowatch()para assinar dados da fila de saída.NotaEm um ambiente de produção, use threads separadas para enviar dados e assinar dados. Para fins de demonstração, este exemplo executa essas operações na mesma thread.
Compactação de dados de solicitação
Para solicitações com grande volume de dados, o EAS suporta compactação usando o formato Zlib ou Gzip antes do envio ao servidor. Para ativar esse recurso, especifique rpc.decompressor na configuração do serviço.
A configuração do serviço é a seguinte:
"metadata": {
"rpc": {
"decompressor": "zlib"
}
}
Segue um exemplo de código:
package com.aliyun.openservices.eas.predict;
import com.aliyun.openservices.eas.predict.http.Compressor;
import com.aliyun.openservices.eas.predict.http.PredictClient;
import com.aliyun.openservices.eas.predict.http.HttpConfig;
public class TestString {
public static void main(String[] args) throws Exception{
// Initialize the client.
PredictClient client = new PredictClient(new HttpConfig());
client.setEndpoint("18*******.cn-hangzhou.pai-eas.aliyuncs.com");
client.setModelName("echo_compress");
client.setToken("YzZjZjQwN2E4NGRkMDMxNDk5NzhhZDcwZDBjOTZjOGYwZDYxZGM2****");
// You can also use Compressor.Gzip.
client.setCompressor(Compressor.Zlib);
// Define the input string.
String request = "[{\"money_credit\": 3000000}, {\"money_credit\": 10000}]";
System.out.println(request);
// Get the response string from EAS.
String response = client.predict(request);
System.out.println(response);
// Shut down the client.
client.shutdown();
return;
}
}
Solução de problemas
Para solucionar problemas de exceções de invocação do Java SDK, incluindo problemas comuns de autenticação, roteamento, conexão e erros do lado do servidor, consulte a seção "Solução de Problemas de Exceções de Invocação" em SDK de Invocação de Serviço.
Para obter uma lista completa de códigos de status de serviço, significados de mensagens de erro e ações recomendadas, consulte Apêndice: Códigos de Status de Serviço e Erros Comuns.