合作伙伴调用合作伙伴中心 Api 的 API 限制指南

Microsoft 正在实施 API 限制,为调用合作伙伴中心 Api 的合作伙伴提供一段时间内更一致的性能。 限制将限制对某个时间段内某个服务的请求数,以防止过度使用资源。 虽然合作伙伴中心设计用于处理大量请求,但如果有大量的请求发生了大量请求,则限制有助于为所有合作伙伴保持最佳性能和可靠性。

限制值因情况而异。 例如,如果正在执行大量写入,则发生限制的可能性会比仅执行读取高。

发生限制时,会出现什么情况?

超出限制阈值时,合作伙伴中心会在一段时间内限制来自该客户端的任何后续请求。 限制行为取决于请求的类型和数量。

常见限制方案

客户端限制的最常见原因包括:

  • 每个合作伙伴租户 Id 有大量的 API 请求:对于某些合作伙伴中心 api,限制是由合作伙伴租户 id 决定的,对同一合作伙伴租户 id 上的这些 api 进行太多调用将导致超出限制阈值。

  • 每个客户租户 id 每个合作伙伴租户 id 的 API 请求数为:对于其他 api,限制由合作伙伴租户 Id/客户租户 id 组合决定;在这些情况下,对同一客户租户 ID 进行太多调用将导致限制,而对其他客户的调用可能会成功。

避免限制的最佳实践

诸如连续轮询资源以检查是否有新的或已删除的资源的编程做法,更有可能导致限制并降低整体性能。 并发 API 调用可能会导致每个单元时间有大量请求,这也会导致请求受到限制。 应改为使用更改跟踪和更改通知。 此外,您应该能够使用活动日志来检测更改。 有关详细信息,请参阅 合作伙伴中心活动日志。 我们强烈建议合作伙伴考虑使用活动日志 API 以提高效率并避免限制。 另请参阅下面的使用活动日志的示例。

处理限制的最佳做法

下面是有关处理限制的最佳方案:

  • 降低并行度。
  • 减少调用频率。
  • 避免立即重试,因为所有请求的使用限制都会受到限制。

实现错误处理时,请使用 HTTP 错误代码 429 检测限制。 失败的响应包含重试间隔响应标头。 使用在延迟一段时间后重试来回退请求是从限制中恢复的最快方法。

若要使用 "重试间隔",请执行以下操作:

  1. 等待 Retry-After 标头中指定的秒数。

  2. 重试请求。

  3. 如果请求再次失败并出现 429 错误代码,则表示你仍然受到请求限制。 使用指数回退重试,使用建议的 Retry-After 延迟,然后重试请求,直到成功为止。

  4. 如果你使用的是 SDK,则当你的请求受到限制时,你将收到一个异常,状态代码为429。 请在异常中使用 RetryAfter 属性,然后在经过一段时间后重试该请求。

当前受限制影响的 Api

最终,每个调用终结点 "api.partnercenter.microsoft.com/" 的单个合作伙伴中心 API 都将受到限制。 目前,阻止限制仅适用于下面列出的 Api。 合作伙伴中心将收集每个 Api 的遥测数据,并动态调整限制。 下表列出了当前强制执行限制的 Api。

操作 合作伙伴中心文档
{baseURL}/v1/customers/{customer_id}/orders 创建订单
{baseURL}/v1/customers/{customer-tenant-id}/subscriptions/{id-for-subscription}/upgrades 转换订阅
{baseURL}/v1/customers/{customer-tenant-id}/orders/{order-id} 购买订阅的加载项
{baseURL}/v1/customers/{customer-id}/carts/{cart-id} 创建购物车
{baseURL}/v1/customers/{customer-id}/carts/{cart-id}/checkout 结帐购物车
{baseURL}/v1/customers/{customer-id}/carts/{cart-id} 更新购物车
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/registrations 注册订阅
{baseURL}/v1/productupgrades 创建产品升级实体
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/conversions 将试用订阅转换为付费订阅
{baseURL}/v1/customers/{customer-tenant-id} 按 ID 获取客户
{baseURL}/v1/productUpgrades/eligibility 获取产品升级的资格
{baseURL}/v1/customers/{customer-tenant-id}/subscriptions/{id-for-subscription} 管理订阅
{baseURL}/v1/customers/{customer_id}/subscriptions 获取-所有客户-s-订阅
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id} 根据 ID 获取订阅
{baseURL}/v1/customers/{customer_id}/orders 获取所有客户订单
{baseURL}/v1/customers/{customer_id}/orders/{order_id} 按 ID 获取订单
{baseURL}/v1/customers/{customer_id}/orders/{order_id}/provisioningstatus 获取订阅预配状态
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id} 管理订单和订阅
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/addons 获取订阅的加载项列表
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/azureEntitlements 获取订阅的 Azure 权利列表
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/registrationstatus 获取订阅注册状态
{baseURL}/v1/customers/{customer-tenant-id}/transfers 获取客户的所有转让
{baseURL}/v1/productUpgrades/{upgrade-id}/status 获取产品升级状态
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/conversions 获取试用版转换产品/服务的列表
{baseURL}/v1/customers/{customer-tenant-id}/migrations/newcommerce/validate 验证要迁移的订阅
{baseURL}/v1/customers/{customer-tenant-id}/migrations/newcommerce 创建向新商务体验的迁移

错误代码响应:

HTTP/1.1 429 Too Many Requests 

Content-Length: 84 

Content-Type: application/json 

Retry-After: 57 

Date: Tue, 21 Jul 2020 04:10:58 GMT 

{ "statusCode": 429, "message": "Rate limit is exceeded. Try again in 57 seconds." } 

活动日志的示例

为分析每日更改的最佳做法,我们建议你查询特定日期的审核记录。 

在响应中,你将获得对特定操作类型的更改的结果。  您可以基于所关注的操作进行筛选。  例如,如果对新创建的客户感兴趣,可以查看 operationType = "add_customer"。  

可在下面的 API 文档中找到 operationtype/资源列表。

响应示例

请求

Http Get call:  https://api.partnercenter.microsoft.com/v1/auditrecords?startDate=2020-09-02&endDate=2020-09-02&size=50 

Authorization: Bearer <token> 

Accept: application/json 

MS-RequestId: 127facaa-e389-41f8-8bb7-1d1af99db893 

MS-CorrelationId: de9c2ccc-40dd-4186-9660-65b9b64c3d14 

X-Locale: en-US 

Host: api.partnercenter.microsoft.com 

Connection: Keep-Alive 

响应

