从0开始搭建开发easyswoole

2020/10/14 08:47
阅读数 64

需要帮助/做项目/交朋友可加微信:a2106593278

在linux上安装php7.3

下载php7.3安装包,因为easyswoole安装环境需要大于php7.1,所以我们安装php7.3 php下载地址:
https://www.php.net/downloads.php
安装php7.3

安装依赖包

yum install -y zip unzip autoconf gcc gcc-c++  make zlib zlib-devel pcre pcre-devel  libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers

解压

tar -zxvf php-7.3.22.tar.gz
cd php-7.3.22

配置

./configure \
--prefix=/usr/local/php \
--exec-prefix=/usr/local/php \
--bindir=/usr/local/php/bin \
--sbindir=/usr/local/php/sbin \
--includedir=/usr/local/php/include \
--libdir=/usr/local/php/lib/php \
--mandir=/usr/local/php/php/man \
--with-config-file-path=/usr/local/php/etc \
--with-openssl \
--enable-mbstring \
--enable-fpm

编译安装

make && make install

复制php.ini

在之前编译的源码包中,找到 php.ini-production,复制到/usr/local/php/etc下,并改名为php.ini

cp php.ini-production /usr/local/php/etc/php.ini

将php源码编译目录下的 sapi/fpm/init.d.php-fpm 文件拷贝到系统配置 /etc/init.d 目录下并重命名为 php-fpm

cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm

添加 php-fpm 配置文件
将php安装目录下的 /usr/local/php/etc/php-fpm.conf.default 文件拷贝同目录下并重命名为 php-fpm.conf

cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf 

添加 www.conf 配置文件
将php安装目录下的 /usr/local/php/etc/php-fpm.d/www.conf.default 文件拷贝同目录下并重命名为 www.conf

cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf 

添加php安装目录到系统环境变量
创建并打开文件php.sh

vi /etc/profile.d/php.sh 

添加内容如下

export PATH=$PATH:/usr/local/php/bin/:/usr/local/php/sbin/ 

保存并退出

:wq

使用source立即生效刚刚添加的php环境变量

source /etc/profile.d/php.sh

启动php-fpm

service php-fpm start

设置php开机启动

#修改系统配置目录下的 php-fpm 文件可执行权限 
chmod +x /etc/init.d/php-fpm
#将系统配置目录下的 `php-fpm` 添加到 `系统服务`
chkconfig --add php-fpm
#设置 `php-fpm` `系统服务` 为开机启动
chkconfig php-fpm on

查看是否安装成功

#出现版本号则安装成功
php -v

安装swoole扩展

首先进入swoole的github下载地址: https://github.com/swoole/swoole-src/releases
如果没有特殊需求,请选择最新版本开始下载(我这里是最新版是v4.4.21):

wget https://github.com/swoole/swoole-src/archive/v4.4.21.tar.gz ## 下载
tar -zvxf v4.4.21.tar.gz  ## 解压到当前目录
cd swoole-src-4.4.21/ ## cd目录
phpize ## 使用phpize创建php编译检测脚本 ./configure
./configure --with-php-config=/usr/local/php/bin/php-config --enable-openssl  ## 创建编译文件,第一个--with,后面是php的安装路径/bin/php-config ,第二个--enable,是开启swoole的ssl功能
sudo make && make install  ## 编译swoole并把编译好的文件移动到php的扩展目录(前面的配置php版本的扩展目录) 需要root权限

这个时候已经安装成功,需要进入php.ini,在最后面增加上:

extension=swoole.so

成功安装swoole,通过php --ri swoole 查看swoole扩展的信息:

php --ri swoole

出现下面的情况则是安装成功

swoole

Swoole => enabled
Author => Swoole Team <team@swoole.com>
Version => 4.4.21
Built => Oct 13 2020 10:14:03
coroutine => enabled
epoll => enabled
eventfd => enabled
signalfd => enabled
cpu_affinity => enabled
spinlock => enabled
rwlock => enabled
openssl => OpenSSL 1.0.2k-fips  26 Jan 2017
pcre => enabled
zlib => 1.2.7
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled
async_redis => enabled

Directive => Local Value => Master Value
swoole.enable_coroutine => On => On
swoole.enable_library => On => On
swoole.enable_preemptive_scheduler => Off => Off
swoole.display_errors => On => On
swoole.use_shortname => On => On
swoole.unixsock_buffer_size => 8388608 => 8388608

