Maison  >  Article  >  développement back-end  >  Comment utiliser Golang pour implémenter la limitation du courant des requêtes

Comment utiliser Golang pour implémenter la limitation du courant des requêtes

PHPz
PHPzoriginal
2023-04-27 09:11:04913parcourir

Avec l'utilisation croissante des applications Web modernes, de nombreuses demandes d'utilisateurs commencent à affluer sur le serveur, ce qui provoque certains problèmes. D'une part, les performances du serveur sont limitées et il n'y a aucune garantie que toutes les requêtes puissent être traitées ; d'autre part, un grand nombre de requêtes arrivant en même temps peut rendre le service instable ; À l'heure actuelle, limiter le taux de requêtes est devenu un choix inévitable. Ce qui suit présente comment utiliser Golang pour implémenter la limitation du courant de requête.

Qu'est-ce que la limitation actuelle ?

La limitation actuelle fait référence à la limitation du nombre maximum de requêtes ou de trafic de données qu'une application, un système ou un service peut supporter pendant une certaine période de temps. La limitation actuelle peut nous aider à atténuer les attaques réseau et à prévenir les abus de bande passante et de ressources. Nous appelons généralement cette limite « contrôle de flux », qui peut hiérarchiser les demandes de différents types et sources et traiter les demandes de différents types et sources dans différentes proportions.

Implémenter la limitation de courant de demande

Algorithme de limitation de courant de fenêtre basé sur la fenêtre de temps

L'algorithme le plus simple et le plus direct est l'algorithme de limitation de courant basé sur la fenêtre de temps. Il vérifie si le nombre total de requêtes envoyées au cours de la période la plus récente dépasse un seuil. La durée de la fenêtre temporelle peut être ajustée en fonction des caractéristiques de l'application pour obtenir des performances optimales et un taux de fausses alarmes minimum.

Supposons que nous devions limiter le nombre maximum d'accès par seconde à une API. Nous pouvons utiliser le package time de Golang pour compter le trafic et utiliser des canaux tampons pour implémenter des files d'attente de requêtes. Le code est le suivant :

type ApiLimiter struct {
    rate       float64 // 时间窗口内最大请求数
    capacity   int // 请求队列最大长度,即最多能有多少请求同时被处理
    requestNum int // 时间窗口内已处理请求总数
    queue      chan int // 缓冲通道,用于实现请求队列
}

func NewApiLimiter(rate float64, capacity int) *ApiLimiter {
    return &ApiLimiter{
        rate:       rate,
        capacity:   capacity,
        requestNum: 0,
        queue:      make(chan int, capacity),
    }
}
func (al *ApiLimiter) Request() bool {
    now := time.Now().UnixNano()
    maxRequestNum := int(float64(now)/float64(time.Second)*al.rate) + 1 // 统计最近一秒内应该处理的请求数量
    if maxRequestNum <= al.requestNum { // 超过最大请求数,返回false
        return false
    }
    al.queue <- 1 // 将请求压入队列
    al.requestNum += 1
    return true
}

Dans cet exemple, nous utilisons chan dans Golang pour implémenter la file d'attente des requêtes et utilisons le package time pour calculer le nombre de requêtes dans la fenêtre de temps. Une fois que chaque requête atteint le serveur, nous mettrons la requête dans la file d'attente et le volume de la requête sera également comparé au nombre maximum de requêtes. Si le nombre maximum de requêtes est dépassé, false sera renvoyé.

Leaky Bucket Algorithm

Leaky Bucket Algorithm est un autre algorithme de limitation de courant célèbre. À tout moment, le bucket qui fuit conserve un certain nombre de requêtes. Lorsqu'une nouvelle demande arrive, vérifiez d'abord si le nombre de demandes restant dans le compartiment qui fuit atteint le montant maximum de la demande. Si tel est le cas, rejetez la nouvelle demande, sinon, placez la nouvelle demande dans le compartiment et réduisez le nombre de demandes dans le compartiment. par un.

L'algorithme du bucket qui fuit peut être implémenté à l'aide de coroutines et de minuteries dans Golang. Nous pouvons utiliser une minuterie pour représenter notre seau qui fuit et qui s'écoule lentement des requêtes au fil du temps. Le code est le suivant :

type LeakyBucket struct {
    rate       float64 // 漏桶每秒处理的请求量(R)
    capacity   int     // 漏桶的大小(B)
    water      int     // 漏桶中当前的水量(当前等待处理的请求个数)
    lastLeaky  int64   // 上一次请求漏出的时间,纳秒
    leakyTimer *time.Timer // 漏桶接下来漏水需要等待的时间
    reject     chan int // 被拒绝的请求通道
}

func NewLeakyBucket(rate float64, capacity int) *LeakyBucket {
    bucket := &LeakyBucket{
        rate:     rate,
        capacity: capacity,
        water:    0,
        reject:   make(chan int, 1000),
    }
    bucket.leakyTimer = time.NewTimer(time.Second / time.Duration(rate))
    return bucket
}

func (lb *LeakyBucket) Request() chan int {
    select {
    case <-lb.leakyTimer.C:
        if lb.water > 0 {
            lb.water -= 1
            lb.leakyTimer.Reset(time.Second / time.Duration(lb.rate))
               return nil // 请求被允许
        }
        lb.leakyTimer.Reset(time.Second / time.Duration(lb.rate))
        return lb.reject // 请求被拒绝
    default:
        if lb.water >= lb.capacity {
            return lb.reject // 请求被拒绝
        } else {
            lb.water += 1 // 请求被允许
            return nil
        }
    }
}

Dans cet exemple, nous utilisons le timer de Golang pour réaliser le taux de sortie du seau qui fuit, et utilisons chan pour réaliser la mise en mémoire tampon des requêtes. Nous avons d'abord créé une minuterie pour vérifier régulièrement le nombre de demandes restantes (eau) dans le seau qui fuit. Avant que la demande ne soit acceptée, nous vérifierons d'abord si elle a atteint la capacité maximale à traiter. Si tel est le cas, nous renverrons un rejet ; sinon, nous le mettrons dans un seau qui fuit et ajouterons 1 à la quantité d'eau.

Autres réflexions

Dans cet article, nous présentons deux algorithmes courants de limitation de courant de requête : l'algorithme de limitation de courant basé sur une fenêtre et l'algorithme de compartiment à fuite. Cependant, il existe de nombreuses autres variantes de ces algorithmes, telles que le contrôle de flux basé sur l'importance de la requête ou combiné à des structures de données de file d'attente. Golang lui-même présente d'excellents modèles de concurrence et de coroutine, ce qui en fait l'un des meilleurs outils pour implémenter la limitation des requêtes.

À l'avenir, avec le développement en profondeur de l'intelligence artificielle, du big data et d'autres technologies, nous aurons besoin de meilleurs algorithmes de limitation de courant pour prendre en charge le fonctionnement de nos applications. Alors, avant d’aller plus loin, explorons et étudions ensemble ce domaine en constante évolution.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn