//  Copyright(C) 2021. Huawei Technologies Co.,Ltd.  All rights reserved.

// Package limiter implement a token bucket limiter
package limiter

import (
"context"
"huawei.com/npu-exporter/hwlog"
"huawei.com/npu-exporter/utils"
"math"
"net/http"
"time"
)

const (
kilo = 1000.0
)

type limitHandler struct {
concurrency chan struct{}
httpHandler http.Handler
log bool
}

// ServeHTTP implement http.Handler
func (h *limitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx := context.TODO()
reqID := req.Header.Get(hwlog.ReqID.String())
if reqID != "" {
ctx = context.WithValue(context.Background(), hwlog.ReqID, reqID)
}
id := req.Header.Get(hwlog.UserID.String())
if id != "" {
ctx = context.WithValue(ctx, hwlog.UserID, id)
}
path := req.URL.Path
clientIP := utils.ClientIP(req)
clientUserAgent := req.UserAgent()
select {
case _, ok := <-h.concurrency:
if !ok {
return
}
start := time.Now()
h.httpHandler.ServeHTTP(w, req)
stop := time.Since(start)
latency := int(math.Ceil(float64(stop.Nanoseconds()) / kilo / kilo))
if h.log {
hwlog.RunLog.InfofWithCtx(ctx, "%s %s: %s <%3d> (%dms) |%15s |%s ", req.Proto, req.Method, path,
http.StatusOK, latency, clientIP, clientUserAgent)
}
h.concurrency <- struct{}{}
default:
hwlog.RunLog.WarnfWithCtx(ctx, "Reject Request:%s: %s <%3d> |%15s |%s ", req.Method, path,
http.StatusServiceUnavailable, clientIP, clientUserAgent)
http.Error(w, "503 too busy", http.StatusServiceUnavailable)
}
}

// NewLimitHandler new a bucket-token limiter
func NewLimitHandler(maxConcur, maxConcurrency int, handler http.Handler, printLog bool) http.Handler {
if maxConcur < 1 || maxConcur > maxConcurrency {
hwlog.RunLog.Fatal("maxConcurrency parameter error")
}
h := &limitHandler{
concurrency: make(chan struct{}, maxConcur),
httpHandler: handler,
log: printLog,
}
for i := 0; i < maxConcur; i++ {
h.concurrency <- struct{}{}
}
return h
}

hwlog--limiter.go的更多相关文章

  1. Cannot send session cache limiter Cannot modify header information

    当php报出  Cannot send session cache limiter 或Cannot modify header information   的错误时   其理论上是因为php代码以前有 ...

  2. Warning: session_start() [function.session-start]: Cannot send session cache limiter

    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers alrea ...

  3. go笔记-限速器(limiter)

    参考: https://blog.csdn.net/wdy_yx/article/details/73849713https://www.jianshu.com/p/1ecb513f7632 http ...

  4. ICD2 VPP limiter for new PIC microcontrollers.

    http://www.circuitsathome.com/mcu/pic_vpp_limiter VOUT = 2.5V * ( 1 + 24/10 ) = 2.5 * 3.4 = 8.5V New ...

  5. rate limiter - system design

    1 问题 Whenever you expose a web service / api endpoint, you need to implement a rate limiter to preve ...

  6. 359. Logger Rate Limiter

    /* * 359. Logger Rate Limiter * 2016-7-14 by Mingyang * 很简单的HashMap,不详谈 */ class Logger { HashMap< ...

  7. Rate Limiter

    Whenever you expose a web service / api endpoint, you need to implement a rate limiter to prevent ab ...

  8. RocksDB Rate Limiter源码解析

    这次的项目我们重点关注RocksDB中的一个环节:Rate Limiter.其实Rate Limiter的思想在很多其他系统中也很常用. 在RocksDB中,后台会实时运行compaction和flu ...

  9. 详解FL Studio压缩器——Fruity Limiter(上)

    压缩,是电音制作中重要一步,将声音信号压缩后可过滤噪音并使音质变好.众所周知,音乐编曲软件FL Studio的特色就是电音制作,所以必不可少要用到压缩器,今天我们就用FL Studio20来讲解一下. ...

  10. 详解FL Studio压缩器——Fruity Limiter(下)

    Hello!小伙伴们又见面啦-接上一篇,本篇咱们继续讲解音乐编曲软件FL Studio20压缩器内容. 包络"ENVELOPE"中包含三个旋钮,它们都有什么作用呢?一起来揭晓吧! ...

随机推荐

  1. 诺塔斯读写卡QT SDK笔记

    卡片操作函数调用 寻卡: Request --> LotusCardRequest 防撞处理: Anticollission --> LotusCardAnticoll 选卡: Selec ...

  2. KingbaseES时间函数的比较

    KingbaseES提供了多种的时间函数,这些函数在使用过程中存在哪些不同? **同一事务** test=# begin test-# for i in 1.. 10 loop test-# rais ...

  3. Oracle 与 PostgreSQL 函数行为的差异引发性能差异

    对于Oracle,对于数据修改的操作通过存储过程处理,而对于函数一般不进行数据修改操作.同时,函数可以通过 Select 进行调用,而存储过程则不行. 一.对于volatile 函数的行为 1.Ora ...

  4. Zookeeper 分布式事务锁的使用

    使用Netflix的包 curator-recipes pom文件引入相关依赖 <dependency> <groupId>org.apache.zookeeper</g ...

  5. Redis 的大 Key 对持久化有什么影响?

    作者:小林coding 图解计算机基础(操作系统.计算机网络.计算机组成.数据库等)网站:https://xiaolincoding.com 大家好,我是小林. 上周有位读者字节一二面时,被问到:Re ...

  6. uniapp路由守卫

    项目地址:https://hhyang.cn/v2/start/quickstart.html ​ 按照他的方法安装,创建相应的js即可,有点基础的自己捣鼓一下就可以了.我的应用场景是:没有登录痕迹- ...

  7. 3.云原生之Docker容器三大核心概念介绍

    转载自:https://www.bilibili.com/read/cv15181760/?from=readlist docker search --no-trunc=false [镜像名称] #搜 ...

  8. Readsh中文版初始设置

    B站视频教程网址:https://space.bilibili.com/630285695/video 安装成功后,打开浏览器输入http://ip:5000如果出现如下画面,即告安装成功. 初始设置 ...

  9. Css3中自适应布局单位vh、vw

    视口单位(Viewport units) 什么是视口? 在桌面端,视口指的是在桌面端,指的是浏览器的可视区域:而在移动端,它涉及3个视口:Layout Viewport(布局视口),Visual Vi ...

  10. HDU3507 print article (斜率优化DP)

    状态表示:dp[i]表示打印前i个单词的最小成本:s[i]维护前缀和. 状态转移:dp[i]=min(dp[j]+(s[i]-s[j])2)+m , 0<=j<i. 换成y=kx+b的形式 ...