{ 

    "totalCount": 17, 

    "items": [ 

        { 

            "id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_e905b566-4779-4e57-944c-7b1b5312705b_updatecustomeruserlicenses_637346859797753934", 

            "partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d", 

            "participants": [ 

                "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d" 

            ], 

            "customerId": "e905b566-4779-4e57-944c-7b1b5312705b", 

            "userPrincipalName": "admin@testsw09.onmicrosoft.com", 

            "applicationId": "FulfillmentService", 

            "resourceType": "license", 

            "operationType": "update_customer_user_licenses", 

            "operationDate": "2020-09-02T23:26:19.7753934Z", 

            "operationStatus": "succeeded", 

            "customizedData": [ 

                { 

                    "key": "CustomerUserId", 

                    "value": "933808c7-b165-496c-a24e-1a4b7846fab4" 

                } 

            ], 

            "attributes": { 

                "objectType": "AuditRecord" 

            } 

        }, 

        { 

            "id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_86bddccf-9a53-40c6-907c-08067a3f8da7_ia80zlkxp6ewoqpp35pbqjlhqv9iigvz1_createorder_637346662909268372", 

            "partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d", 

            "participants": [ 

                "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d" 

            ], 

            "customerId": "86bddccf-9a53-40c6-907c-08067a3f8da7", 

            "customerName": "CustomMetersStagingTest", 

            "userPrincipalName": "admin@testsw09.onmicrosoft.com", 

            "applicationId": "4990cffe-04e8-4e8b-808a-1175604b879f", 

            "resourceType": "order", 

            "resourceNewValue": "{\"Id\":\"Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"AlternateId\":\"64144d300bde\",\"ReferenceCustomerId\":\"86bddccf-9a53-40c6-907c-08067a3f8da7\",\"BillingCycle\":\"monthly\",\"CurrencyCode\":\"USD\",\"CurrencySymbol\":\"$\",\"LineItems\":[{\"LineItemNumber\":0,\"ProvisioningContext\":null,\"OfferId\":\"DZH318Z0C964:0001:DZH318Z0BZDG\",\"SubscriptionId\":\"f428d44a-d08b-348b-579e-ce92a6362c7b\",\"ParentSubscriptionId\":null,\"TermDuration\":\"P1M\",\"TransactionType\":\"New\",\"FriendlyName\":\"SaaS custom meter offer - Bronze\",\"Quantity\":1,\"Pricing\":null,\"PartnerIdOnRecord\":null,\"RenewsTo\":null,\"Links\":{\"Product\":{\"Uri\":\"/products/DZH318Z0C964?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"Sku\":{\"Uri\":\"/products/DZH318Z0C964/skus/0001?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"Availability\":{\"Uri\":\"/products/DZH318Z0C964/skus/0001/availabilities/DZH318Z0BZDG?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"ActivationLinks\":{\"Uri\":\"/customers/86bddccf-9a53-40c6-907c-08067a3f8da7/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1/lineitems/0/activationlinks\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]}}}],\"CreationDate\":\"2020-09-02T17:58:01.7755853Z\",\"Status\":\"pending\",\"TransactionType\":\"UserPurchase\",\"Links\":{\"Self\":{\"Uri\":\"/customers/86bddccf-9a53-40c6-907c-08067a3f8da7/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"ProvisioningStatus\":{\"Uri\":\"/customers/86bddccf-9a53-40c6-907c-08067a3f8da7/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1/provisioningstatus\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"PatchOperation\":{\"Uri\":\"/customers/86bddccf-9a53-40c6-907c-08067a3f8da7/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"Method\":\"PATCH\",\"Body\":null,\"Headers\":[]}},\"Client\":{\"marketplaceCountry\":\"US\",\"deviceFamily\":\"UniversalStore-PartnerCenter\",\"name\":\"Partner Center Web\"},\"Attributes\":{\"ObjectType\":\"Order\"}}", 

            "operationType": "create_order", 

            "originalCorrelationId": "96514ebe-c1b2-4865-cb46-2c2d20a2e911", 

            "operationDate": "2020-09-02T17:58:10.9268372Z", 

            "operationStatus": "succeeded", 

            "customizedData": [ 

                { 

                    "key": "OrderId", 

                    "value": "Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1" 

                }, 

                { 

                    "key": "AlternateId", 

                    "value": "64144d300bde" 

                }, 

                { 

                    "key": "BillingCycle", 

                    "value": "Monthly" 

                }, 

                { 

                    "key": "OfferId-0", 

                    "value": "DZH318Z0C964:0001:DZH318Z0BZDG" 

                }, 

                { 

                    "key": "SubscriptionId-0", 

                    "value": "f428d44a-d08b-348b-579e-ce92a6362c7b" 

                }, 

                { 

                    "key": "SubscriptionName-0", 

                    "value": "SaaS custom meter offer - Bronze" 

                }, 

                { 

                   "key": "Quantity-0", 

                    "value": "1" 

                }, 

                { 

                    "key": "PartnerOnRecord-0", 

                    "value": null 

                } 

            ], 

            "attributes": { 

                "objectType": "AuditRecord" 

            } 

        }, 

                           { 

            "id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_86bddccf-9a53-40c6-907c-08067a3f8da7_86bddccf-9a53-40c6-907c-08067a3f8da7_addcustomer_637346648528069005", 

            "partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d", 

            "participants": [ 

                "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d" 

            ], 

            "customerId": "86bddccf-9a53-40c6-907c-08067a3f8da7", 

            "customerName": "CustomMetersStagingTest", 

            "userPrincipalName": "admin@testsw09.onmicrosoft.com", 

            "applicationId": "4990cffe-04e8-4e8b-808a-1175604b879f", 

            "resourceType": "customer", 

            "resourceNewValue": "{\"Id\":\"86bddccf-9a53-40c6-907c-08067a3f8da7\",\"CommerceId\":\"9dd78b4f-f98a-44b4-a2fa-2b82ac58d24c\",\"CompanyProfile\":{\"TenantId\":\"86bddccf-9a53-40c6-907c-08067a3f8da7\",\"Domain\":\"CustomMetersStagingTest.onmicrosoft.com\",\"CompanyName\":\"CustomMetersStagingTest\",\"Address\":null,\"Email\":null,\"OrganizationRegistrationNumber\":null,\"Links\":{\"Self\":{\"Uri\":\"/customers/86bddccf-9a53-40c6-907c-08067a3f8da7/profiles/company\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]}},\"Attributes\":{\"ObjectType\":\"CustomerCompanyProfile\"}},\"BillingProfile\":{\"Id\":\"4beafd7b-cdab-5bdc-52ed-02e16edf2e7a\",\"FirstName\":\"CustomMetersStagingTest\",\"LastName\":\"CustomMetersStagingTest\",\"Email\":\"CustomMetersStagingTest@CustomMetersStagingTest.com\",\"Culture\":\"en-US\",\"Language\":\"en\",\"CompanyName\":\"CustomMetersStagingTest\",\"DefaultAddress\":{\"Id\":null,\"Country\":\"US\",\"Region\":null,\"City\":\"Seattle\",\"State\":\"WA\",\"District\":null,\"AddressLine1\":\"CustomMetersStagingTest\",\"AddressLine2\":null,\"AddressLine3\":null,\"PostalCode\":\"98122\",\"FirstName\":\"CustomMetersStagingTest\",\"LastName\":\"CustomMetersStagingTest\",\"EmailAddress\":null,\"PhoneNumber\":null,\"MiddleName\":null},\"Attributes\":{\"Etag\":\"-2279334701316321663\",\"ObjectType\":\"CustomerBillingProfile\"}},\"RelationshipToPartner\":\"reseller\",\"AllowDelegatedAccess\":true,\"UserCredentials\":{\"userName\":\"admin\",\"password\":\"\"},\"AssociatedPartnerId\":null,\"CustomDomains\":null,\"Attributes\":{\"ObjectType\":\"Customer\"}}", 

            "operationType": "add_customer", 

            "originalCorrelationId": "7550d9ea-e64a-416f-e49b-3670c516cf69", 

            "operationDate": "2020-09-02T17:34:12.8069005Z", 

            "operationStatus": "succeeded", 

            "customizedData": [ 

                { 

                    "key": "PrimaryDomainName", 

                    "value": "CustomMetersStagingTest.onmicrosoft.com" 

                }, 

                { 

                    "key": "Relationship", 

                    "value": "Reseller" 

                } 

            ], 

            "attributes": { 

                "objectType": "AuditRecord" 

            } 

        }, 

                            

        ... 

    ], 

    "links": { 

        "self": { 

            "uri": "/auditrecords?startDate=2020-09-02&endDate=2020-09-02&size=50", 

            "method": "GET", 

            "headers": [] 

        } 

    }, 

    "attributes": { 

        "objectType": "Collection" 

    } 

}