Linux supervise PHP常驻

Supervise安装可以参考:上一篇博文

php:php.php

<?php 
$fp = fopen("text.txt",'w');
fwrite($fp,date("Y-m-d H:i:s",time()));
fclose($fp);
while(1){
//保持不退出
}

脚本:run

#!/bin/sh
ps -elf| grep php.php | grep -v grep > /dev/null
if [  $? -ne 0 ]
    then
                php php.php #注意这里不在加 ./ 因为php已经设置环境变量
fi


效果:

初始:

微信截图_20190216145821.png

等待一会,结束掉php的进程。

1550300347(1).png

最终

微信截图_20190216150101.png

Linux supervise进程守护

Daemontools是Linux下的一个软件包,里面包含了supervise。而利用supervise可以达到进程关闭后重启的目的。这种技术也叫作进程守护。

安装

PuTTY连接服务器

1、cd / #切换到根目录

2、 mkdir supervise #新建一个目录 例如:supervise

3、chmod  777 supervise #设置文件夹的权限为777(或者利用WinScp来操作)

4、cd supervise #切换到supervise目录

5、wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz #下载Daemontools源码到supervise

6、tar -xpf daemontools-0.76.tar.gz #解压源码包

7、rm -f daemontools-0.76.tar.gz #删除源码包

8、cd admin/daemontools-0.76 #切换到源码包的目录里

9、wget http://www.qmail.org/moni.csi.hu/pub/glibc-2.3.1/daemontools-0.76.errno.patch #下载一个补丁,用于编译,如果没有这个补丁文件,有可能编译会出错。

10、patch -Np1 -i daemontools-0.76.errno.patch #安装补丁

11、sudo package/install #进行编译Daemontools并且安装,尽量加上sudo提权指令。

12、sudo apt-get install csh #安装csh 也可省略

13、csh -cf '/command/svscanboot &' #启动svscanboot

启动svscanboot会经历如下启动过程:svscanboot启动之后会启动svscan,svscan会启动supervise,supervise会启动并监听/service中存放服务目录下的run可执行文件。

编写脚本

新建一个文件夹:test(可自定义名称),里面需要有一个且必须有一个的文件:run(注意:这个文件是没有后缀的)。

源码:

const char *run[2] = { "./run", 0 };

这个文件最好使用vi来编辑,如果你是在window下用notepad++或其他文本工具编辑的话,文件格式是无法在linux被识别的,也就会抛错。

源码:

  if (stat("down",&st) != -1)
    flagwantup = 0;
  else
    if (errno != error_noent)
      strerr_die4sys(111,FATAL,"unable to stat ",dir,"/down: ");

如果你想在window下编辑,那么你需要在linxu上这样操作:

1、vi run #打开run

2、:set fileformat=unix #执行这条命令

3、:wq #执行这条命令保存并退出

脚本内容:

#!/bin/sh #指定文件是一个脚本文件

./iwonmo  #运行程序,./ 的意思是在当前目录下。如果不加的话,linux脚本执行器会把它当成环境变量

执行脚本:

nohup supervise test/  > /dev/null 2>&1 &  #nohup 后台运行的语法规则,其中的> /dev/null 2>&1 &是输出级别,可以查阅nohup的使用方法

效果:终止iwonmo程序后会立马在启动iwonmo程序。如果需要修改iwonmo程序的话,先要终止守护进程,然后在终止iwonmo。

微信截图_20190216144029.png

终止程序指令:kill -9 pid #这里进来发送9信号,结束程序比较安全。

redis 订阅

index.php  web方式访问

<?php
$redis = new Redis();  
$redis->connect("127.0.0.1","6379"); 
$order_id = 12;
//$redis->PUBLISH("cccc","手动的信息来了");
$redis->setex($_POST['id'],1,$order_id);
exit($_POST['id']);

psubscribe.php Cli模式运行

<?php
$redis = new Redis();  
$redis->connect("127.0.0.1","6379");  //php客户端设置的ip及端口  
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
$redis->psubscribe(array('__keyevent@0__:expired','__keyevent@1__:expired','__keyevent@2__:expired','__keyevent@3__:expired','__keyevent@4__:expired','__keyevent@5__:expired','__keyevent@6__:expired','__keyevent@7__:expired','__keyevent@8__:expired','__keyevent@9__:expired','__keyevent@10__:expired','__keyevent@11__:expired','__keyevent@12__:expired','__keyevent@13__:expired','__keyevent@14__:expired','cccc'), 'keyCallback');
// 回调函数,这里写处理逻辑
function keyCallback($redis, $pan, $chan, $msg)
{ 
echo "$msg\n\n";
}

直接php psubscribe.php运行。

运行前需要修改redis的配置文件,里面有一个未开启的选项。

微信截图_20190215171757.png修改完毕后,重启redis。

高并发测试:

微信截图_20190215171657.png

回调显示

微信截图_20190215171718.png

excel整理后

微信截图_20190215171641.png


可以发现没有漏掉的情况。


并行和并发

并行:多个任务同一时间执行。

    两个人同时去挖坑,1小时内挖了直径2米的坑

