NET 5 原子操作、接口限流Semaphore以及性能测试JMeter
一、Semaphore
限流也可使用令牌桶算法+redis
1.Semaphore定义
类似互斥锁,但它可以允许多个线程同时访问一个共享资源
通过使用一个计数器来控制对共享资源的访问,如果计数器大于0,就允许访问,如果等于0,就拒绝访问。计数器累计的是“许可证”的数目,为了访问某个资源。线程必须从信号量获取一个许可证。
通常在使用信号量时,希望访问共享资源的线程将尝试获取一个许可证,如果信号量的计数器大于0,线程将获取一个许可证并将信号量的计数器减1,否则先线程将阻塞,直到获取一个许可证;当线程不再需要共享资源时,将释放锁拥有的许可证,并将许可证的数量加1,如果有其他的线程正在等待许可证,那么该线程将立刻获取许可证。
另外,允许同时访问的资源的进程数量是在创建信号量时指定的,如果创建一个允许进程访问的信号量数目为1,则该信号量就和互斥锁的用法一样。
Semaphore常用的方法有两个WaitOne()和Release(),Release()的作用是退出信号量并返回前一个计数,而WaitOne()则是阻止当前线程,直到当前线程的WaitHandle 收到信号。这里我举一个例子让大家更容易理解:
当我们这样实例化Semaphore时候,如果写Semaphore sema = new Semaphore(x,y)这种表达式,就可以理解为这样一个场景
有一队人排队上洗手间,人就相当于线程,x为还剩余的位置数量,y为总的位置数量。
WaitOne()方法就相当于人在等待洗手间位置的行为,而Release()方法就相当于一个人从洗手间出来的行为,这里再假设x和y都为5,说明开始的时候洗手间有5个空位置,且总共只有5个位置,当一队超过5个人的队伍要上洗手间的就排队,首先WaitOne()方法等待,发现有空位就依次进去,每进去一个空位减一,直到进去5之后个没有空位,这时候后面的人就一直等待,直到进去的人从洗手间出来Release()方法,空位加一,在等待WaitOne()方法的人发现有空位又进去一个空位减一……如此循环往复。
2、代码举例
//创建一个可授权30个许可证的信号量,且初始值为20
//20为初始线程数,30为最大线程数
//重载可以添加 系统信号量 名称,这样子可以在多进程间进行访问了
private readonly static Semaphore _semaphore = new Semaphore(20, 30);
[HttpGet("GetValue")]
public async Task<string> GetValueAsync()
{ return await Task.Run(async () =>
{
try
{
//申请一个许可证
//Wait 有多个重载,加个时间 用于自动释放
_semaphore.WaitOne();
Thread.Sleep(100);
return await Task.FromResult("Value");
}
finally
{
//释放
//重载可释放多个信号量
_semaphore.Release();
}
}); }
3.原子操作Interlocked
使用 Interlocked 类,可以在不阻塞线程(lock、Monitor)的情况下,避免竞争条件。
在某个时刻,必须只有一个线程能够进行某个操作。而上面的操作,指的是读取、计算、写入这一过程。
当然,我们可以使用 lock 或者 Monitor 来解决,但是这样会带来比较大的性能损失。
这时 Interlocked 就起作用了,对于一些简单的操作运算, Interlocked 可以实现原子性的操作。
Interlocked 类是静态类,让我们先来看看 Interlocked 的常用方法:
方法 | 作用 |
---|---|
CompareExchange() | 比较两个数是否相等,如果相等,则替换第一个值。 |
Decrement() | 以原子操作的形式递减指定变量的值并存储结果。 |
Exchange() | 以原子操作的形式,设置为指定的值并返回原始值。 |
Increment() | 以原子操作的形式递增指定变量的值并存储结果。 |
Add() | 对两个数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。 |
Read() | 返回一个以原子操作形式加载的值。 |
全部方法请查看:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked?view=netcore-3.1#methods
class Program
{
static Semaphore semaphore;
//当前信号量中线程数量
static int count;
//用于生成随机数
static Random r; static void Main()
{
r = new Random();
//初始化信号量:初始请求数为1,最大请求数为3
semaphore = new Semaphore(1, 3);
//放出10个线程
for (int i = 0; i < 5; i++)
ThreadPool.QueueUserWorkItem(doo, i + 1);
Console.ReadKey(true);
} static void doo(object arg)
{
int id = (int)arg;
PrintStatus(id, "等待信号量");
//获取一个资源
semaphore.WaitOne();
PrintStatus(id, "获得信号量开始执行");
PrintCount(1);
Thread.Sleep(r.Next(1000));
PrintStatus(id, "退出");
PrintCount(-1);
//释放一个资源
semaphore.Release(); } //输出线程状态
static void PrintStatus(int id, string s)
{
Console.WriteLine("线程{0}:{1}", id, s);
} //修改并输出线程数量
static void PrintCount(int add)
{
//在多进程(线程)的操作系统中不能被其它进程(线程)打断的操作就叫原子操作,一个线程在执行其它线程无法抢占。
//对两个 32 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。
Interlocked.Add(ref count, add);
//以原子操作的形式,将 32 位有符号整数设置为指定的值并返回原始值。
Console.WriteLine("=> 信号量值:{0}", Interlocked.Exchange(ref count, count));
}
}
二、JMeter
1.Java安装
JAVA环境变量配置:https://jingyan.baidu.com/article/fd8044fa2c22f15031137a2a.html
Java安装之前先查看下要安装的JMeter对Java SDK的版本要求,安装好后配置环境变量。安装完后cmd输入以下验证是否安装成功:
Java -version
2.JMeter安装
Jmter官方地址 https://jmeter.apache.org/
按提示下载JMeter,解压下载的二进制包,进入bin目录,使用jmeter.bat启动程序。当然前提你得先安装JAVA,或者直接运行 Bin/jmeter.bat,就可以启动JMeter
1 先配置中文
或者汉化:bin目录下找到jmeter.properties文件,找到#language=en,下面添加language=zh_CN,汉化就好了。
2 配置线程组(模拟用户)
先简单模拟50个用户,预热间1秒,Ramp-Up Period(in-seconds)代表隔多长时间执行,也就是每隔1秒生成一个线程,50个用户全部生成,一共需要50秒
3 添加取样器,线程组 --> 右键 --> 添加 --> 取样器 --> HTTP请求
JMeter不支持localhost请求,也可配置。
4 添加监听器,主要作用用于收集数据,了解接口的响应情况,先简单查看一下聚合报告吧
聚合报告内面有一个参数,吞吐量就是我们平常说的网站吞吐量,是一个重要的性能指示
5 最后一步,点中间绿色三角,“运行”,就可以进行一次负载测试了
从聚合报告的实时动态来看,这个接口的并发量高达 3W/秒
当然这只是一个简单接口,现实项目中复杂的接口,一般不会能承受这么高的并发量的,比如下订单接口,如果压测并发达3W/S,那项目架构应该达到了一线项目的水平了
参考地址https://www.cnblogs.com/stulzq/p/8971531.html
NET 5 原子操作、接口限流Semaphore以及性能测试JMeter的更多相关文章
- 库存秒杀问题-redis解决方案- 接口限流
<?php/** * Created by PhpStorm. * redis 销量超卖秒杀解决方案 * redis 文档:http://doc.redisfans.com/ * ab -n 1 ...
- Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流
最近管点闲事浪费了不少时间,感谢网友libinwalan的留言提醒.及时纠正路线,继续跟大家一起学习Spring Cloud Alibaba. Nacos作为注册中心和配置中心的基础教程,到这里先告一 ...
- SpringCloud(8)---zuul权限校验、接口限流
zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...
- 基于注解的接口限流+统一session认证
代码心得: 一个基本的做法:对于用户身份认证做到拦截器里,针对HandlerMethod进行统一拦截认证,根据方法上的注解标识,判别是否需要身份验证,并将查找出来的User实体存入ThreadLoca ...
- 【Dnc.Api.Throttle】适用于.Net Core WebApi接口限流框架
Dnc.Api.Throttle 适用于Dot Net Core的WebApi接口限流框架 使用Dnc.Api.Throttle可以使您轻松实现WebApi接口的限流管理.Dnc.Api.Thr ...
- Spring Cloud(7):Zuul自定义过滤器和接口限流
上文讲到了Zuul的基本使用: https://www.cnblogs.com/xuyiqing/p/10884860.html 自定义Zuul过滤器: package org.dreamtech.a ...
- Guava的RateLimiter实现接口限流
最近开发需求中有需要对后台接口进行限流处理,整理了一下基本使用方法. 首先添加guava依赖: <dependency> <groupId>com.google.guava&l ...
- SpringCloud之Zuul高并发情况下接口限流(十二)
高并发下接口限流技术gauva(谷歌的框架) MySql最大连接数3000: 原理:框架每秒向桶里放100个令牌,接口请求来了先去拿令牌,拿到令牌后才能继续向后走,否则不允许向后执行:当接口请求太频繁 ...
- 使用google的guova开发高并发下的接口限流
使用google的guova开发高并发下的接口限流 使用google的guova进行限流 1.guova的限流方式,在定时产生定量的令牌,令牌的数量限制了流量 2.增加一个订单接口限流类OrderRa ...
随机推荐
- C语言讲义——变量的输入
scanf("%_", &变量); 注意两点: 1.scanf的第一个参数:中只写占位符(%_),不要写别的内容(不是输出给谁看). 2.scanf的第二个参数:要加&am ...
- Python基于Socket实现简易多人聊天室
前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...
- linux查看内存及磁盘使用情况
1.查看当前目录 命令: df -h (统一每个目录下磁盘的整体情况) 2.查看指定目录 在命令后直接放目录名,比如查看"usr"目录使用情况: 命令: df ...
- IntelliJ IDEA 2020.3正式发布,年度最后一个版本很讲武德
仰不愧天,俯不愧人,内不愧心.关注公众号[BAT的乌托邦],有Spring技术栈.MyBatis.JVM.中间件等小而美的原创专栏供以免费学习.分享.成长,拒绝浅尝辄止.本文已被 https://ww ...
- 自动化运维工具之Puppet模块
前文我们了解来puppet的变量.流程控制.正则表达式.类和模板的相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/14079208.html:今天我们来 ...
- 转:Python常见字符编码及其之间的转换
参考:Python常见字符编码 + Python常见字符编码间的转换 一.Python常见字符编码 字符编码的常用种类介绍 第一种:ASCII码 ASCII(American Standard Cod ...
- Python匹配对象的groups、groupdict和group之间的关系
匹配对象的groups()方法返回一个包含所有参与匹配的子组(不含组0)的匹配到的搜索文本子串的元组,groupdict返回一个包含所有匹配到的命名组的组名为键值和命名组匹配到的搜索文本子串为值作为元 ...
- 「Elasticsearch」SpringBoot快速集成ES
Elastic Search 的底层是开源库 Lucene.但是Lucene的使用门槛比较高,必须自己写代码去调用它的接口.而Elastic Search的出现正是为了解决了这个问题,它是 Lucen ...
- shell 编程 && bash 简介(shell 变量、shell操作环境、数据流重导向、管线命令、shell script)
如何学习一门编程语言 数据类型 运算符 关键字 1 认识BASH 这个shell linux是操作系统核心,用户通过shell与核心进行沟通,达到我们想要的目的.硬件.核心.用户之间的关系: 原理:所 ...
- 在iframe中获取另一个iframe中的元素
$(top.parent.iframeId).contents().find("#selector") //iframeId为iframe的id名称