

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用自定义计量将您的容器产品与 AWS Marketplace Metering Service 和集成 适用于 Java 的 AWS SDK
<a name="java-integration-example-meterusage"></a>

AWS Marketplace 集装箱产品可以对每种产品多达 24 种不同的定价维度进行自定义计量。要启用自定义计量，请将您的容器产品与 AWS Marketplace Metering Service 集成。您可以使用 [https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html) API 操作为该用量定义自己的定价单位和自定义计量以便 AWS 进行计费。以下示例概述了使用与[AWS Marketplace 计量服务](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html)`MeterUsage`操作集成的实现。 适用于 Java 的 AWS SDK 

有关完整的详细信息，请参阅 [`MeterUsage` Java 示例](#meterusage-java-example)。以下步骤中的许多步骤适用于任何语言。

**示例： AWS Marketplace 计量服务集成**

1. 登录到 [AWS Marketplace 管理门户](https://aws.amazon.com/marketplace/management/tour)。

1. 从**资产**中，选择**容器**以开始创建新容器产品。创建产品会生成产品的产品代码以与您的容器映像集成。有关设置 AWS Identity and Access Management (IAM) 权限的信息，请参阅[AWS Marketplace 计量和授权 API 权限](iam-user-policy-for-aws-marketplace-actions.md)。

1.  下载公开的 [AWS Java SDK](https://aws.amazon.com/sdk-for-java/)。
**重要**  
 要从 Amazon Elastic Kubernetes Service (Amazon EKS) 调用计量 API 操作，您必须[使用支持的](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html) AWS SDK 并在运行 Kubernetes 1.13 或更高版本的 Amazon EKS 集群上运行。

1. 针对每个维度使用情况，每小时从任务或容器组 (pod) 调用一次 `MeterUsage` 操作。此 API 操作对于 `Dimension`、`Resource` 和 `Hour` 的唯一组合接受一个计量记录。资源要么是 Amazon Elastic Container Service (Amazon ECS) 任务，要么是 Amazon EKS 容器组 (pod)。

   ```
   {
       "ProductCode" : "string", // (required)
       "UsageDimension" : "string", // (required)
       "UsageQuantity":  int, // (optional) Default is 0. Acceptable value from [0, 2147483647 (INT_MAX)]
       "Timestamp": Date, // (required) Timestamp in UTC. Value can be one hour in the past.
       "UsageAllocations": List<UsageAllocation> // (optional) UsageAllocations across 1 or more tags.
   }
   ```
**注意**  
在连接时可能会出现暂时性问题 AWS Marketplace Metering Service。 AWS Marketplace 强烈建议实施最长 30 分钟的重试，并以指数级退缩，以避免短期中断或网络问题。

1. 重建包含 `MeterUsage` 调用的新版本容器映像，标记容器，然后将其推送至与 Amazon ECS 或 Amazon EKS 兼容的任何 Docker 注册表，如 Amazon Elastic Container Registry (Amazon ECR)。如果您使用的是 Amazon ECR，请确保启动 Amazon ECS 任务或 Amazon EKS 容器组 (pod) 的账户对 Amazon ECR 存储库拥有权限。否则，该操作将失败。

1. 创建一个 [IAM](https://aws.amazon.com/iam/) 角色来授予容器调用 `MeterUsage` 的权限，如以下代码示例所定义。您必须在 Amazon ECS 任务的[任务角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn)参数或 Amazon EKS 容器定义中提供此 AWS Identity and Access Management (IAM) 角色。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Action": [
                   "aws-marketplace:MeterUsage"
                   ],
                   "Effect": "Allow",
                   "Resource": "*"
           }
       ]
   }
   ```

------

1. 创建 Amazon ECS 任务或 Amazon EKS 容器定义，引用已与您在步骤 6 中创建的 IAM 角色集成的容器 AWS Marketplace 并引用该角色。如果要查看日志记录，请在任务定义中启用 AWS CloudTrail 日志记录。

1. 创建 Amazon ECS 或 Amazon EKS 集群来运行您的任务或容器组 (pod)。有关创建 Amazon ECS 集群的更多信息，请参阅《Amazon Elastic Container Service 开发人员指南》**中的[创建集群](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html)。有关（使用 Kubernetes 版本 1.1.3.x 或更高版本）创建 Amazon EKS 集群的更多信息，请参阅[创建 Amazon EKS 集群](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html)。

1. 配置 Amazon ECS 或 Amazon EKS 集群，然后在 us-east-1 AWS 区域启动您在步骤 8 中创建的 Amazon ECS 任务定义或亚马逊 EKS 容器。只有在此测试过程中，在产品上线之前，您才必须使用此区域。

1. 当您从正在为产品发布的每个维度的 `MeterUsage` 获得有效相应时，您可以开始创建容器产品。如有问题，请联系 [AWS Marketplace 卖家运营](https://aws.amazon.com/marketplace/management/contact-us/)团队。

## `MeterUsage` Java 示例
<a name="meterusage-java-example"></a>

以下代码示例使用 适用于 Java 的 AWS SDK 和 AWS Marketplace 计量服务来调用该`MeterUsage`操作。

使用以下示例代码调用 `MeterUsage` 操作，不设置 `UsageAllocations`。

```
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMetering;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder;
import com.amazonaws.services.marketplacemetering.model.MeterUsageRequest;
import com.amazonaws.services.marketplacemetering.model.MeterUsageResult;