并发:同一时间执行多个任务。

    两个人交替去挖坑,1小时内挖了直径1米的坑

关键:同时、交替、效率。 

即:并行是同时发生,并发是交替发生。并发的效率小于并行。

高并发:在极短的时间内,有极多的任务。

高并行:不存在,极多任务也是同时去执行。

产生高并发的问题:交替。在计算机微观里,CPU是无法同时执行很多个程序的,虽然在宏观上感觉是同时执行。比如同时开两个音乐播放器,可以听到两首歌。但是实际上CPU是通过不断的切换(时间片)来达到这个目的的。播放器A在播放的时候播放器B是停止的。然后播放器B播放时播放器A是停止的,不过由于CPU切换的速度非常快,所以人感受上是分辨不出来的,就像是显示屏的刷新频率60HZ,屏幕一直在刷新,只是人感官上是感受不到的。由于CPU交替切换的,所以会产生一个资源竞争的问题。这个问题的产生是因为IO读写,IO分为两种:文件IO网络IO

例如:Mysql

Mysql是存储在磁盘上的,每次读取的时候相当于从磁盘去读取,所以产生了一个文件IO。A用户正在读X字段,但是B用户正在写X字段,本来是B先执行写操作,但是在还没有写入的时候CPU切换了执行的程序,切换到A,那么A去读的数据就是B未写入前的数据,但是我们理想状态是B先写A在读。由于存在切换,并且是操作同一个字段,所以会产生资源竞争。即高并发问题。本身高并发并不会造成资源竞争,但是如果你的资源是同一个资源的话,那么就会产生高并发。不过如果你每个链接都是访问的不同地址的话,那么也就不是并发而是并行了。

总结:并发:宏观上感觉是同时执行,但是微观上是交替进行。并行:宏观微观都是同时执行。

微擎 Redis Mysql 高并发

1、宝塔安装

软件管理-PHP-设置-安装扩展-redis

2、微擎配置

文件:data/config.php

$config['setting']['cache'] = 'redis'; [35行左右] 缓存改为redis。

最下面加上

// --------------------------  CONFIG REDIS  --------------------------- //

$config['setting']['redis']['server'] = '127.0.0.1';//如果redis服务器在别的机器,请填写机器的IP地址。

$config['setting']['redis']['port'] = 6379;

$config['setting']['redis']['pconnect'] = 0;

$config['setting']['redis']['timeout'] = 1;

$config['setting']['redis']['auth'] = 'iwonmo'; //微擎

$config['setting']['redis']['requirepass'] = 'iwonmo';//人人用这个


auth 配置需要到redis的配置文档里进行配置,在微擎里如上定义只是方便引用。

3、更新微擎缓存

微擎后台-系统-更新缓存

4、查看是否开启成功

微擎后台-站点-性能优化

微信截图_20190213150825.png

5、测试代码

    public function build_sn(){
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[rand(0,9)] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
        return $orderSn;
    }
    public function doPageRedis_setRedPack(){
        global  $_W;
        $redisConfig = $_W["config"]['setting']['redis'];
        $redis = new Redis();
        $redis->pconnect($redisConfig['server'], $redisConfig['port'],$redisConfig['timeout']);
//        随机一个红包Key
        $key = $this->build_sn();
        for ($i = 1; $i <= 10; $i++)
        {
            $redis->lpush($key, $i);
        }
//        写入到数据库
        $RedPack_data = array(
            'num' => 10,
        );
        $result = pdo_insert('redis_test', $RedPack_data);
//        返回前端信息 - 抢红包
        if (!empty($result)) {
            echo "id:".pdo_insertid()."  RadKey:".$key;
        }else{
            echo "RadPack:Error";
        }
    }
    public function doPageRedis_test(){
        global  $_W,$_GPC;
        $redisConfig = $_W["config"]['setting']['redis'];
        $redis = new Redis();
        $redis->pconnect($redisConfig['server'], $redisConfig['port'],$redisConfig['timeout']);
//        返回列表的长度  key 被解释为一个空列表,返回 0
        if($redis->llen($_GPC['RadKey']) == 0) return $this->result($errno = 0, $message = 'No Pack');
//        移除并返回列表的第一个元素
        $List = $redis->lpop($_GPC['RadKey']);
        if(intval($List) > 0){
            $result = pdo_update('redis_test', array('num' => $List-1), array('id' => $_GPC['id']));
            if (!empty($result)) return $this->result($errno = 0, $message = 'Get Ok:'.$List); else return $this->result($errno = 0, $message = 'Get Error:'.$List);
        }else
            return $this->result($errno = 1, $message = 'Error:High incidence of complications','llen(RadKey) == 0');
    }

生成红包:Redis_setRedPack

拆开红包:Redis_test

    POST:id=[红包ID]&RadKey=[RdisListKey]

使用:访问Redis_setRedPack创建红包,会返回ID和RdisListKey。继而访问Redis_test拆开红包。

6、高并发测试

软件会测 [H.Test]

并发30个链接结果:

会测.png

7、缓存数据库情况

微信截图_20190213152109.png