# huaweicloud-sdk-java-v3 **Repository Path**: HuaweiCloudDeveloper/huaweicloud-sdk-java-v3 ## Basic Information - **Project Name**: huaweicloud-sdk-java-v3 - **Description**: 华为云全新设计的SDK V3版本,提供统一的SDK使用方式。通过添加依赖或下载的方式调用华为云API,访问华为云应用、资源和数据。无需关心请求细节即可快速使用弹性云服务器(ECS)、虚拟私有云(VPC)等多个华为云服务。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master-dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 9 - **Forks**: 99 - **Created**: 2023-06-13 - **Last Updated**: 2025-06-26 ## Categories & Tags **Categories**: cloud **Tags**: None ## README [English](./README.md) | 简体中文

华为云开发者 Java 软件开发工具包(Java SDK)

欢迎使用华为云 Java SDK 。 华为云 Java SDK 让您无需关心请求细节即可快速使用弹性云服务器(ECS)、虚拟私有云(VPC)等多个华为云服务。 这里将向您介绍如何获取并使用华为云 Java SDK 。 ## 使用前提 - 要使用华为云 Java SDK ,您需要拥有华为云账号以及该账号对应的 Access Key(AK)和 Secret Access Key(SK)。请在华为云控制台 “我的凭证-访问密钥” 页面上创建和查看您的 AK&SK 。更多信息请查看 [访问密钥](https://support.huaweicloud.com/usermanual-ca/zh-cn_topic_0046606340.html) 。 - 要使用华为云 Java SDK 访问指定服务的 API ,您需要确认已在 [华为云控制台](https://console.huaweicloud.com/console/?locale=zh-cn®ion=cn-north-4#/home) 开通当前服务。 - 华为云 Java SDK 支持 **Java JDK 1.8** 及其以上版本。 ## SDK 获取和安装 推荐您通过 Maven 安装依赖的方式使用华为云 Java SDK: 首先您需要在您的操作系统中 [下载](https://maven.apache.org/download.cgi) 并 [安装](https://maven.apache.org/install.html) Maven ,安装完成后您只需在 Maven 项目的 `pom.xml` 文件加入相应的依赖项即可。 指定依赖时请选择特定的版本号,否则可能会在构建时导致不可预见的问题。 您可以通过 [SDK中心](https://console.huaweicloud.com/apiexplorer/#/sdkcenter?language=Java) 或 [Maven中心仓库](https://search.maven.org/search?q=huaweicloud-sdk) 查询SDK版本信息。 ### 独立服务包: 根据需要独立引入SDK依赖包 。以 ECS 和 VPC SDK 为例,您需要安装 `huaweicloud-sdk-ecs`和 `huaweicloud-sdk-vpc`: ``` xml com.huaweicloud.sdk huaweicloud-sdk-ecs ${version} com.huaweicloud.sdk huaweicloud-sdk-vpc ${version} ``` ### 整个SDK包: 支持只添加一个依赖包导入所有支持的服务(3.0.40-rc及以上版本): ```xml com.huaweicloud.sdk huaweicloud-sdk-all ${version} ``` ### 整个SDK Bundle包: 当出现第三方库冲突的时候,可以引入如下bundle包(3.0.40-rc及以上版本),该包包含所有支持的服务和重定向了SDK依赖的第三方软件,避免和业务自身依赖的库产生冲突: ```xml com.huaweicloud.sdk huaweicloud-sdk-bundle ${version} ``` 常见冲突例如Jackson,okhttp3版本冲突等。 **注意:** bundle包已经包含了core包和云服务集合包,不要再单独引入core包和服务包,根据maven依赖解析顺序,可能会导致bundle包不生效。 以下为错误示例: ```xml com.huaweicloud.sdk huaweicloud-sdk-core ${version} com.huaweicloud.sdk huaweicloud-sdk-ecs ${version} com.huaweicloud.sdk huaweicloud-sdk-bundle ${version} ``` ## 代码示例 - 使用如下代码同步查询指定 Region 下的 VPC 列表,实际使用中请将 `VpcClient` 替换为您使用的产品/服务相应的 `{Service}Client` 。 - 认证用的ak和sk直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全。 - 本示例中的ak和sk保存在环境变量中,运行本示例前请先在本地环境中配置环境变量`HUAWEICLOUD_SDK_AK`和`HUAWEICLOUD_SDK_SK`。 **精简示例** ``` java package com.huaweicloud.sdk.test; import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.ICredential; import com.huaweicloud.sdk.core.exception.ConnectionException; import com.huaweicloud.sdk.core.exception.RequestTimeoutException; import com.huaweicloud.sdk.core.exception.ServiceResponseException; import com.huaweicloud.sdk.vpc.v2.VpcClient; import com.huaweicloud.sdk.vpc.v2.model.ListVpcsRequest; import com.huaweicloud.sdk.vpc.v2.model.ListVpcsResponse; import com.huaweicloud.sdk.vpc.v2.region.VpcRegion; public class Application { public static void main(String[] args) { // 配置认证信息 // 可通过环境变量等方式配置认证信息,参考2.4认证信息管理章节 ICredential auth = new BasicCredentials() .withAk(System.getenv("HUAWEICLOUD_SDK_AK")) .withSk(System.getenv("HUAWEICLOUD_SDK_SK")); // 创建服务客户端 VpcClient client = VpcClient.newBuilder() .withCredential(auth) .withRegion(VpcRegion.valueOf("cn-north-4")) .build(); // 发送请求并获取响应 ListVpcsRequest request = new ListVpcsRequest(); try { ListVpcsResponse response = client.listVpcs(request); System.out.println(response.toString()); } catch (ConnectionException | RequestTimeoutException e) { e.printStackTrace(); } catch (ServiceResponseException e) { e.printStackTrace(); System.out.println(e.getHttpStatusCode()); System.out.println(e.getRequestId()); System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } } ``` **详细示例** ```java package com.huaweicloud.sdk.test; import com.huaweicloud.sdk.core.HttpListener; import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.ICredential; import com.huaweicloud.sdk.core.auth.SigningAlgorithm; import com.huaweicloud.sdk.core.exception.ConnectionException; import com.huaweicloud.sdk.core.exception.RequestTimeoutException; import com.huaweicloud.sdk.core.exception.ServiceResponseException; import com.huaweicloud.sdk.core.http.HttpConfig; import com.huaweicloud.sdk.vpc.v2.VpcClient; import com.huaweicloud.sdk.vpc.v2.model.ListVpcsRequest; import com.huaweicloud.sdk.vpc.v2.model.ListVpcsResponse; import com.huaweicloud.sdk.vpc.v2.region.VpcRegion; import java.util.stream.Collectors; public class Application { public static void main(String[] args) { // 配置认证信息 ICredential auth = new BasicCredentials() // 可通过环境变量等方式配置认证信息,参考2.4认证信息管理章节 .withAk(System.getenv("HUAWEICLOUD_SDK_AK")) .withSk(System.getenv("HUAWEICLOUD_SDK_SK")) // 如果未填写ProjectId,SDK会自动调用IAM服务查询所在region对应的项目id .withProjectId("{your projectId string}") // 配置SDK内置的IAM服务地址 .withIamEndpoint("https://iam.cn-north-4.myhuaweicloud.com"); // 使用默认配置 HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig(); // 配置是否忽略SSL证书校验, 默认不忽略 httpConfig.withIgnoreSSLVerification(true); // 默认连接超时时间为60秒,可根据需要配置(v3.1.94及之前的版本) httpConfig.withTimeout(60); // 默认连接超时时间为60秒,可根据需要配置(v3.1.95版本起,优先使用withConnectionTimeout) httpConfig.withConnectionTimeout(60); // 默认读取超时时间为120秒,可根据需要配置 httpConfig.withReadTimeout(120); // 根据需要配置网络代理,网络代理默认的协议为 `http` 协议 // 请根据实际情况替换示例中的代理地址和端口号 httpConfig.withProxyHost("proxy.huaweicloud.com") .withProxyPort(8080) // 如果代理需要认证,请配置用户名和密码 .withProxyUsername(System.getenv("PROXY_USERNAME")) .withProxyPassword(System.getenv("PROXY_PASSWORD")); // 自定义SSLSocketFactory和TrustManager,需要用户自行实现 httpConfig.withSSLSocketFactory(sslSocketFactory) .withX509TrustManager(trustManager); // 使用HMAC_SM3签名算法(需要JDK8u302及以上版本),默认签名算法为HMAC_SHA256 httpConfig.withSigningAlgorithm(SigningAlgorithm.HMAC_SM3); // 注册监听器后打印原始请求信息,请勿用于生产环境 HttpListener requestListener = HttpListener.forRequestListener(listener -> System.out.printf("> Request %s %s\n> Headers:\n%s\n> Body: %s\n", listener.httpMethod(), listener.uri(), listener.headers().entrySet().stream() .flatMap(entry -> entry.getValue().stream().map( value -> "\t" + entry.getKey() + ": " + value)) .collect(Collectors.joining("\n")), listener.body().orElse(""))); httpConfig.addHttpListener(requestListener); // 注册监听器后打印原始响应信息,请勿用于生产环境 HttpListener responseListener = HttpListener.forResponseListener(listener -> System.out.printf("< Response %s %s %s\n< Headers:\n%s\n< Body: %s\n", listener.httpMethod(), listener.uri(), listener.statusCode(), listener.headers().entrySet().stream() .flatMap(entry -> entry.getValue().stream().map( value -> "\t" + entry.getKey() + ": " + value)) .collect(Collectors.joining("\n")), listener.body().orElse(""))); httpConfig.addHttpListener(responseListener); // 创建服务客户端 VpcClient client = VpcClient.newBuilder() // 配置认证信息 .withCredential(auth) // 配置地区, 如果地区不存在会抛出IllegalArgumentException .withRegion(VpcRegion.valueOf("cn-north-4")) // HTTP配置 .withHttpConfig(httpConfig) .build(); // 创建请求 ListVpcsRequest request = new ListVpcsRequest(); // 配置每页返回的个数 request.setLimit(1); try { // 发送请求并获取响应 ListVpcsResponse response = client.listVpcs(request); System.out.println(response.toString()); } catch (ConnectionException | RequestTimeoutException e) { e.printStackTrace(); } catch (ServiceResponseException e) { e.printStackTrace(); System.out.println(e.getHttpStatusCode()); System.out.println(e.getRequestId()); System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } } ``` ## 在线调试 [API Explorer](https://apiexplorer.developer.huaweicloud.com/apiexplorer/overview) 提供API检索、SDK示例及平台调试,支持全量快速检索、可视化调试、帮助文档查看、在线咨询。 ## 变更日志 每个版本的详细更改记录可在 [变更日志](https://github.com/huaweicloud/huaweicloud-sdk-java-v3/blob/master/CHANGELOG_CN.md) 中查看。 ## 用户手册 [:top:](#华为云开发者-java-软件开发工具包java-sdk) * [1. 客户端连接参数](#1-客户端连接参数-top) * [1.1 默认配置](#11-默认配置-top) * [1.2 网络代理](#12-网络代理-top) * [1.3 超时配置](#13-超时配置-top) * [1.4 SSL 配置](#14-ssl-配置-top) * [1.5 签名算法](#15-签名算法-top) * [2. 认证信息配置](#2-认证信息配置-top) * [2.1 使用永久 AK 和 SK](#21-使用永久-ak-和-sk-top) * [2.2 使用临时 AK 和 SK](#22-使用临时-ak-和-sk-top) * [2.3 使用 IdpId 和 IdTokenFile](#23-使用-idpid-和-idtokenfile-top) * [2.4 认证信息管理](#24-认证信息管理-top) * [2.4.1 环境变量](#241-环境变量-top) * [2.4.2 配置文件](#242-配置文件-top) * [2.4.3 实例元数据](#243-实例元数据-top) * [2.4.4 认证信息提供链](#244-认证信息提供链-top) * [3. 客户端初始化](#3-客户端初始化-top) * [3.1 指定云服务 Endpoint 方式](#31-指定云服务-endpoint-方式-top) * [3.2 指定 Region 方式(推荐)](#32-指定-region-方式-推荐-top) * [3.3 自定义配置](#33-自定义配置-top) * [3.3.1 IAM endpoint配置](#331-iam-endpoint配置-top) * [3.3.2 Region配置](#332-region配置-top) * [4. 发送请求并查看响应](#4-发送请求并查看响应-top) * [4.1 异常处理](#41-异常处理-top) * [5. 异步客户端使用](#5-异步客户端使用-top) * [6. 故障处理](#6-故障处理-top) * [6.1 访问日志](#61-访问日志-top) * [6.2 HTTP 监听器](#62-http-监听器-top) * [7. 接口调用器](#7-接口调用器-top) * [7.1 自定义请求头](#71-自定义请求头-top) * [7.2 请求重试](#72-请求重试-top) * [7.2.1 同步客户端请求重试](#721-同步客户端请求重试-top) * [7.2.2 异步客户端请求重试](#722-异步客户端请求重试-top) * [7.2.3 典型重试场景调用示例](#723-典型重试场景调用示例-top) * [8. 文件上传与下载](#8-文件上传与下载-top) * [8.1 上传与下载](#81-上传与下载-top) * [8.2 获取进度](#82-获取进度-top) * [9. FAQ](#9-faq-top) * [9.1 云联盟场景如何调用](#91-云联盟场景如何调用-top) ### 1. 客户端连接参数 [:top:](#用户手册-top) #### 1.1 默认配置 [:top:](#用户手册-top) ``` java import com.huaweicloud.sdk.core.http.HttpConfig; // 使用默认配置 HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig(); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` #### 1.2 网络代理 [:top:](#用户手册-top) 当前 Java SDK 仅支持配置 HTTP 代理。 ``` java // 根据需要配置网络代理,网络代理默认的协议为 `http` 协议 HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig() // 请根据实际情况替换示例中的代理地址和端口号 .withProxyHost("proxy.xxx.com") .withProxyPort(12345) // 如果代理需要认证,请配置用户名和密码 // 本示例中的账号和密码保存在环境变量中,运行本示例前请先在本地环境中配置环境变量PROXY_USERNAME和PROXY_PASSWORD .withProxyUsername(System.getenv("PROXY_USERNAME")) .withProxyPassword(System.getenv("PROXY_PASSWORD")); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` #### 1.3 超时配置 [:top:](#用户手册-top) ``` java HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig() // 默认连接超时时间为60秒,可根据需要配置(v3.1.94及之前的版本) .withTimeout(60); // 默认连接超时时间为60秒,可根据需要调整(v3.1.95版本起,优先使用withConnectionTimeout) .withConnectionTimeout(60) // 默认读取超时时间为120秒,可根据需要调整 .withReadTimeout(120); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` #### 1.4 SSL 配置 [:top:](#用户手册-top) SDK使用的是 **Java 默认信任库**,即 `$JAVA_HOME/lib/security/cacerts`中的证书,如果其中**证书链不完整或不受信任**可能会导致**SSLHandshakeException、SSLPeerUnverifiedException、SunCertPathBuilderException**等异常,可以通过 **Java自带工具 keytool** 确认证书是否存在问题。 同时SDK也支持 **SSL跳过验证** 和 **自定义配置**。 跳过验证: ``` java // 根据需要配置是否跳过SSL证书验证, 请勿用于生产环境 HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig().withIgnoreSSLVerification(true); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` 自定义配置: ```java // 自定义SSLSocketFactory、TrustManager和HostnameVerifier,需要用户自行实现 HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig() .withSSLSocketFactory(sslSocketFactory) .withX509TrustManager(trustManager) .withHostnameVerifier(hostnameVerifier); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` #### 1.5 签名算法 [:top:](#用户手册-top) ```java import com.huaweicloud.sdk.core.auth.SigningAlgorithm; // 使用HMAC_SM3签名算法需要JDK8u302及以上版本, 默认签名算法为HMAC_SHA256 HttpConfig.getDefaultHttpConfig().withSigningAlgorithm(SigningAlgorithm.HMAC_SM3); VpcClient client = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` ### 2. 认证信息配置 [:top:](#用户手册-top) 华为云服务存在两种部署方式,Region 级服务和 Global 级服务。 Global 级服务有 BSS、DevStar、EPS、IAM、OSM、RMS、TMS。 Region 级服务使用 BasicCredentials 初始化,需要提供 projectId 。 Global 级服务使用 GlobalCredentials 初始化,需要提供 domainId 。 客户端认证方式支持以下几种: - 永久 AK&SK 认证 - 临时 AK&SK&SecurityToken 认证 - IdpId&IdTokenFile 认证 #### 2.1 使用永久 AK 和 SK [:top:](#用户手册-top) 获取AK/SK请参考 https://support.huaweicloud.com/devg-apisign/api-sign-provide-aksk.html **认证参数说明**: - `ak` - 华为云账号 Access Key - `sk` - 华为云账号 Secret Access Key - `projectId` - 云服务所在项目 ID ,根据你想操作的项目所属区域选择对应的项目 ID - `domainId` - 华为云账号 ID ``` java import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.GlobalCredentials; // Region级服务 BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withProjectId(projectId); // Global级服务 GlobalCredentials globalCredentials = new GlobalCredentials() .withAk(ak) .withSk(sk) .withDomainId(domainId); ``` **说明**: - `3.0.26-beta` 及以上版本支持自动获取 projectId/domainId ,用户需要指定当前华为云账号的永久 AK&SK 和 对应的 region_id,同时在初始化客户端时配合 `withRegion()` 方法使用。代码示例详见 [3.2 指定Region方式(推荐)](#32-指定-region-方式-推荐-top)。 #### 2.2 使用临时 AK 和 SK [:top:](#用户手册-top) 临时AK/SK和securitytoken是系统颁发给IAM用户的临时访问令牌,有效期可在15分钟至24小时范围内设置,过期后需要重新获取。 首先需要获得临时 AK、SK 和 SecurityToken ,可以从永久 AK&SK 获得,或者通过委托授权获得。 - 通过永久 AK&SK 获得可以参考文档:https://support.huaweicloud.com/api-iam/iam_04_0002.html ,对应 IAM SDK 中的 `CreateTemporaryAccessKeyByToken` 方法。 - 通过委托授权获得可以参考文档:https://support.huaweicloud.com/api-iam/iam_04_0101.html ,对应 IAM SDK 中的 `CreateTemporaryAccessKeyByAgency` 方法。 **认证参数说明**: - `ak` - 华为云账号 Access Key - `sk` - 华为云账号 Secret Access Key - `projectId` - 云服务所在项目 ID ,根据你想操作的项目所属区域选择对应的项目 ID - `domainId` - 华为云账号 ID - `securityToken` - 采用临时 AK&SK 认证场景下的安全票据 临时 AK&SK&SecurityToken 获取成功后,可使用如下方式初始化认证信息: ``` java import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.GlobalCredentials; // Region级服务 BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withSecurityToken(securityToken) .withProjectId(projectId) // Global级服务 GlobalCredentials globalCredentials = new GlobalCredentials() .withAk(ak) .withSk(sk) .withSecurityToken(securityToken) .withDomainId(domainId); ``` 以下两种情况,会尝试从实例元数据中读取认证信息: 1. 创建客户端时未手动指定 BasicCredentials 或 GlobalCredentials 2. 创建 BasicCredentials 或 GlobalCredentials 时未指定 AK/SK 关于元数据获取请参阅:[元数据获取](https://support.huaweicloud.com/usermanual-ecs/ecs_03_0166.html) ```java import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.GlobalCredentials; // Region级服务 BasicCredentials credentials = new BasicCredentials().withProjectId(projectId); // Global级服务 GlobalCredentials credentials = new GlobalCredentials().withDomainId(domainId); ``` #### 2.3 使用 IdpId 和 IdTokenFile [:top:](#用户手册-top) 通过OpenID Connect ID token方式获取联邦认证token, 可参考文档:[获取联邦认证token(OpenID Connect ID token方式)](https://support.huaweicloud.com/api-iam/iam_13_0605.html) **认证参数说明**: - `IdpId` 身份提供商ID - `IdTokenFile` 存放id_token的文件路径,id_token由企业IdP构建,携带联邦用户身份信息 - `projectId` 云服务所在项目 ID ,根据你想操作的项目所属区域选择对应的项目 ID - `domainId` 华为云账号 ID ``` java import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.GlobalCredentials; // Region级服务 BasicCredentials basicCredentials = new BasicCredentials() .withIdpId(idpId) .withIdTokenFile(idTokenFile) .withProjectId(projectId) // Global级服务 GlobalCredentials globalCredentials = new GlobalCredentials() .withIdpId(idpId) .withIdTokenFile(idTokenFile) .withDomainId(domainId); ``` #### 2.4 认证信息管理 [:top:](#用户手册-top) 从**3.0.97**版本起,支持从各类提供器中获取认证信息 **Region级服务** 请使用 `XxxCredentialProvider.getBasicCredentialXxxProvider()` **Global级服务** 请使用 `XxxCredentialProvider.getGlobalCredentialXxxProvider()` ##### 2.4.1 环境变量 [:top:](#用户手册-top) **AK/SK认证** | 环境变量 | 说明 | | ------------ | ------------ | | HUAWEICLOUD_SDK_AK | 必填,AccessKey | | HUAWEICLOUD_SDK_SK | 必填,SecretKey | | HUAWEICLOUD_SDK_SECURITY_TOKEN | 可选, 使用临时ak/sk认证时需要指定该参数 | | HUAWEICLOUD_SDK_PROJECT_ID | 可选,用于Region级服务,多ProjectId场景下必填 | | HUAWEICLOUD_SDK_DOMAIN_ID | 可选,用于Global级服务 | 配置环境变量: ``` // Linux export HUAWEICLOUD_SDK_AK=YOUR_AK export HUAWEICLOUD_SDK_SK=YOUR_SK // Windows set HUAWEICLOUD_SDK_AK=YOUR_AK set HUAWEICLOUD_SDK_SK=YOUR_SK ``` 从配置的环境变量中获取认证信息: ```java import com.huaweicloud.sdk.core.auth.EnvCredentialProvider; import com.huaweicloud.sdk.core.auth.ICredential; // basic EnvCredentialProvider basicProvider = EnvCredentialProvider.getBasicCredentialEnvProvider(); ICredential basicCred = basicProvider.getCredentials(); // global EnvCredentialProvider globalProvider = EnvCredentialProvider.getGlobalCredentialEnvProvider(); ICredential globalCred = globalProvider.getCredentials(); ``` **IdpId/IdTokenFile认证** | 环境变量 | 说明 | | ------------ | ------------ | | HUAWEICLOUD_SDK_IDP_ID | 必填,身份提供商ID | | HUAWEICLOUD_SDK_ID_TOKEN_FILE | 必填,存放id_token的文件路径 | | HUAWEICLOUD_SDK_PROJECT_ID | basic类型认证时,该参数必填 | | HUAWEICLOUD_SDK_DOMAIN_ID | global类型认证时,该参数必填 | 配置环境变量: ``` // Linux export HUAWEICLOUD_SDK_IDP_ID=YOUR_IDP_ID export HUAWEICLOUD_SDK_ID_TOKEN_FILE=/some_path/your_token_file export HUAWEICLOUD_SDK_PROJECT_ID=YOUR_PROJECT_ID // basic认证时必填 export HUAWEICLOUD_SDK_DOMAIN_ID=YOUR_DOMAIN_ID // global认证时必填 // Windows set HUAWEICLOUD_SDK_IDP_ID=YOUR_IDP_ID set HUAWEICLOUD_SDK_ID_TOKEN_FILE=/some_path/your_token_file set HUAWEICLOUD_SDK_PROJECT_ID=YOUR_PROJECT_ID // basic认证时必填 set HUAWEICLOUD_SDK_DOMAIN_ID=YOUR_DOMAIN_ID // global认证时必填 ``` 从配置的环境变量中获取认证信息: ```java import com.huaweicloud.sdk.core.auth.EnvCredentialProvider; import com.huaweicloud.sdk.core.auth.ICredential; // basic EnvCredentialProvider basicProvider = EnvCredentialProvider.getBasicCredentialEnvProvider(); ICredential basicCred = basicProvider.getCredentials(); // global EnvCredentialProvider globalProvider = EnvCredentialProvider.getGlobalCredentialEnvProvider(); ICredential globalCred = globalProvider.getCredentials(); ``` ##### 2.4.2 配置文件 [:top:](#用户手册-top) 默认会从用户主目录下读取认证信息配置文件,linux为`~/.huaweicloud/credentials`,windows为`C:\Users\USER_NAME\.huaweicloud\credentials`,可以通过配置环境变量`HUAWEICLOUD_SDK_CREDENTIALS_FILE`来修改默认文件的路径 **AK/SK认证** | 配置参数 | 说明 | | ------------ | ------------ | | ak | 必填,AccessKey | | sk | 必填,SecretKey | | security_token | 可选, 使用临时ak/sk认证时需要指定该参数 | | project_id | 可选,用于Region级服务,多ProjectId场景下必填 | | domain_id | 可选,用于Global级服务 | | iam_endpoint | 可选,用于身份认证的endpoint,默认为`https://iam.myhuaweicloud.com` | 配置文件内容如下: ```ini [basic] ak = your_ak sk = your_sk [global] ak = your_ak sk = your_sk ``` 从配置文件中读取认证信息: ```java import com.huaweicloud.sdk.core.auth.ProfileCredentialProvider; import com.huaweicloud.sdk.core.auth.ICredential; // basic ProfileCredentialProvider basicProvider = ProfileCredentialProvider.getBasicCredentialProfileProvider(); ICredential basicCred = basicProvider.getCredentials(); // global ProfileCredentialProvider globalProvider = ProfileCredentialProvider.getGlobalCredentialProfileProvider(); ICredential globalCred = globalProvider.getCredentials(); ``` **IdpId/IdTokenFile认证** | 配置参数 | 说明 | | ------------ | ------------ | | idp_id | 必填,身份提供商ID | | id_token_file | 必填,存放id_token的文件路径 | | project_id | basic类型认证时,该参数必填 | | domain_id | global类型认证时,该参数必填 | | iam_endpoint | 可选,用于身份认证的endpoint,默认为`https://iam.myhuaweicloud.com` | 配置文件内容如下: ```ini [basic] idp_id = your_idp_id id_token_file = /some_path/your_token_file project_id = your_project_id [global] idp_id = your_idp_id id_token_file = /some_path/your_token_file domainId = your_domain_id ``` 从配置文件中读取认证信息: ```java import com.huaweicloud.sdk.core.auth.ProfileCredentialProvider; import com.huaweicloud.sdk.core.auth.ICredential; // basic ProfileCredentialProvider basicProvider = ProfileCredentialProvider.getBasicCredentialProfileProvider(); ICredential basicCred = basicProvider.getCredentials(); // global ProfileCredentialProvider globalProvider = ProfileCredentialProvider.getGlobalCredentialProfileProvider(); ICredential globalCred = globalProvider.getCredentials(); ``` ##### 2.4.3 实例元数据 [:top:](#用户手册-top) 从实例元数据获取临时AK/SK和securitytoken,关于元数据获取请参阅:[元数据获取](https://support.huaweicloud.com/usermanual-ecs/ecs_03_0166.html) 手动获取实例元数据认证信息: ```java import com.huaweicloud.sdk.core.auth.MetadataCredentialProvider; import com.huaweicloud.sdk.core.auth.ICredential; // basic MetadataCredentialProvider basicProvider = MetadataCredentialProvider.getBasicCredentialMetadataProvider(); ICredential basicCred = basicProvider.getCredentials(); // global MetadataCredentialProvider globalProvider = MetadataCredentialProvider.getGlobalCredentialMetadataProvider(); ICredential globalCred = globalProvider.getCredentials(); ``` ##### 2.4.4 认证信息提供链 [:top:](#用户手册-top) 在创建服务客户端,未显式指定认证信息时,按照顺序 **环境变量 -> 配置文件 -> 实例元数据** 尝试加载认证信息 通过提供链获取认证信息: ```java import com.huaweicloud.sdk.core.auth.CredentialProviderChain; import com.huaweicloud.sdk.core.auth.ICredential; // basic CredentialProviderChain basicChain = CredentialProviderChain.getBasicCredentialProviderChain(); ICredential basicCred = basicChain.getCredentials(); // global CredentialProviderChain globalChain = CredentialProviderChain.getGlobalCredentialProviderChain(); ICredential globalCred = globalChain.getCredentials(); ``` 支持自定义认证信息提供链: ```java import com.huaweicloud.sdk.core.auth.CredentialProviderChain; import com.huaweicloud.sdk.core.auth.ICredential; import com.huaweicloud.sdk.core.auth.ICredentialProvider; import com.huaweicloud.sdk.core.auth.MetadataCredentialProvider; import com.huaweicloud.sdk.core.auth.ProfileCredentialProvider; ICredentialProvider[] providers = new ICredentialProvider[]{ MetadataCredentialProvider.getBasicCredentialMetadataProvider(), ProfileCredentialProvider.getBasicCredentialProfileProvider() }; CredentialProviderChain chain = new CredentialProviderChain(providers); ICredential cred = chain.getCredentials(); ``` ### 3. 客户端初始化 [:top:](#用户手册-top) 客户端初始化有两种方式,可根据需要选择下列两种方式中的一种: #### 3.1 指定云服务 Endpoint 方式 [:top:](#用户手册-top) ``` java // 初始化客户端认证信息,需要填写相应 projectId/domainId,以初始化 BasicCredentials 为例 BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withProjectId(projectId); // 初始化指定云服务的客户端 {Service}Client ,以初始化 Region 级服务 VPC 的 VpcClient 为例 VpcClient vpcClient = VpcClient.newBuilder() .withHttpConfig(config) .withCredential(basicCredentials) // 指定终端节点,以 VPC 服务北京四的 endpoint 为例 .withEndpoint("https://vpc.cn-north-4.myhuaweicloud.com") .build(); ``` **说明:** - `endpoint` 是华为云各服务应用区域和各服务的终端节点,详情请查看 [地区和终端节点](https://developer.huaweicloud.com/endpoint) 。 - 当用户使用指定 Region 方式无法自动获取 projectId 时,可以使用当前方式调用接口。 #### 3.2 指定 Region 方式 **(推荐)** [:top:](#用户手册-top) ``` java // 增加region依赖 import com.huaweicloud.sdk.iam.v3.region.IamRegion; // 初始化客户端认证信息,使用当前客户端初始化方式可不填 projectId/domainId,以初始化 GlobalCredentials 为例 GlobalCredentials globalCredentials = new GlobalCredentials() .withAk(ak) .withSk(sk); // 初始化指定云服务的客户端 {Service}Client ,以初始化 Global 级服务 IAM 的 IamClient 为例 IamClient iamClient = IamClient.newBuilder() .withCredential(globalCredentials) .withRegion(IamRegion.CN_NORTH_4) .build(); ``` **说明:** - 指定 Region 方式创建客户端的场景,支持自动获取用户的 projectId 或者 domainId,初始化认证信息时可无需指定相应参数。 - **不适用**于 `多ProjectId` 的场景。 - 支持指定的 Region 可通过[地区和终端节点](https://console.huaweicloud.com/apiexplorer/#/endpoint)查询。调用不支持的 region 可能会抛出 `Unsupported regionId` 的异常信息。 **两种方式对比:** | 初始化方式 | 优势 | 劣势 | | :---- | :---- | :---- | | 指定云服务 Endpoint 方式 | 只要接口已在当前环境发布就可以成功调用 | 需要用户自行查找并填写 projectId 和 endpoint | 指定 Region 方式 | 无需指定 projectId 和 endpoint,按照要求配置即可自动获取该值并回填 | 支持的服务和 region 有限制 #### 3.3 自定义配置 [:top:](#用户手册-top) **注:** 3.0.93版本起支持 ##### 3.3.1 IAM endpoint配置 [:top:](#用户手册-top) 自动获取用户的 projectId 和 domainId 会分别调用统一身份认证服务的 [KeystoneListProjects](https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IAM&api=KeystoneListProjects) 和 [KeystoneListAuthDomains](https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IAM&api=KeystoneListAuthDomains) 接口。 默认访问的endpoint会从[映射表](./core/src/main/resources/iam_endpoints.json)中查询,如果查不到则会使用默认值 **https://iam.myhuaweicloud.com** **欧洲站用户需要指定 endpoint 为 https://iam.eu-west-101.myhuaweicloud.eu** ,用户可以通过以下两种方式来修改endpoint ###### 3.3.1.1 全局级 [:top:](#用户手册-top) 全局范围生效,通过环境变量`HUAWEICLOUD_SDK_IAM_ENDPOINT`指定 ``` //linux export HUAWEICLOUD_SDK_IAM_ENDPOINT=https://iam.cn-north-4.myhuaweicloud.com //windows set HUAWEICLOUD_SDK_IAM_ENDPOINT=https://iam.cn-north-4.myhuaweicloud.com ``` ###### 3.3.1.2 凭证级 [:top:](#用户手册-top) 只对单个凭证生效,会覆盖全局配置 ```java import com.huaweicloud.sdk.core.auth.BasicCredentials; BasicCredentials credentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withIamEndpoint("https://iam.cn-north-4.myhuaweicloud.com"); ``` ##### 3.3.2 Region配置 [:top:](#用户手册-top) ###### 3.3.2.1 代码配置 [:top:](#用户手册-top) ```java import com.huaweicloud.sdk.core.region.Region; import com.huaweicloud.sdk.ecs.v2.EcsClient; // 使用自定义的regionId和endpoint创建一个region Region region = new Region("cn-north-9", "https://ecs.cn-north-9.myhuaweicloud.com"); EcsClient client = EcsClient.newBuilder() .withCredential(auth) .withRegion(region) .build(); ``` ###### 3.3.2.2 环境变量 [:top:](#用户手册-top) 通过环境变量配置,格式为`HUAWEICLOUD_SDK_REGION_{SERVICE_NAME}_{REGION_ID}={endpoint}` 注:环境变量名全大写,中划线替换为下划线 ``` // 以ECS和IoTDA服务为例 // linux export HUAWEICLOUD_SDK_REGION_ECS_CN_NORTH_9=https://ecs.cn-north-9.myhuaweicloud.com export HUAWEICLOUD_SDK_REGION_IOTDA_AP_SOUTHEAST_1=https://iotda.ap-southwest-1.myhuaweicloud.com // windows set HUAWEICLOUD_SDK_REGION_ECS_CN_NORTH_9=https://ecs.cn-north-9.myhuaweicloud.com set HUAWEICLOUD_SDK_REGION_IOTDA_AP_SOUTHEAST_1=https://iotda.ap-southwest-1.myhuaweicloud.com ``` 从**3.1.62**版本起,支持配置一个region对应多个endpoint,主要endpoint无法连接会自动切换到备用endpoint 格式为`HUAWEICLOUD_SDK_REGION_{SERVICE_NAME}_{REGION_ID}={endpoint1},{endpoint2}`, 多个endpoint之间用英文逗号隔开, 比如`HUAWEICLOUD_SDK_REGION_ECS_CN_NORTH_9=https://ecs.cn-north-9.myhuaweicloud.com,https://ecs.cn-north-9.myhuaweicloud.cn` ###### 3.3.2.3 文件配置 [:top:](#用户手册-top) 通过yaml文件配置,默认会从用户主目录下读取region配置文件,linux为`~/.huaweicloud/regions.yaml`,windows为`C:\Users\USER_NAME\.huaweicloud\regions.yaml`,默认配置文件可以不存在,但是如果配置文件存在且内容格式不对会解析错误抛出异常。 可以通过配置环境变量`HUAWEICLOUD_SDK_REGIONS_FILE`来修改默认文件的路径,如`HUAWEICLOUD_SDK_REGIONS_FILE=/tmp/my_regions.yml` 文件内容格式如下: ```yaml # 服务名不区分大小写 ECS: - id: 'cn-north-1' endpoint: 'https://ecs.cn-north-1.myhuaweicloud.com' - id: 'cn-north-9' endpoint: 'https://ecs.cn-north-9.myhuaweicloud.com' IoTDA: - id: 'ap-southwest-1' endpoint: 'https://iotda.ap-southwest-1.myhuaweicloud.com' ``` 从**3.1.62**版本起,支持配置一个region对应多个endpoint,主要endpoint无法连接会自动切换到备用endpoint,格式如下: ```yaml ECS: - id: 'cn-north-1' endpoints: - 'https://ecs.cn-north-1.myhuaweicloud.com' - 'https://ecs.cn-north-1.myhuaweicloud.cn' ``` ###### 3.3.2.4 Region提供链 [:top:](#用户手册-top) **Region.valueOf(regionId)** 方法默认查找顺序为 **环境变量 -> 配置文件 -> SDK中已定义Region**,以上方式都找不到region会抛出异常 **IllegalArgumentException**,获取region示例: ```java import com.huaweicloud.sdk.core.region.Region; import com.huaweicloud.sdk.ecs.v2.region.EcsRegion; Region region1 = EcsRegion.valueOf("cn-north-1"); Region region2 = EcsRegion.valueOf("cn-north-9"); ``` ### 4. 发送请求并查看响应 [:top:](#用户手册-top) ``` java // 初始化请求,以调用接口 ListVpcs 为例 ListVpcRequest request = new ListVpcsRequest().withLimit(1); ListVpcsResponse response = client.listVpcs(request); logger.info(response.toString()); ``` #### 4.1 异常处理 [:top:](#用户手册-top) | 一级分类 | 一级分类说明 | 二级分类 | 二级分类说明 | | :---- | :---- | :---- | :---- | | ConnectionException | 连接类异常 | HostUnreachableException | 网络不可达、被拒绝 | | | | SslHandShakeException | SSL认证异常 | | | | ConnectionTimeoutException | 连接超时异常 | | RequestTimeoutException | 响应超时异常 | CallTimeoutException | 单次请求,服务器处理超时未返回,包括读写超时等异常 | | | | RetryOutageException | 在重试策略消耗完成已后,仍无有效的响应 | | ServiceResponseException | 服务器响应异常 | ServerResponseException | 服务端内部错误,Http响应码:[500,] | | | | ClientRequestException | 请求参数不合法,Http响应码:[400, 500) | ``` java // 异常处理 try { ListVpcRequest request = new ListVpcsRequest().withLimit(1); ListVpcsResponse response = client.listVpcs(request); logger.info(response.toString()); } catch(ServiceResponseException e) { logger.error("HttpStatusCode: " + e.getHttpStatusCode()); logger.error("RequestId: " + e.getRequestId()); logger.error("ErrorCode: " + e.getErrorCode()); logger.error("ErrorMsg: " + e.getErrorMsg()); } ``` ### 5. 异步客户端使用 [:top:](#用户手册-top) ``` java // 初始化异步客户端,以初始化 VpcAsyncClient 为例 VpcAsyncClient vpcAsyncClient = VpcAsyncClient.newBuilder() .withCredential(basicCredentials) .withEndpoint(endpoint) .build(); // 发送异步请求 CompletableFuture future = vpcAsyncClient.listVpcsAsync(new ListVpcsRequest().withLimit(1)); // 获取异步请求结果 ListVpcsResponse response = future.get(); ``` ### 6. 故障处理 [:top:](#用户手册-top) SDK 提供 Access 级别的访问日志及 Debug 级别的原始 HTTP 监听器日志,用户可根据需要进行配置。 #### 6.1 访问日志 [:top:](#用户手册-top) **注意:** SDK在运行的时候默认采用slf4j的实现库进行日志打印,如果在运行代码实例时,未配置日志实现库,会有提示如下: ``` text SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. ``` *更多关于使用slf4j的常见问题请参阅: [Frequently Asked Questions about SLF4J](https://www.slf4j.org/faq.html)* SDK支持的slf4j与对应的日志实现的版本关系,如下表所示: | slf4j-api | logback-classic | slf4j-log4j12 | slf4j-simple | slf4j-jdk14 | |-----------|-----------------|---------------|--------------|-------------| | 1.7.x | 1.2.x | 1.6.x/1.7.x | 1.6.x/1.7.x | 1.6.x/1.7.x | 用户需要根据目标项目实际情况引入对应的日志实现,请在对应的工程项目的 pom.xml 文件中引入日志实现的依赖,如: **logback** ``` xml ch.qos.logback logback-classic 1.3.12 ``` **log4j** ``` xml org.slf4j slf4j-log4j12 1.7.36 ``` **slf4j simple** ``` xml org.slf4j slf4j-simple 1.7.36 ``` **jul** ``` xml org.slf4j slf4j-jdk14 1.7.36 ``` SDK 默认会打印访问日志,每次请求都会有一条记录: ``` text 16:53:04.905 [main] INFO HuaweiCloud-SDK-Access - "GET https://ecs.cn-southwest-2.myhuaweicloud.com/v1/077d6a6c19000fdd2f3bc00150080291/cloudservers/detail?offset=1&limit=25" 200 2251 deabe20c14f997a0291fc451a4da16a4 233 16:53:06.212 [main] INFO HuaweiCloud-SDK-Access - "PUT https://ecs.cn-southwest-2.myhuaweicloud.com/v1/077d6a6c19000fdd2f3bc00150080291/cloudservers/1aeac6fb-a2f2-48dc-9052-36637d119dd3" 200 880 f16f70e3fe245c11ab741760f8689a01 234 17:02:37.734 [main] INFO HuaweiCloud-SDK-Access - "GET https://ecs.cn-southwest-2.myhuaweicloud.com/v1/077d6a6c19000fdd2f3bc00150080291/cloudservers/detail?offset=1&limit=-1" 400 165 8c3c8b6fed4482d28e1929a78dc93f04 235 ``` 日志名称为 "HuaweiCloud-SDK-Access" , 日志格式为: ``` text "{httpMethod} {uri}" {httpStatusCode} {responseContentLength} {requestId} {durationMs} ``` 其中 requestId 是华为云 API Gateway 返回的请求 ID ,可以用于用户报障或者问题跟踪。 可以根据项目情况在对应的日志配置文件中对访问日志进行屏蔽,或者单独打印到独立文件中。 例如在 logback 中关闭访问日志: ``` xml ``` #### 6.2 HTTP 监听器 [:top:](#用户手册-top) 在某些场景下可能对业务发出的 HTTP 请求进行 Debug ,需要看到原始的 HTTP 请求和返回信息, SDK 提供监听器功能来获取原始的为加密的 HTTP 请求和返回信息。 > :warning: Warning: 原始信息打印仅在 Debug 阶段使用,请不要在生产系统中打印原始的 HTTP 头和 Body 信息,这些信息并未加密且其中包含敏感数据,例如所创建虚拟机的密码,IAM 用户的密码等;当 Body 体为二进制内容,即 Content-Type 标识为二进制时,Body 为"***",详细内容不输出。 ``` java import com.huaweicloud.sdk.core.HttpListener; import com.huaweicloud.sdk.core.http.HttpConfig; HttpConfig httpConfig = HttpConfig.getDefaultHttpConfig(); // 注册监听器后打印原始请求信息,请勿用于生产环境 HttpListener requestListener = HttpListener.forRequestListener(listener -> System.out.printf("> Request %s %s\n> Headers:\n%s\n> Body: %s\n", listener.httpMethod(), listener.uri(), listener.headers().entrySet().stream() .flatMap(entry -> entry.getValue().stream().map( value -> "\t" + entry.getKey() + ": " + value)) .collect(Collectors.joining("\n")), listener.body().orElse(""))); httpConfig.addHttpListener(requestListener); // 注册监听器后打印原始响应信息,请勿用于生产环境 HttpListener responseListener = HttpListener.forResponseListener(listener -> System.out.printf("< Response %s %s %s\n< Headers:\n%s\n< Body: %s\n", listener.httpMethod(), listener.uri(), listener.statusCode(), listener.headers().entrySet().stream() .flatMap(entry -> entry.getValue().stream().map( value -> "\t" + entry.getKey() + ": " + value)) .collect(Collectors.joining("\n")), listener.body().orElse(""))); httpConfig.addHttpListener(responseListener); VpcClient vpcClient = VpcClient.newBuilder() .withHttpConfig(httpConfig) .build(); ``` ### 7. 接口调用器 [:top:](#用户手册-top) #### 7.1 自定义请求头 [:top:](#用户手册-top) 可以根据需要灵活地配置请求头域参数,非必要**请勿**指定诸如`Host`、`Authorization`、`User-Agent`、`Content-Type`等通用请求头,可能会导致接口调用错误。 ``` java EcsClient client = EcsClient.newBuilder() .withCredential(basicCredentials) .withRegion(EcsRegion.CN_NORTH_4) .build(); String jobId = "{valid job id}"; ShowJobRequest request = new ShowJobRequest().withJobId(jobId); try { ShowJobResponse response = client.showJobInvoker(request) // 自定义请求头 .addHeader("key1", "value1") .addHeader("key2", "value2") .invoke(); logger.info(response.toString()); } catch (SdkException e) { logger.error("", e); } ``` #### 7.2 请求重试 [:top:](#用户手册-top) 当请求遇到网络异常或者流控场景的时候,通常需要对请求进行重试。Java SDK 提供了请求重试的入口,可用于请求方式为 `GET` 的请求。重试配置支持同步客户端和异步客户端,如需使用重试,需要配置最大重试次数、重试条件和重试策略。其中, - _最大重试次数_:30 次,可设置任意不大于 30 的正整数 - _重试条件_:lambda 函数,提供默认的重试条件,会对 ConnectionException 进行重试,关键代码如下: ``` java /** * 默认重试条件,当请求响应状态异常,并且异常类型为 ConnectionException 及其子类时,会执行重试 * * @param 响应类的泛型 * @return BiFunction 返回值为布尔类型的 true / false */ public static BiFunction defaultRetryCondition() { return (resp, exception) -> { if (Objects.nonNull(exception)) { return ConnectionException.class.isAssignableFrom(exception.getClass()); } return false; }; } ``` - _重试策略_:每次重试前的等待时间,提供默认的 SdkBackoffStrategy 策略,采用(随机数 + 指数退避)的算法计算下次重试前的等待时间。 以下将针对不同的场景介绍重试的具体使用。 ##### 7.2.1 同步客户端请求重试 [:top:](#用户手册-top) 在同步客户端中使用重试,需要使用 {Service}Client 中提供的 invoker 方法,SDK 对连接超时类的异常提供了默认的重试条件,用户可以直接调用。 以 ECS 服务的 `ShowJob` 接口为例,最多重试5次,使用默认重试条件,代码如下: ``` java // 初始化同步客户端 EcsClient client = EcsClient.newBuilder() .withCredential(basicCredentials) .withRegion(EcsRegion.CN_NORTH_4) .build(); String jobId = "{valid job id}"; ShowJobRequest request = new ShowJobRequest().withJobId(jobId); try { ShowJobResponse response = client.showJobInvoker(request) // 请求最大重试次数 .retryTimes(5) // 请求重试条件,默认的重试条件为网络连接异常自动重试 .retryCondition(BaseInvoker.defaultRetryCondition()) .invoke(); logger.info(response.toString()); } catch (SdkException e) { logger.error("", e); } ``` ##### 7.2.2 异步客户端请求重试 [:top:](#用户手册-top) 在异步客户端中使用重试,需要使用 {Service}Client 中提供的 invoker 方法,SDK 对连接超时类的异常提供了默认的重试条件,用户可以直接调用。 以 ECS 服务的 `ShowJob` 接口为例,最多重试5次,使用默认重试条件,代码如下: ``` java // 初始化异步客户端 EcsAsyncClient asyncClient = EcsAsyncClient.newBuilder() .withCredential(basicCredentials) .withRegion(EcsRegion.CN_NORTH_4) .build(); String jobId = "{valid job id}"; ShowJobRequest request = new ShowJobRequest().withJobId(jobId); try { ShowJobResponse response = asyncClient.showJobAsyncInvoker(request) // 请求最大重试次数 .retryTimes(5) // 请求重试条件,默认的重试条件为网络连接异常自动重试 .retryCondition(BaseInvoker.defaultRetryCondition()) .invoke(); logger.info(response.toString()); } catch (SdkException e) { logger.error("", e); } ``` ##### 7.2.3 典型重试场景调用示例 [:top:](#用户手册-top) **场景1**:当接口响应状态码为 500(服务器端异常) 或者 429(服务器端流控) 时,对请求进行重试。示例代码如下: ``` java String jobId = "{valid job id}"; ShowJobRequest request = new ShowJobRequest().withJobId(jobId); try { ShowJobResponse response = client.showJobInvoker(request) .retryTimes(3) .retryCondition( (resp, ex) -> Objects.nonNull(ex) && ServiceResponseException.class.isAssignableFrom(ex.getClass()) && (((ServiceResponseException) ex).getHttpStatusCode() == 429 || ((ServiceResponseException) ex).getHttpStatusCode() == 500)) .invoke(); logger.info(response.toString()); } catch (InterruptedException e) { logger.error("InterruptedException", e); } catch (ExecutionException e) { logger.error("ExecutionException", e); } ``` **场景2**:针对 job 指定状态进行重试,如 job 状态为成功时停止重试,执行下一步操作。示例代码如下: ``` java String jobId = "{valid job id}"; ShowJobRequest request = new ShowJobRequest().withJobId(jobId); try { // 退避等待的基础时间(毫秒) final int baseDelay = 1000; // 退避等待的最长时间 final int maxBackoffInMilliseconds = 30000; ShowJobResponse response = client.showJobInvoker(request) // 请求最大重试次数 .retryTimes(10) // 请求重试条件,将重试条件设置为job状态是success的时候停止重试 .retryCondition((resp, ex) -> Objects.nonNull(resp) && !resp.getStatus().equals(ShowJobResponse.StatusEnum.SUCCESS)) // 请求退避策略,计算每次请求失败后下次的请求时间,轮询 job 状态需要设置较长的基础等待时间 .backoffStrategy(new SdkBackoffStrategy(baseDelay, maxBackoffInMilliseconds)) .invoke(); logger.info(response.toString()); } catch (SdkException e) { logger.error("", e); } ``` ### 8. 文件上传与下载 [:top:](#用户手册-top) #### 8.1 上传与下载 [:top:](#用户手册-top) 以数据安全中心服务的嵌入图片水印接口为例,该接口需要上传一个图片文件,并返回加过水印的图片文件流: ```java package com.huaweicloud.sdk.test; import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.dsc.v1.DscClient; import com.huaweicloud.sdk.dsc.v1.model.CreateImageWatermarkRequest; import com.huaweicloud.sdk.dsc.v1.model.CreateImageWatermarkRequestBody; import com.huaweicloud.sdk.dsc.v1.model.CreateImageWatermarkResponse; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.function.Consumer; public class CreateImageWatermarkDemo { public static void createImageWatermark(DscClient client) throws IOException { CreateImageWatermarkRequest request = new CreateImageWatermarkRequest(); // 创建File对象和FileInputStream对象 File file = new File("demo.jpg"); FileInputStream fis = new FileInputStream(file); CreateImageWatermarkRequestBody body = new CreateImageWatermarkRequestBody() // 文件传参 .withFile(fis, file.getName()) .withBlindWatermark("test123"); request.setBody(body); CreateImageWatermarkResponse response = client.createImageWatermark(request); fis.close(); //下载文件的consumer Consumer consumer = inputStream -> { try { FileOutputStream out = new FileOutputStream("result.jpg"); byte[] data = new byte[1024]; int len = 0; while ((len = inputStream.read(data))!= -1) { out.write(data, 0, len); } inputStream.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } }; //下载文件 response.consumeDownloadStream(consumer); } public static void main(String[] args) throws IOException { String ak = System.getenv("HUAWEICLOUD_SDK_AK"); String sk = System.getenv("HUAWEICLOUD_SDK_SK"); String endpoint = "{your endpoint string}"; String projectId = "{your project id}"; BasicCredentials auth = new BasicCredentials() .withAk(ak) .withSk(sk) .withProjectId(projectId); DscClient client = DscClient.newBuilder() .withCredential(auth) .withEndpoint(endpoint) .build(); createImageWatermark(client); } } ``` #### 8.2 获取进度 [:top:](#用户手册-top) 以对象存储服务的上传对象和下载对象接口为例: ```java package com.huaweicloud.sdk.test; import com.huaweicloud.sdk.obs.v1.ObsClient; import com.huaweicloud.sdk.obs.v1.ObsCredentials; import com.huaweicloud.sdk.obs.v1.model.GetObjectRequest; import com.huaweicloud.sdk.obs.v1.model.GetObjectResponse; import com.huaweicloud.sdk.obs.v1.model.PutObjectRequest; import com.huaweicloud.sdk.obs.v1.model.PutObjectResponse; import com.huaweicloud.sdk.obs.v1.region.ObsRegion; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.function.Consumer; public class ObsDemo { // 上传对象 public static void putObject(ObsClient client) throws IOException { PutObjectRequest request = new PutObjectRequest().withBucketName("bucketname").withObjectKey("objectname"); FileInputStream fileInputStream = new FileInputStream("/tmp/file-to-upload"); request.setUploadStream(fileInputStream); request.setProgressListener(progressStatus -> { // 获取上传平均速率(B/S) System.out.println("AverageSpeed:" + progressStatus.getAverageSpeed()); // 获取上传进度百分比 System.out.println("TransferPercentage:" + progressStatus.getTransferPercentage()); }); // 每上传1MB数据反馈进度 request.setProgressInterval(1024 * 1024L); PutObjectResponse response = client.putObject(request); System.out.println(response.getHttpStatusCode()); fileInputStream.close(); } // 下载对象 public static void getObject(ObsClient client) { GetObjectRequest request = new GetObjectRequest().withBucketName("bucketname").withObjectKey("objectname"); request.setProgressListener(progressStatus -> { // 获取下载平均速率(B/S) System.out.println("AverageSpeed:" + progressStatus.getAverageSpeed()); // 获取下载进度百分比 System.out.println("TransferPercentage:" + progressStatus.getTransferPercentage()); }); // 每下载1MB数据反馈进度 request.setProgressInterval(1024 * 1024L); GetObjectResponse response = client.getObject(request); System.out.println(response.getHttpStatusCode()); //下载文件的consumer Consumer consumer = inputStream -> { try { FileOutputStream out = new FileOutputStream("/tmp/downloaded-file"); byte[] data = new byte[1024]; int len; while ((len = inputStream.read(data)) != -1) { out.write(data, 0, len); } inputStream.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } }; response.consumeDownloadStream(consumer); } public static void main(String[] args) throws IOException { ObsCredentials credentials = new ObsCredentials() .withAk(System.getenv("HUAWEICLOUD_SDK_AK")) .withSk(System.getenv("HUAWEICLOUD_SDK_SK")); ObsClient client = ObsClient.newBuilder() .withCredential(credentials) .withRegion(ObsRegion.valueOf("cn-north-1")) .build(); putObject(client); getObject(client); } } ``` ### 9. FAQ [:top:](#用户手册-top) #### 9.1 云联盟场景如何调用 [:top:](#用户手册-top) ```java // 初始化客户端认证信息,需要填写相应 projectId/domainId,以初始化 BasicCredentials 为例 BasicCredentials basicCredentials = new BasicCredentials() // 请使用华为云AK/SK, 非云联盟AK/SK .withAk(ak) .withSk(sk) .withProjectId(projectId); // 初始化指定云服务的客户端 {Service}Client,以初始化 Region 级服务 VPC 的 VpcClient 为例 VpcClient vpcClient = VpcClient.newBuilder() .withCredential(basicCredentials) // 指定终端节点,以 云联盟都柏林节点调用 VPC 服务为例 .withEndpoint("https://vpc.eu-west-101.myhuaweicloud.com") .build(); ```