//  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. 从 Linux 内核角度探秘 JDK NIO 文件读写本质

    1. 前言 笔者在 <从 Linux 内核角度看 IO 模型的演变>一文中曾对 Socket 文件在内核中的相关数据结构为大家做了详尽的阐述. 又在此基础之上介绍了针对 socket 文件 ...

  2. eclipse 统一设置编码_项目工程统一设置成utf8编码_eclipse代码规范

    在做项目的时候文件有的时候编码不同一 经常出现乱码,eclipse统一设置编码 可以解决项目编码混乱的问题, 设置eclipse java,jsp,css,js文件编码的方法如下: 1.在工具栏中点击 ...

  3. WinForm完美实现Cefsharp-v49控件C#与JS交互,并且可加载运行flash

    https://blog.csdn.net/zhao331863874/article/details/117328415

  4. C语言[char**]与[malloc]的组合使用

    简介 首先!要搞懂char**是什么? 我们知道 char* 是字符指针,是一个地址,指向一个字符串. 那么 char** 就是指向 char* 的指针,也是一个地址,指向指针的指针. 使用char* ...

  5. 1.云原生之Docker容器技术基础知识介绍

    转载自:https://www.bilibili.com/read/cv15180540/?from=readlist

  6. Shell分析日志文件

    文章转载自:https://mp.weixin.qq.com/s/o63aIM2p9rc2OjhxiC6wgA 1.查看有多少个IP访问: awk '{print $1}' log_file|sort ...

  7. 启动elasticsearch报错解决

    说不定以后会不定期更新该文档 1.提示文件描述符数量太少,修改/etc/security/limits.conf文件,添加. * soft nofile 65537 * hard nofile 655 ...

  8. 在 Fedora 中使用 Cockpit 创建虚拟机

    本文向你展示如何在 Fedora 31 上使用安装 Cockpit 所需软件来创建和管理虚拟机.Cockpit 是一个交互式管理界面,可让你在任何受支持的 Web 浏览器上访问和管理系统.随着 vir ...

  9. Python中class内置方法__init__与__new__作用与区别探究

    背景 最近尝试了解Django中ORM实现的原理,发现其用到了metaclass(元类)这一技术,进一步又涉及到Python class中有两个特殊内置方法__init__与__new__,决定先尝试 ...

  10. 页面导出Excel

    后端: 1.准备要导出的数据 2.利用XSSFWorkbook对象(workbook)创建工作簿行列等并添加数据 3.响应给前端 例: // 获取响应流 OutputStream output = r ...