import java.util.Date;

public class MeterUsage {
    private static final String PRODUCT_CODE = ".......";
    private final AWSMarketplaceMetering awsMarketplaceMetering;

    public MeterUsage() {
        awsMarketplaceMetering = AWSMarketplaceMeteringClientBuilder.standard().build();
    }

    /**
     * Submits metering record for a FCP Dimension. The API accepts 1 metering record per dimension
     * for a given buyer's resource for a given timestamp hour. Ex. If a buyer is running 10 tasks,
     * the API will accepts 1 call to MeterUsage in an hour for a given dimension for each running task.
     *
     * @param dimension - FCP dimension name provided during the publishing of the product.
     * @param quantity - FCP dimension consumption value for the hour.
     * @param timestamp - Timestamp, in UTC, for which the usage is being reported.
     *                  Timestamp cant be more than 1 hour in the past.
     *                  Make sure the timestamp value is not before the start of the software usage.
     */
    public void callMeterUsage(String dimension, int quantity, Date timestamp) {
        MeterUsageRequest meterUsageRequest = new MeterUsageRequest()
                .withProductCode(PRODUCT_CODE)
                .withUsageDimension(dimension)
                .withUsageQuantity(quantity)
                .withTimestamp(timestamp);
        MeterUsageResult meterUsageResult = awsMarketplaceMetering.meterUsage(meterUsageRequest);
    }
}
```

使用以下示例代码调用 `MeterUsage` 操作，设置 `UsageAllocations`。

```
private static String callMeterUsageWithAllocationsByTag(AWSMarketplaceMetering marketplaceMetering) {
        // Tag Keys for the product
        String tagKey1 = "Key1";
        String tagKey2 = "Key2";
        String tagKey3 = "Key3";

        // 1st Usage Allocation bucket which has two Tags [{Key1, Key1Value1},{Key2, Key2Value1}]
        List<Tag> tagsForUsageAllocation1 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value1"),
                new Tag().withKey(tagKey2).withValue("Key2Value1"));
        UsageAllocation usageAllocation1 = new UsageAllocation()
                .withTags(tagsForUsageAllocation1)
                .withAllocatedUsageQuantity(20);

        // 2nd Usage Allocation bucket which has two Tags [{Key1, Key1Value2},{Key2, Key2Value1}]
        List<Tag> tagsForUsageAllocation2 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value2"),
                new Tag().withKey(tagKey2).withValue("Key2Value1"));
        UsageAllocation usageAllocation2 = new UsageAllocation()
                .withTags(tagsForUsageAllocation2)
                .withAllocatedUsageQuantity(20);

        // 3rd Usage Allocation bucket which has two Tags [{Key1, Key1Value2},{Key2, Key2Value2},{Key3, Key3Value1}]
        List<Tag> tagsForUsageAllocation3 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value2"),
                new Tag().withKey(tagKey2).withValue("Key2Value2"),
                new Tag().withKey(tagKey3).withValue("Key3Value1"));
        UsageAllocation usageAllocation3 = new UsageAllocation()
                .withTags(tagsForUsageAllocation3)
                .withAllocatedUsageQuantity(15);

        // 4th Usage Allocation bucket with no tags
        UsageAllocation usageAllocation4 = new UsageAllocation()
                .withAllocatedUsageQuantity(15);

        List<UsageAllocation> usageAllocationList = Arrays.asList(usageAllocation1,
                usageAllocation2,
                usageAllocation3,
                usageAllocation4);

        MeterUsageRequest meterUsageRequest = new MeterUsageRequest()
                .withProductCode("TestProductCode")
                .withUsageDimension("Dimension1")
                .withTimestamp(new Date())
                //UsageQuantity value must match with sum of all AllocatedUsageQuantity
                .withUsageQuantity(70)
                .withUsageAllocations(usageAllocationList);

        MeterUsageResult meterUsageResult;
        try {
            meterUsageResult = marketplaceMetering.meterUsage(meterUsageRequest);
        } catch (Exception e) {
            // Log Error
            throw e;
        }

        return meterUsageResult.getMeteringRecordId();
    }
```