安装composer

安装前请务必确保已经正确安装了 PHP。打开命令行窗口并执行 php -v 查看是否正确输出版本号。打开命令行并依次执行下列命令安装最新版本的 Composer:

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php

如果出现下面的报错,可以忽略

Downloading...

Composer (version 1.10.13) successfully installed to: /home/down/composer.phar
Use it: php composer.phar

Some settings on your machine may cause stability issues with Composer.
If you encounter issues, try to change the following:

The zlib extension is not loaded, this can slow down Composer a lot.
If possible, install it or recompile php with --with-zlib

The php.ini used by your command-line PHP is: /usr/local/php/etc/php.ini
If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.

执行第三条命令

php -r "unlink('composer-setup.php');"

上述 3 条命令的作用依次是:
下载安装脚本 - composer-setup.php - 到当前目录。
执行安装过程。
删除安装脚本。


全局安装

sudo mv composer.phar /usr/local/bin/composer

检查一下是否安装成功

[root@localhost down]# composer 
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.10.13 2020-09-09 11:46:34

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
  -q, --quiet                    Do not output any message
  -V, --version                  Display this application version
      --ansi                     Force ANSI output
      --no-ansi                  Disable ANSI output
  -n, --no-interaction           Do not ask any interactive question
      --profile                  Display timing and memory usage information
      --no-plugins               Whether to disable plugins.
  -d, --working-dir=WORKING-DIR  If specified, use the given directory as working directory.
      --no-cache                 Prevent use of the cache
  -v|vv|vvv, --verbose           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

提示:不要忘了经常执行 composer selfupdate 以保持 Composer 一直是最新版本哦!

设置阿里镜像

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

安装easyswoole框架

composer require easyswoole/easyswoole=3.x

如果我们是服务器的root账号会报错,告诉我们不能用root账号来运行composer,所以我们新创建一个账号并给他root的权限:

[root@localhost easyswoole]# composer require easyswoole/easyswoole=3.x
Do not run Composer as root/super user! See https://getcomposer.org/root for details

所以我们需要创建一个新的用户账号,并且给它root账号的权限,方便我们以后操作,为了方便我们也给它设置切换账号的时候不用重新输入密码,此处我们添加一个账号swoole,密码也是swoole

useradd swoole
passwd swoole

给这个账号设置root权限并且免密码

vi /etc/sudoers

添加下面的两行代码

swoole         ALL=(ALL)        ALL
swoole         ALL=(ALL)        NOPASSWD:ALL

下面是在文本中内容举例:

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
swoole  ALL=(ALL)       ALL
## Allows members of the 'sys' group to run networking, software,
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL
swoole         ALL=(ALL)        NOPASSWD:ALL

保存退出

:wq!

切换账号

su swoole

把我们的项目目录添加权限,以便安装项目,然后进入项目目录,进行安装easyswoole

sudo chmod -R 777 program
cd program

安装easyswoole

composer require easyswoole/easyswoole=3.x
php vendor/easyswoole/easyswoole/bin/easyswoole install

安装成功

