顺晟科技
2021-08-28 09:40:54
161
想要了解Golang高并发问题的解决方案,iGoogle.ink将在本文中详细讲解Golang高并发的相关知识和一些代码示例。欢迎大家阅读指正。让我们先关注高并发的Golang。让我们一起学习。
戈朗高并发问题的解决方案
与其他编程语言相比,Golang在高并发的问题上有很大的优势,即在相同的配置下,Golang可以以更低的成本处理更多的线程,线程数相同,占用的资源更少!这样,只有一部分问题得到了解决,因为每个协调过程中的处理逻辑仍然会有问题。
当并发性较高时,需要考虑服务器能够承受的更大压力、读取数据库时的io问题、连接数、带宽问题等
研究了并发解决方案,并记录在这里
参考文章:快速处理每分钟100万个请求
地址:http://marcio . io/2015/07/与golang一起处理每分钟100万个请求/
代码如下:
//==================================
//*姓名:杰瑞
//*电话:18017448610
//* DateTime:2019/2/24 14:02
//==================================
包装主体
导入(
github.com/lunny/log '
“运行时”
同步
时间
)
//工厂模型
工厂类型结构
Wg *同步。WaitGroup //任务监控系统
MaxWorker int //更大机器数
MaxJobs int //更大作业数
JobQueue chan int //工作队列管道
退出游戏//关闭机器
}
//创建工厂模型
func NewFactory(maxWorker int,wg *sync。WaitGroup)工厂(
返回工厂{
WG : WG//参考任务监控系统
maxWorker : maxWorker//机器数量(数量取决于服务器性能)
作业队列: make (chan int,max worker),//工作管道,数量大于或等于机器数量
Quit: make(chan bool),
}
}
//设置更大订单数量
func(f * Factory)SetMaxJobs(TaskNum int){ 0
f.MaxJobs=taskNum
}
//开始工作
功能(工厂)启动()
//机器已打开,MaxWorker
对于I :=0;i f . MaxWorker我
//每台机器开机后开始工作
go func(){ 0
//等待发出命令
对于{ 0
选择{
案例i :=-f.JobQueue:
//拿到工作就开始!
f.doWork(一)
案例-f.Quit:
日志。Println(“机器关机”)
返回
}
}
}()
}
}
//将每个任务分配给管道
函数(f *工厂)添加任务(TaskNum int){ 0
//系统监控任务1
f.工作组增编(1)
//将任务分配给管道
f.作业队列-任务编号
}
//模拟耗时的工作
func(f * Factory)DoWork(TaskNum int){ 0
//生产产品的工作
时间到了。睡眠(200 *时间。毫秒)
//完成工作报告
f.工作组已完成()
//日志。Println('完成:',taskNum)
}
//创建工厂
func Begin(){ 0
//配置工作审核
gomaxprocs :=运行时。运行时。NumCPU())
日志。Println('支票号码:',gomaxprocs)
//配置监控系统
wg :=新(同步。WaitGroup)
//开工厂
工厂:=新工厂(1000,工作组)
//订单数量
工厂。SetMaxJobs(10000)
//开始工作
工厂。开始()
日志。Println(“开始生产”)
//谈论所有订单并将其添加到任务队列中
对于I :=0;我是工厂。MaxJobs我
工厂。添加任务(I)
}
工厂。工作组等待()
日志。Println(“所有订单任务都已完成”)
}
测试代码和结果
在上面的代码中,MaxWorker的数量非常重要,这取决于服务器能够承受的压力。当然不能无限增加,合理的数值效率更高(多少合适,自己测试)
代码:
func Benchmark _ Begin(b *测试。b){ 0
开始()
}
结果:
在1000台机器和10000个工作负载的情况下,我的个人电脑测试结果如下:
2019/02/26 16:42:31号码:4
2019年2月26日,16:42:31开始生产
2019年2月26日,16:42:33,所有订单和任务完成
goos: windows
goarch: amd64
pkg:第11天
基准_高2-4 1 2035574000 ns/op
及格
进程已完成,退出代码为0
总结:
此方法仅仅是在代码层面解决一定的问题,高并发产生的原因还包括其他原因,如带宽,数据库读取速度等等,还需加大带宽,多级数据库,优化数据的检索等等方法
补充:golang高并发任务处理方案
这个主要用开发的陈和例行的属性做的,比很多语言方便多了,可以参考参考
//任务的请求
类型MtaskRequest结构{
史策国际公司
//[修订]
}
//作业队列工作池
var(
MaxWorker=os .Getenv('MAX_WORKERS ')
MaxQueue=os .Getenv('MAX_QUEUE ')
)
//作业代表要运行的作业
作业类型结构{
请求
}
//一个我们可以发送工作请求的缓冲通道。
//var JobQueue更改作业-这样申明会卡主,没有初始化
变量作业队列=生成(更改作业)
//工人表示执行作业的工作者
工作者类型结构{
工人变更工作
作业通道更改作业
退出chan bool
}
功能新工作人员(工作人员变更工作)工作人员(
返回工人{
WorkerPool: workerPool,
作业通道:制作(更改作业),
quit: make(chan bool)}
}
//停止向工作人员发出停止监听工作请求的信号。
功能(工作人员)停止()
go func(){ 0
w。退出-真
}()
}
类型分配器结构{
//向调度程序注册的工作通道池
工人变更工作
maxWorkers int
}
func new Dispatcher(MaxWorkers int)* Dispatcher {
池:=制作(更改更改作业,maxWorkers)
返回调度程序{工人池,更大工人:更大工人}
}
//开始方法启动工作程序的运行循环,监听中的退出通道
//以防我们需要阻止它
功能(工作人员)开始()
go func(){ 0
对于{ 0
//将当前工作进程注册到工作进程队列中。
w.工作通道
选择{
案例-w.JobChannel:
时间到了。睡眠(5 *时间。第二)
//我们收到了工作请求。
fmt .Println('调起工人)
case -w.quit:
//我们收到了停止的信号
返回
//不能写系统默认值
}
}
}()
}
函数(d *调度员)运行(){ 0
//启动一定数量的工人
fmt .Println('启动一定数量的工人)
对于I :=0;i d.maxWorkers我
工人:=新工人
工人。开始()
}
转到d .调度()
}
//分派任务
功能(d *调度程序)调度(){ 0
对于{ 0
选择{
案例作业:=-JobQueue: //接收一个工作请求
fmt .Println('JobQueue收到请求)
go func(作业作业){ 0
//尝试获取可用的工人工作渠道。
//这会一直阻塞,直到一个工作人员空闲
jobChannel :=-d.WorkerPool
//将作业发送到工人作业通道
作业通道-作业
}(作业)
}
}
}
//接收到红包数据
func(这个* TaskRedbao)用户getredbao(red _ id,uid,shop_id,rand_arr,Amoney字符串)错误{
fmt .Println('收到接收到红包数据超文本传送协议(超文本传输协议的缩写)请求)
mtaskRequest :=mtaskRequest { 67 }
工作:=工作{ mtaskRequest : mtaskRequest }
工作队列-工作
返回零
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
21
2022-04
28
2021-08
28
2021-08
28
2021-08
28
2021-08
28
2021-08