美文网首页
15.Swoole+PHP7+Redis+ThinkPHP5.1

15.Swoole+PHP7+Redis+ThinkPHP5.1

作者: 一枼落知天下 | 来源:发表于2019-06-28 00:27 被阅读0次

    192.168.31.62    Swoole+PHP7+Redis
    192.168.31.63    Swoole+PHP7
    192.168.31.64    Nginx+HTML
    

    Nginx配置

    upstream liveChartWS {
            server 192.168.31.62:8080;
            server 192.168.31.63:8080;
        }
    
        server {
            listen       80;
            server_name  live.zhou.com;
    
            #charset koi8-r;
    
            access_log  logs/host.access.log  main;
    
            location  ~ \/(live|chart)$ {
                proxy_pass http://liveChartWS;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
            }
    
            location / {
                root   /home/thinkPHP/public/static;
                index  index.html index.htm;
                if (!-e $request_filename){
                  proxy_pass http://liveChartWS;
                }
            }
    }
    

    启动swoole

      netstat -anp 2>/dev/null | grep 8080 | grep LISTEN |wc -l
      nohup /usr/local/bin/php /home/thinkPHP/server/ws.php >> /home/thinkPHP/server/logs/SERVER-`date +%Y-%m-%d`.log 2>&1 & 
    
    目录结构

    reload.sh

    #! /usr/bin/env bash
    echo "Loading..."
    pid=`pidof LIVE_MASTER`
    echo $pid
    kill -USR1 $pid
    echo "Loading Success"
    

    HTTP WEBSOCKET SERVER

    <?php
    /**
     * WebSocket
     * netstat -anp 2>/dev/null | grep 8080 | grep LISTEN |wc -l
     * 
     * nohup /usr/local/bin/php /home/thinkPHP/server/ws.php >> /home/thinkPHP/server/logs/SERVER-`date +%Y-%m-%d`.log 2>&1 & 
     */
    
    class Ws 
    {
        CONST HOST = "0.0.0.0";
        CONST PORT = 8080;
    
        public $ws    = null;
        public $redis = null;
    
        public function __construct(){
            //创建websocket服务器对象,监听0.0.0.0:9502端口
            $this->ws = new swoole_websocket_server(self::HOST,self::PORT);
            $this->ws->set(
                [
                    'worker_num'=>4,
                    'task_worker_num'=>4,
                    'enable_static_handler'=>true,
                    'document_root'=> "/home/thinkPHP/public/static",
                ]
            );
    
            
            $this->ws->on('start',[$this,'onStart']);
            $this->ws->on('workerStart',[$this,'onWorkerStart']);
            $this->ws->on('open',[$this,'onOpen']);
            $this->ws->on("message",[$this,"onMessage"]);
            $this->ws->on("request",[$this,"onRequest"]);
            $this->ws->on("task",[$this,"onTask"]);
            $this->ws->on("finish",[$this,"onFinish"]);
            $this->ws->on("close",[$this,"onClose"]);
    
            $this->redis = new \Redis();
            $result = $this->redis->connect('192.168.31.62',6379,10);
            if ($result == false){
                throw new \Exception("Redis connect error");
            }
            $this->redis->del('live');
            $this->redis->del('chart');
            $this->redis->close();
            $this->redis = null;
    
            $this->ws->start();
        }
    
        public function onStart($server){
            // echo "Master_pid: {$server->master_pid}-Manager_pid:{$server->manager_pid}\n";
            swoole_set_process_name("LIVE_MASTER");
        }
    
    
        /**
         * [onWorkerStart 回调]
         * @author Jhou Shuai
         * @datetime 2019-06-24T13:58:54+0800 
         */
        public function onWorkerStart($server,$worker_id){
            // 加载基础文件
            require __DIR__ . '/../thinkphp/base.php';
        }
    
    
        /**
         * [onRequest 回调]
         * @author Jhou Shuai
         * @datetime 2019-06-24T14:00:23+0800
         */
        public function onRequest($request, $response){
            if ($request->server['request_uri']=='/favicon.ico'){
                $response->status(404);
                $response->end();
                return ;
            }
    
            $_GET = $_POST = [];
    
            if(isset($request->server)){
                foreach ($request->server as $key => $value) {
                    $_SERVER[strtoupper($key)] = $value;
                }
            }
    
            if(isset($request->header)){
                foreach ($request->header as $key => $value) {
                    $_SERVER[strtoupper($key)] = $value;
                }
            }
    
            if(isset($request->get)){
                foreach ($request->get as $key => $value) {
                    $_GET[$key] = $value;
                }
            }
    
            
            if(isset($request->post)){
                foreach ($request->post as $key => $value) {
                    $_POST[$key] = $value;
                }
            }
            
            $_FILE = [];
            if(isset($request->files)){
                foreach ($request->files as $key => $value) {
                    $_FILE[$key] = $value;
                }
            }
    
            $_POST['http_server'] = $this->ws;
    
            ob_start();
    
            try{
                // 执行应用并响应
                think\Container::get('app')->run()->send();
            }catch(\Exception $e){
                //todo
            }
            $res = ob_get_contents();
            ob_end_clean();
    
    
            $response->header("Content-Type", "text/html; charset=utf-8");
            $response->end($res);
        }
    
        /**
         * [onOpen 监听WebSocket连接打开事件]
         * @author Jhou Shuai
         * @datetime 2019-06-24T13:58:54+0800
         * @param    [type]                   $ws     
         * @param    [type]                   $repuest 
         */
        public function onOpen($ws,$request){
            if (!empty($request->server['path_info'])) {
                $key = trim(ltrim($request->server['path_info'], '/'));
                print_r($key."==>".$request->fd."\n");
                app\common\lib\Redis::getInstance()->sAdd($key,$request->fd);
            }else{
                $ws->push($request->fd, "服务器连接错误~~~");
            }
        }
    
    
        /**
         * [onMessage 监听WebSocket消息事件]
         * @author Jhou Shuai
         * @datetime 2019-06-24T14:00:23+0800
         * @param    [type] $ws    
         * @param    [type] $frame 
         */
        public function onMessage($ws,$frame){
            // 接收到客户端的消息,下面的业务逻辑
            echo "Message: {$frame->data}-Date:".date("Y-m-d")."\n";
            // 接收到客户端的消息,下面的业务逻辑,非常耗时 
            // todo 10s
            // swoole Task机制
            // $data = [
            //  'task'=>1,
            //  'fd'=>$frame->fd,
            // ];
            // $ws->task($data);
            // 
            // $ws->push($frame->fd, "Server: {$frame->data} Date:".date("Y-m-d  H:i:s"));
        }
    
        /**
         * [onClose 监听WebSocket连接关闭事件]
         * @author Jhou Shuai
         * @datetime 2019-06-24T14:01:29+0800
         * @param    [type]                   $ws 
         * @param    [type]                   $fd 
         */
        public function onClose($ws, $fd){
            echo "client-{$fd} is closed\n";
            app\common\lib\Redis::getInstance()->sRem("live",$fd);
            app\common\lib\Redis::getInstance()->sRem("chart",$fd);
        }
    
        /**
         * [onTask ]
         * @author Jhou Shuai
         * @datetime 2019-06-24T14:49:27+0800
         * @param    [type]                   $ws      
         * @param    [type]                   $taskId   
         * @param    [type]                   $workerId 
         * @param    [type]                   $data     
         */
        public function onTask($serv,$taskId,$workerId,$data){
            print_r($data);
            sleep(10);
            return "On Task Finish";
        }
    
        /**
         * [onFinish ]
         * @author Jhou Shuai
         * @datetime 2019-06-24T14:51:48+0800
         * @param    [type]                   $serv   
         * @param    [type]                   $taskId 
         * @param    [type]                   $data   
         */
        public function onFinish($serv,$taskId,$data){
            echo "{$taskId}-{$data}--Succ Task\n";
        }
    }
    
    new Ws();
    

    Index.php

    <?php
    namespace app\index\controller;
    
    use app\common\lib\Util;
    
    class Index extends \think\Controller
    {
        
        public function index(){
            return Util::return_client(config('code.success'),'成功!',$_GET);
        }
    
        public function hello($name = 'ThinkPHP5')
        {
            print_r(request()->get());
            print_r(request()->post());
            return 'hello,' . $name;
        }
    }
    

    Live.php

    <?php
    namespace app\index\controller;
    
    use app\common\lib\Util;
    use app\common\lib\Redis;
    
    class Live extends \think\Controller
    {
        
        public function push(){
            $msg = request()->get('msg');
            // 把数据push到直播页面。
            // todo 业务逻辑~~~~
            $info = !empty($msg)?trim($msg):"你有新短消息来啦~~~";
            $server = $_POST['http_server'];
            // $server->task();
            $client = Redis::getInstance()->sMembers(config("redis.live"));
            foreach ($client as $key => $fd) {
                $server->push($fd,$info);
            }
            return Util::return_client(config('code.success'),'Push Live Msg Success~~',$client);
        }
    
    }
    

    Chart.php

    <?php
    namespace app\index\controller;
    
    use app\common\lib\Util;
    use app\common\lib\Redis;
    
    class Chart extends \think\Controller
    {
        
        public function send(){
            $msg = request()->get('msg');
            // 把数据push到聊天专用页面。
            // todo 业务逻辑~~~~
            $info = !empty($msg)?trim($msg):"你有新短消息来啦~~~";
            $server = $_POST['http_server'];
            // $server->task();
            $client = Redis::getInstance()->sMembers(config("redis.chart"));
            foreach ($client as $key => $fd) {
                $server->push($fd,$info);
            }
            return Util::return_client(config('code.success'),'Send Chart Msg Success~~',$client);
        }
    
    }
    

    Redis.php

    <?php
    
    namespace app\common\lib;
    
    class Redis {
    
        public $redis = "";
        /**
         * 定义单例模式的变量
         * @var null
         */
        private static $_instance=null;
    
        private function __construct(){
            $this->redis = new \Redis();
            $result = $this->redis->connect('192.168.31.62',6379,10);
            if ($result == false){
                throw new \Exception("Redis connect error");
                
            }
        }
    
    
        public static function getInstance() {
            if(empty(self::$_instance)){
                self::$_instance = new self();
            }
            return self::$_instance;
        }
    
        public function get($key){
            # code...
        }
    
        public function sAdd($key,$value){
            return $this->redis->sAdd($key,$value);
        }
    
        public function sRem($key,$value){
            return $this->redis->sRem($key,$value);
        }
    
        public function sMembers($key)
        {
            return $this->redis->sMembers($key);
        }
    
        /**
         * 清空当前数据库
         * @return bool
         */
        public function flushDB(){
            return $this->redis->flushDB();
        }
    
        public function del($key){
            return $this->redis->del($key);
        }
    
        /**
         * [__destruct 释放连接]
         * @author Jhou Shuai
         */
        private function __destruct() {
           $this->redis->close();
        }
    }
    

    Util.php

    <?php
    
    namespace app\common\lib;
    
    class Util {
    
        /**
         * [return_client 给客户端输出数据]
         * @author Jhou Shuai
         * @datetime 2019-06-25T16:53:59+0800
         */
        public static function return_client($status,$msg='',$data=[]){
            $result = [
                'status'   => $status,
                'message'  => $msg,
                'data'     => $data,    
                'curtime'  => date("Y-m-d,H:i:s"),
            ];
            return json_encode($result);
        }
    
    }
    

    config/code.php

    <?php
    
    
    return [
        "success" => '0000',
        "error"   => '1000',
    ];
    

    config/redis.php

    <?php
    
    return [
        'host'        => '192.168.31.62',
        'password'    => '',
        'port'        => 6379,
        'timeout'     => 5,
        'live'        =>'live',
        'chart'       =>'chart',
    ];
    
    

    index.html

    <!DOCTYPE html>
    <html>
    <head>
    <title>玫瑰之约<Swoole.WebSocket.JhouShuai></title>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> 
    </head>
    <body>
    <h1>玫瑰之约~~来啦,老弟!@JhouShuai</h1>
    <p style="text-align: center;">
    <canvas id="c" height="500" width="500"></canvas>
    <script>
     var b = document.body;
     var c = document.getElementsByTagName('canvas')[0];
     var a = c.getContext('2d');
     document.body.clientWidth;
    </script>
    <script>
    with(m=Math)C=cos,S=sin,P=pow,R=random;c.width=c.height=f=500;h=-250;function p(a,b,c){if(c>60)return[S(a*7)*(13+5/(.2+P(b*4,4)))-S(b)*50,b*f+50,625+C(a*7)*(13+5/(.2+P(b*4,4)))+b*400,a*1-b/2,a];A=a*2-1;B=b*2-1;if(A*A+B*B<1){if(c>37){n=(j=c&1)?6:4;o=.5/(a+.01)+C(b*125)*3-a*300;w=b*h;return[o*C(n)+w*S(n)+j*610-390,o*S(n)-w*C(n)+550-j*350,1180+C(B+A)*99-j*300,.4-a*.1+P(1-B*B,-h*6)*.15-a*b*.4+C(a+b)/5+P(C((o*(a+1)+(B>0?w:-w))/25),30)*.1*(1-B*B),o/1e3+.7-o*w*3e-6]}if(c>32){c=c*1.16-.15;o=a*45-20;w=b*b*h;z=o*S(c)+w*C(c)+620;return[o*C(c)-w*S(c),28+C(B*.5)*99-b*b*b*60-z/2-h,z,(b*b*.3+P((1-(A*A)),7)*.15+.3)*b,b*.7]}o=A*(2-b)*(80-c*2);w=99-C(A)*120-C(b)*(-h-c*4.9)+C(P(1-b,7))*50+c*2;z=o*S(c)+w*C(c)+700;return[o*C(c)-w*S(c),B*99-C(P(b, 7))*50-c/3-z/1.35+450,z,(1-b/1.2)*.9+a*.1, P((1-b),20)/4+.05]}}setInterval('for(i=0;i<1e4;i++)if(s=p(R(),R(),i%46/.74)){z=s[2];x=~~(s[0]*f/z-h);y=~~(s[1]*f/z-h);if(!m[q=y*f+x]|m[q]>z)m[q]=z,a.fillStyle="rgb("+~(s[3]*h)+","+~(s[4]*h)+","+~(s[3]*s[3]*-80)+")",a.fillRect(x,y,1,1)}',0)
    </script>
    </p>
    <script type="text/javascript">
    (function(win) {
        var Client = function(options) {
          var MAX_CONNECT_TIMES = 10;
          var DELAY = 15000;
          this.options = options || {};
          this.createConnect(MAX_CONNECT_TIMES, DELAY);
        }
    
        Client.prototype.createConnect = function(max, delay) {
            var self = this;
            if (max === 0) {
              return;
            }
    
            connect();
    
            function connect() {
                var domain = document.domain;
                var ws = new WebSocket('ws://'+domain+'/live');
                ws.onopen = function() {
                    auth();
                    register();
                }
    
                ws.onmessage = function(evt) {
                    var data = evt.data;
                    var notify = self.options.notify;
                    if(notify) notify(data);
                }
    
                ws.onclose = function() {
                    console.log("连接断开咯~~~重连中~~~")
                    setTimeout(reConnect, delay);
                }
    
                function auth() {
                    // 可以做认证
                    ws.send("帅哥请求进入~~~");
                }
    
                function register() {
                    // 注册
                    ws.send("小可爱来啦~~~~");
                }
            }
    
            function reConnect() {
                self.createConnect(--max, delay * 2);
            }
        }
    
      win['MyClient'] = Client;
    })(window);
    var client = new MyClient({
      notify: function(data) {
        console.log(data);
        alert(JSON.stringify(data));
      }
    });
    </script>
    </body>
    </html>
    

    chart.html

    <!DOCTYPE html>
    <html>
    <head>
    <title>小嘴抹蜜,口吐芬芳~~<Swoole.WebSocket.JhouShuai></title>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> 
    </head>
    <body>
    <h1>小嘴抹蜜,口吐芬芳~~@JhouShuai</h1>
    <p style="text-align: center;">
    <canvas id="c" height="500" width="500"></canvas>
    <script>
     var b = document.body;
     var c = document.getElementsByTagName('canvas')[0];
     var a = c.getContext('2d');
     document.body.clientWidth;
    </script>
    <script>
    with(m=Math)C=cos,S=sin,P=pow,R=random;c.width=c.height=f=500;h=-250;function p(a,b,c){if(c>60)return[S(a*7)*(13+5/(.2+P(b*4,4)))-S(b)*50,b*f+50,625+C(a*7)*(13+5/(.2+P(b*4,4)))+b*400,a*1-b/2,a];A=a*2-1;B=b*2-1;if(A*A+B*B<1){if(c>37){n=(j=c&1)?6:4;o=.5/(a+.01)+C(b*125)*3-a*300;w=b*h;return[o*C(n)+w*S(n)+j*610-390,o*S(n)-w*C(n)+550-j*350,1180+C(B+A)*99-j*300,.4-a*.1+P(1-B*B,-h*6)*.15-a*b*.4+C(a+b)/5+P(C((o*(a+1)+(B>0?w:-w))/25),30)*.1*(1-B*B),o/1e3+.7-o*w*3e-6]}if(c>32){c=c*1.16-.15;o=a*45-20;w=b*b*h;z=o*S(c)+w*C(c)+620;return[o*C(c)-w*S(c),28+C(B*.5)*99-b*b*b*60-z/2-h,z,(b*b*.3+P((1-(A*A)),7)*.15+.3)*b,b*.7]}o=A*(2-b)*(80-c*2);w=99-C(A)*120-C(b)*(-h-c*4.9)+C(P(1-b,7))*50+c*2;z=o*S(c)+w*C(c)+700;return[o*C(c)-w*S(c),B*99-C(P(b, 7))*50-c/3-z/1.35+450,z,(1-b/1.2)*.9+a*.1, P((1-b),20)/4+.05]}}setInterval('for(i=0;i<1e4;i++)if(s=p(R(),R(),i%46/.74)){z=s[2];x=~~(s[0]*f/z-h);y=~~(s[1]*f/z-h);if(!m[q=y*f+x]|m[q]>z)m[q]=z,a.fillStyle="rgb("+~(s[3]*h)+","+~(s[4]*h)+","+~(s[3]*s[3]*-80)+")",a.fillRect(x,y,1,1)}',0)
    </script>
    </p>
    <script type="text/javascript">
    (function(win) {
        var Client = function(options) {
          var MAX_CONNECT_TIMES = 10;
          var DELAY = 15000;
          this.options = options || {};
          this.createConnect(MAX_CONNECT_TIMES, DELAY);
        }
    
        Client.prototype.createConnect = function(max, delay) {
            var self = this;
            if (max === 0) {
              return;
            }
    
            connect();
    
            function connect() {
                var domain = document.domain;
                var ws = new WebSocket('ws://'+domain+'/chart');
                ws.onopen = function() {
                    auth();
                    register();
                }
    
                ws.onmessage = function(evt) {
                    var data = evt.data;
                    var notify = self.options.notify;
                    if(notify) notify(data);
                }
    
                ws.onclose = function() {
                    console.log("连接断开咯~~~重连中~~~")
                    setTimeout(reConnect, delay);
                }
    
                function auth() {
                    // 可以做认证
                    ws.send("帅哥进入聊天室~~~");
                }
    
                function register() {
                    // 注册
                    ws.send("嘤嘤嘤进入聊天室~~~~");
                }
            }
    
            function reConnect() {
                self.createConnect(--max, delay * 2);
            }
        }
    
      win['MyClient'] = Client;
    })(window);
    var client = new MyClient({
      notify: function(data) {
        console.log(data);
        alert(JSON.stringify(data));
      }
    });
    </script>
    </body>
    </html>
    

    最终效果:

    相关文章

      网友评论

          本文标题:15.Swoole+PHP7+Redis+ThinkPHP5.1

          本文链接:https://www.haomeiwen.com/subject/npudcctx.html