shell队列实现线程并发控制

需求:并发检测1000台web服务器状态(或者并发为1000台web服务器分发文件等)如何用shell实现?

方案一:(这应该是大多数人都第一时间想到的方法吧)

思路:一个for循环1000次,顺序执行1000次任务。

实现:      

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
start_time=` date  +%s`  #定义脚本运行的开始时间
 
for  ((i=1;i<=1000;i++))
do
         sleep  1   #sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替)
         echo  'success' $i;       
done
 
stop_time=` date  +%s`   #定义脚本运行的结束时间
 
echo  "TIME:`expr $stop_time - $start_time`"

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
[root@iZ94yyzmpgvZ ~] # . test.sh 
success1
success2
success3
success4
success5
success6
success7
........此处省略
success999
success1000
TIME:1000

代码解析以及问题:

一个for循环1000次相当于需要处理1000个任务,循环体用sleep 1代表运行一条命令需要的时间,用success$i来标示每条任务.

这样写的问题是,1000条命令都是顺序执行的,完全是阻塞时的运行,假如每条命令的运行时间是1秒的话,那么1000条命令的运行时间是1000秒,效率相当低,而我的要求是并发检测1000台web的存活,如果采用这种顺序的方式,那么假如我有1000台web,这时候第900台机器挂掉了,检测到这台机器状态所需要的时间就是900s,吃屎都吃不上热乎的。

所以,问题的关键集中在一点:如何并发

方案二:

思路:一个for循环1000次,循环体里面的每个任务都放入后台运行(在命令后面加&符号代表后台运行)。

实现:      

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
start=` date  +%s`  #定义脚本运行的开始时间
 
for  ((i=1;i<=1000;i++))
do
{
         sleep  1   #sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替)
         echo  'success' $i; 
  }&               #用{}把循环体括起来,后加一个&符号,代表每次循环都把命令放入后台运行
                  #一旦放入后台,就意味着{}里面的命令交给操作系统的一个线程处理了
                  #循环了1000次,就有1000个&把任务放入后台,操作系统会并发1000个线程来处理
                  #这些任务         
done    
wait              #wait命令的意思是,等待(wait命令)上面的命令(放入后台的)都执行完毕了再
                  #往下执行。
                  #在这里写wait是因为,一条命令一旦被放入后台后,这条任务就交给了操作系统
                  #shell脚本会继续往下运行(也就是说:shell脚本里面一旦碰到&符号就只管把它
                  #前面的命令放入后台就算完成任务了,具体执行交给操作系统去做,脚本会继续
                  #往下执行),所以要在这个位置加上wait命令,等待操作系统执行完所有后台命令
end=` date  +%s`   #定义脚本运行的结束时间
 
echo  "TIME:`expr $end - $start`"

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@iZ94yyzmpgvZ /] # . test1.sh 
......
[989]   Done                    {  sleep  1;  echo  'success' $i; }
[990]   Done                    {  sleep  1;  echo  'success' $i; }
success992
[991]   Done                    {  sleep  1;  echo  'success' $i; }
[992]   Done                    {  sleep  1;  echo  'success' $i; }
success993
[993]   Done                    {  sleep  1;  echo  'success' $i; }
success994
success995
[994]   Done                    {  sleep  1;  echo  'success' $i; }
success996
[995]   Done                    {  sleep  1;  echo  'success' $i; }
[996]   Done                    {  sleep  1;  echo  'success' $i; }
success997
success998
[997]   Done                    {  sleep  1;  echo  'success' $i; }
success999
[998]   Done                    {  sleep  1;  echo  'success' $i; }
[999]-  Done                    {  sleep  1;  echo  'success' $i; }
success1000
[1000]+  Done                    {  sleep  1;  echo  'success' $i; }
TIME:2


代码解析以及问题:

shell中实现并发,就是把循环体的命令用&符号放入后台运行,1000个任务就会并发1000个线程,运行时间2s,比起方案一的1000s,已经非常快了。

可以看到输出结果success4 ...success3完全都是无序的,因为大家都是后台运行的,这时候就是cpu随机运行了,所以并没有什么顺序

这样写确实可以实现并发,然后,大家可以想象一下,1000个任务就要并发1000个线程,这样对操作系统造成的压力非常大,它会随着并发任务数的增多,操作系统处理速度会变慢甚至出现其他不稳定因素,就好比你在对nginx调优后,你认为你的nginx理论上最大可以支持1w并发了,实际上呢,你的系统会随着高并发压力会不断攀升,处理速度会越来越慢(你以为你扛着500斤的东西你还能跑的跟原来一样快吗)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值