Azure DevOps速率限制
目标是在GO中使用其许可证和项目权利来检索Azure Devops用户。
我正在使用 Microsoft SDK 。
我们的Azure DevOps组织拥有1500多名用户。因此,当我请求每个用户授权时,我的错误消息是 azure devops速率限制 => 443:阅读:连接重置,但是
,用100/200限制顶部,当然可以。
,但是 限制。或者也许使用 heimdall 。
您对一个好设计师的建议是什么?
谢谢。
这是代码:
package main
import (
"context"
"fmt"
"github.com/microsoft/azure-devops-go-api/azuredevops"
"github.com/microsoft/azure-devops-go-api/azuredevops/memberentitlementmanagement"
"log"
"runtime"
"sync"
"time"
)
var organizationUrl = "https://dev.azure.com/xxx"
var personalAccessToken = "xxx"
type User struct {
DisplayName string
MailAddress string
PrincipalName string
LicenseDisplayName string
Status string
GroupAssignments string
ProjectEntitlements []string
LastAccessedDate azuredevops.Time
DateCreated azuredevops.Time
}
func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) // Try to use all available CPUs.
}
func main() {
// Time measure
defer timeTrack(time.Now(), "Fetching Azure DevOps Users License and Projects")
// Compute context
fmt.Println("Version", runtime.Version())
fmt.Println("NumCPU", runtime.NumCPU())
fmt.Println("GOMAXPROCS", runtime.GOMAXPROCS(0))
fmt.Println("Starting concurrent calls...")
// Create a connection to your organization
connection := azuredevops.NewPatConnection(organizationUrl, personalAccessToken)
// New context
ctx := context.Background()
// Create a member client
memberClient, err := memberentitlementmanagement.NewClient(ctx, connection)
if err != nil {
log.Fatal(err)
}
// Request all users
top := 10000
skip := 0
filter := "Id"
response, err := memberClient.GetUserEntitlements(ctx, memberentitlementmanagement.GetUserEntitlementsArgs{
Top: &top,
Skip: &skip,
Filter: &filter,
SortOption: nil,
})
usersLen := len(*response.Members)
allUsers := make(chan User, usersLen)
var wg sync.WaitGroup
wg.Add(usersLen)
for _, user := range *response.Members {
go func(user memberentitlementmanagement.UserEntitlement) {
defer wg.Done()
var userEntitlement = memberentitlementmanagement.GetUserEntitlementArgs{UserId: user.Id}
account, err := memberClient.GetUserEntitlement(ctx, userEntitlement)
if err != nil {
log.Fatal(err)
}
var GroupAssignments string
var ProjectEntitlements []string
for _, assignment := range *account.GroupAssignments {
GroupAssignments = *assignment.Group.DisplayName
}
for _, userProject := range *account.ProjectEntitlements {
ProjectEntitlements = append(ProjectEntitlements, *userProject.ProjectRef.Name)
}
allUsers <- User{
DisplayName: *account.User.DisplayName,
MailAddress: *account.User.MailAddress,
PrincipalName: *account.User.PrincipalName,
LicenseDisplayName: *account.AccessLevel.LicenseDisplayName,
DateCreated: *account.DateCreated,
LastAccessedDate: *account.LastAccessedDate,
GroupAssignments: GroupAssignments,
ProjectEntitlements: ProjectEntitlements,
}
}(user)
}
wg.Wait()
close(allUsers)
for eachUser := range allUsers {
fmt.Println(eachUser)
}
}
func timeTrack(start time.Time, name string) {
elapsed := time.Since(start)
log.Printf("%s took %s", name, elapsed)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以编写
getUserentitrempt
函数的自定义版本。它不使用任何私人成员。
获得
http.Response
后,您可以检查retry-terry-fefter
标题,并在存在的情况下延迟下一个环的迭代。https:https:// github。 com/microsoft/azure-devops-go-api/blob/dev/azuredevops/memberentitementmanagement.cliant.go#l306
您的代码中的PS同时发生是多余的,可以删除。
更新 - 解释并发问题:
您无法轻松在并发代码中实现限制速率。如果您顺序执行所有请求,并在移至下一个响应之前,在每个响应中检查标题,将会更简单。
通过并行执行:1)您不能依靠
重试
标题值,因为您可能会同时返回另一个值的另一个请求执行。 2)您不能将延迟应用于其他请求,因为其中一些已经在进行中。You can write custom version of
GetUserEntitlement
function.https://github.com/microsoft/azure-devops-go-api/blob/dev/azuredevops/memberentitlementmanagement/client.go#L297-L314
It does not use any private members.
After getting
http.Response
you can checkRetry-After
header and delay next loop's iteration if it is present.https://github.com/microsoft/azure-devops-go-api/blob/dev/azuredevops/memberentitlementmanagement/client.go#L306
P.S. Concurrency in your code is redundant and can be removed.
Update - explaining concurrency issue:
You cannot easily implement rate-limiting in concurrent code. It will be much simpler if you execute all requests sequentially and check
Retry-After
header in every response before moving to the next one.With parallel execution: 1) you cannot rely on
Retry-After
header value because you may have another request executing at the same time returning a different value. 2) You cannot apply delay to other requests because some of them are already in progress.您是说要通过直接使用REST API避免速率限制吗?
如果是这样,那么您的想法将不起作用。
大多数REST API都可以通过客户端库访问,如果您基于REST API或其他基于REST API的内容使用SDK,它当然会达到速率限制。
由于速率限制是基于用户的,因此我建议您可以根据多个用户完成操作(前提是您的请求不是阻止IP的服务器太多)。
Do you mean you want to avoid the Rate Limit by using the REST API directly?
If so, then your idea will not work.
Most REST APIs are accessible through client libraries, and if you're using SDK based on a REST API or other thing based on a REST API, it will of course hit a rate limit.
Since the rate limit is based on users, I suggest that you can complete your operations based on multiple users (provided that your request is not too much that the server blocking your IP).