[swoole@localhost easyswoole]$ php vendor/easyswoole/easyswoole/bin/easyswoole install
  ______                          _____                              _
 |  ____|                        / ____|                            | |
 | |__      __ _   ___   _   _  | (___   __      __   ___     ___   | |   ___
 |  __|    / _` | / __| | | | |  \___ \  \ \ /\ / /  / _ \   / _ \  | |  / _ \
 | |____  | (_| | \__ \ | |_| |  ____) |  \ V  V /  | (_) | | (_) | | | |  __/
 |______|  \__,_| |___/  \__, | |_____/    \_/\_/    \___/   \___/  |_|  \___|
                          __/ |
                         |___/
install success,enjoy!  
dont forget run composer dump-autoload  

启动框架

php easyswoole start

启动成功显示如下

php easyswoole start
  ______                          _____                              _
 |  ____|                        / ____|                            | |
 | |__      __ _   ___   _   _  | (___   __      __   ___     ___   | |   ___
 |  __|    / _` | / __| | | | |  \___ \  \ \ /\ / /  / _ \   / _ \  | |  / _ \
 | |____  | (_| | \__ \ | |_| |  ____) |  \ V  V /  | (_) | | (_) | | | |  __/
 |______|  \__,_| |___/  \__, | |_____/    \_/\_/    \___/   \___/  |_|  \___|
                          __/ |
                         |___/
main server                   SWOOLE_WEB
listen address                0.0.0.0
listen port                   9501
ip@ens33                      192.168.17.147
worker_num                    8
reload_async                  true
max_wait_time                 3
pid_file                      /home/program/easyswoole/Temp/pid.pid
log_file                      /home/program/easyswoole/Log/swoole.log
user                          swoole
daemonize                     false
swoole version                4.4.21
php version                   7.3.22
easy swoole                   3.3.7
develop/produce               develop
temp dir                      /home/program/easyswoole/Temp
log dir                       /home/program/easyswoole/Log

此时我们可以访问虚拟机中的项目http://192.168.17.147:9501/,如果打不开,请关闭虚拟机防火墙,很有可能是9501端口没有开启,成功之后,如下图
easyswoole安装成功

用window系统电脑开发easyswoole

因为我们的项目在linux虚拟机中运行,所以我们需要在本机上开发代码,实时同步到虚拟机中以便我们的开发,此处我用vscode编辑器来举例怎样同步开发项目
首先我们需要打包虚拟机中下载好的项目

zip -r easyswoole.zip * .[^.]*

解压到我们本地项目中,用vscode打开,然后安装插件

1.vscode 安装 sftp插件

在vscode中安装sftp插件扩展

2. 创建sftp配置

使用 ctrl+shift+p 快捷键调出输入框,选择 SFTP:Config 回车
会在 .vscode 目录下创建一个 sftp.json 配置文件,配置如下

{
    "name": "myserver",
    "host": "192.168.2.111",    
    "port": 22,     
    "username": "root", 
    "password": "xxxx", 
    "protocol": "sftp", 
    "passive": false,
    "interactiveAuth": false,
    "remotePath": "/usr/share/nginx/mwServer/web/laravel/",   
    "uploadOnSave": true, 
    "syncMode": "update",
    "ignore": [            
        "**/.vscode/**",
        "**/.git/**",
        "**/.DS_Store"
    ]
}

3. 上传本地代码到服务器

使用 ctrl+shift+p 快捷键调出输入框,选择 SFTP:Upload 回车
本地的项目代码就可以上传到服务器了
现在修改本地代码 ctrl+s 保存,即可同步到服务器了

EasySwoole服务热重启

由于 swoole 常驻内存的特性,修改文件后需要重启worker进程才能将被修改的文件重新载入内存中,我们可以自定义Process的方式实现文件变动自动进行服务重载
有时间把热启动代码备注一下

热重载进程

新建文件 App/Process/HotReload.php 并添加如下内容,也可以放在其他位置,请对应命名空间

<?php
/**
 * Created by PhpStorm.
 * User: evalor
 * Date: 2018-11-26
 * Time: 23:18
 */

namespace App\Process;

use EasySwoole\Component\Process\AbstractProcess;
use EasySwoole\EasySwoole\ServerManager;
use EasySwoole\Utility\File;
use Swoole\Process;
use Swoole\Table;
use Swoole\Timer;

/**
 * 暴力热重载
 * Class HotReload
 * @package App\Process
 */
class HotReload extends AbstractProcess
{
    /** @var \swoole_table $table */
    protected $table;
    protected $isReady = false;

    protected $monitorDir; // 需要监控的目录
    protected $monitorExt; // 需要监控的后缀

    /**
     * 启动定时器进行循环扫描
     */
    public function run($arg)
    {
        // 此处指定需要监视的目录 建议只监视App目录下的文件变更
        $this->monitorDir = !empty($arg['monitorDir']) ? $arg['monitorDir'] : EASYSWOOLE_ROOT . '/App';

        // 指定需要监控的扩展名 不属于指定类型的的文件 无视变更 不重启
        $this->monitorExt = !empty($arg['monitorExt']) && is_array($arg['monitorExt']) ? $arg['monitorExt'] : ['php'];

        if (extension_loaded('inotify') && empty($arg['disableInotify'])) {
            // 扩展可用 优先使用扩展进行处理
            $this->registerInotifyEvent();
            echo "server hot reload start : use inotify\n";
        } else {
            // 扩展不可用时 进行暴力扫描
            $this->table = new Table(512);
            $this->table->column('mtime', Table::TYPE_INT, 4);
            $this->table->create();
            $this->runComparison();
            Timer::tick(1000, function () {
                $this->runComparison();
            });
            echo "server hot reload start : use timer tick comparison\n";
        }
    }

    /**
     * 扫描文件变更
     */
    private function runComparison()
    {
        $startTime = microtime(true);
        $doReload = false;

        $dirIterator = new \RecursiveDirectoryIterator($this->monitorDir);
        $iterator = new \RecursiveIteratorIterator($dirIterator);
        $inodeList = array();

        // 迭代目录全部文件进行检查
        foreach ($iterator as $file) {
            /** @var \SplFileInfo $file */
            $ext = $file->getExtension();
            if (!in_array($ext, $this->monitorExt)) {
                continue; // 只检查指定类型
            } else {
                // 由于修改文件名称 并不需要重新载入 可以基于inode进行监控
                $inode = $file->getInode();
                $mtime = $file->getMTime();
                array_push($inodeList, $inode);
                if (!$this->table->exist($inode)) {
                    // 新建文件或修改文件 变更了inode
                    $this->table->set($inode, ['mtime' => $mtime]);
                    $doReload = true;
                } else {
                    // 修改文件 但未发生inode变更
                    $oldTime = $this->table->get($inode)['mtime'];
                    if ($oldTime != $mtime) {
                        $this->table->set($inode, ['mtime' => $mtime]);
                        $doReload = true;
                    }
                }
            }
        }

        foreach ($this->table as $inode => $value) {
            // 迭代table寻找需要删除的inode
            if (!in_array(intval($inode), $inodeList)) {
                $this->table->del($inode);
                $doReload = true;
            }
        }

        if ($doReload) {
            $count = $this->table->count();
            $time = date('Y-m-d H:i:s');
            $usage = round(microtime(true) - $startTime, 3);
            if (!$this->isReady == false) {
                // 监测到需要进行热重启
                echo "severReload at {$time} use : {$usage} s total: {$count} files\n";
                ServerManager::getInstance()->getSwooleServer()->reload();
            } else {
                // 首次扫描不需要进行重启操作
                echo "hot reload ready at {$time} use : {$usage} s total: {$count} files\n";
                $this->isReady = true;
            }
        }
    }

    /**
     * 注册Inotify监听事件
     */
    private function registerInotifyEvent()
    {
        // 因为进程独立 且当前是自定义进程 全局变量只有该进程使用
        // 在确定不会造成污染的情况下 也可以合理使用全局变量
        global $lastReloadTime;
        global $inotifyResource;

        $lastReloadTime = 0;
        $files = File::scanDirectory(EASYSWOOLE_ROOT . '/App');
        $files = array_merge($files['files'], $files['dirs']);

        $inotifyResource = inotify_init();

        // 为当前所有的目录和文件添加事件监听
        foreach ($files as $item) {
            inotify_add_watch($inotifyResource, $item, IN_CREATE | IN_DELETE | IN_MODIFY);
        }

        // 加入事件循环
        swoole_event_add($inotifyResource, function () {
            global $lastReloadTime;
            global $inotifyResource;
            $events = inotify_read($inotifyResource);
            if ($lastReloadTime < time() && !empty($events)) { // 限制1s内不能进行重复reload
                $lastReloadTime = time();
                ServerManager::getInstance()->getSwooleServer()->reload();
            }
        });
    }

    public function onShutDown()
    {
        // TODO: Implement onShutDown() method.
    }

    public function onReceive(string $str)
    {
        // TODO: Implement onReceive() method.
    }
}

添加好后在全局的 EasySwooleEvent.php 中,注册该自定义进程

use App\Process\HotReload;
public static function mainServerCreate(EventRegister $register)
{
    $swooleServer = ServerManager::getInstance()->getSwooleServer();
    $swooleServer->addProcess((new HotReload('HotReload', ['disableInotify' => false]))->getProcess());
}

因为虚拟机中inotify无法监听到FTP/SFTP等文件上传的事件,将 disableInotify 设置为 true ,可以关闭inotify方式的热重启,使得虚拟机环境下,强制使用文件循环扫描来触发重载操作,同理 OSX 开发环境下,没有Inotify扩展,将自动使用扫描式重载

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部