文章851
标签121
分类10

PHP 多进程开发中常用的PCNTL常用的函数

PHP进程控制函数库(PCNTL),使php能在类unix系统中实现跟c一样的创建子进程、使用exec函数执行程序、处理信号等功能。 PCNTL使用ticks来作为信号处理机制(signal handle callback mechanism),可以最小程度地降低处理异步事件时的负载。Tick 是一个在代码段中解释器每执行N条低级语句就会发生的事件,这个代码段需要通过declare来指定。php多进程开发中常用的PCNTL常用的函数列表如下:

1. pcntl_alarm ( int $seconds )

设置一个$seconds秒后发送SIGALRM信号的计数器

2. pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls ] )

$signo设置一个处理该信号的回调函数。下面是一个隔5秒发送一个SIGALRM信号,并由signal_handler函数获取,然后打印一个“Caught SIGALRM”的例子:

3. pcntl_exec ( string $path [, array $args [, array $envs ]] )

在当前的进程空间中执行指定程序,类似于c中的exec族函数。所谓当前空间,即载入指定程序的代码覆盖掉当前进程的空间,执行完该程序进程即结束。

4. pcntl_fork ( void )

为当前进程创建一个子进程,并且先运行父进程,返回的是子进程的PID,肯定大于零。在父进程的代码中可以用 pcntl_wait(&$status)暂停父进程知道他的子进程有返回值。注意:父进程的阻塞同时会阻塞子进程。但是父进程的结束不影响子进程的运行。
父进程运行完了会接着运行子进程,这时子进程会从执行pcntl_fork()的那条语句开始执行(包括此函数),但是此时它返回的是零(代表这是一个子进程)。在子进程的代码块中最好有exit语句,即执行完子进程后立即就结束。否则它会又重头开始执行这个脚本的某些部分。

5. pcntl_wait ( int &$status [, int $options ] )

阻塞当前进程,只到当前进程的一个子进程退出或者收到一个结束当前进程的信号。使用$status返回子进程的状态码,并可以指定第二个参数来说明是否以阻塞状态调用:
阻塞方式调用的,函数返回值为子进程的pid,如果没有子进程返回值为-1;
非阻塞方式调用,函数还可以在有子进程在运行但没有结束的子进程时返回0。

6. pcntl_waitpid ( int $pid , int &$status [, int $options ] )

功能同pcntl_wait,区别为waitpid为等待指定pid的子进程。当pid为-1时pcntl_waitpidpcntl_wait 一样。在pcntl_waitpcntl_waitpid两个函数中的$status中存了子进程的状态信息,这个参数可以用于 pcntl_wifexitedpcntl_wifstoppedpcntl_wifsignaledpcntl_wexitstatuspcntl_wtermsigpcntl_wstopsigpcntl_waitpid这些函数。

7. pcntl_getpriority ([ int $pid [, int $process_identifier ]] )

取得进程的优先级,即nice值,默认为0,在我的测试环境的linux中(CentOS release 5.2 (Final)),优先级为-20到19,-20为优先级最高,19为最低。(手册中为-20到20)。

8. pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] )

设置进程的优先级。

9. posix_kill

可以给进程发送信号

  1. pcntl_singal
    用来设置信号的回调函数

11.posix_setsid
用来脱离执行进程,自己生成管理进程以及处理进程。

PHP 信号处理

PHP5.3.0起支持pcntl_signal系列进程控制函数可以对信号进行安装、分发等操作。

信号处理函数

  • pcntl_signal():安装信号;
  • pcntl_signal_dispatch():分发信号;
  • pcntl_sigwaitinfo():等待信号;

信号类别

  • SIGTERM:信号触发命令:kill pidkill -15 pidkill -SIGTERM等;
  • SIGINT:程序终止(interrupt)信号,通常由ctrl+c触发;
  • SIGKILL:触发命令:kill -9 pid;
  • SIGHUP:挂断信号,通常父进程终止后向子进程组发送该信号;
  • SIGALRM:定时器信号;

简单案例

// 安装信号
echo "开始安装信号...\n";
pcntl_signal(SIGHUP, function($signal) {
  echo "信号被调用!\n";
});
// 发出信号
echo "发出信号...\n";
posix_kill(posix_getpid(), SIGHUP);
// 分发信号
echo "开始分发信号...\n";
pcntl_signal_dispatch();
echo "完成\n";
/*
开始安装信号...
发出信号...
开始分发信号...
信号被调用
完成
*/

复杂点案例

class Listener
{
    public function __construct()
    {
        pcntl_signal(SIGTERM,   array($this, "stop"));
        pcntl_signal(SIGINT,    array($this, "stop"));
        pcntl_signal(SIGHUP,    array($this, "sighup"));
        pcntl_signal(SIGALRM,   array($this, "alarm"), true);
        set_error_handler(array($this, "errorHandler"));
    }
    public function errorHandler($errno, $errstr, $errfile, $errline)
    {
        if (!(error_reporting() & $errno)) {
            // This error code is not included in error_reporting
            return;
        }

        switch ($errno) {
            case E_WARNING:
                throw new \Exception("PHP WARNING: [$errno] $errstr $errfile Line:$errline");
                return true;
            case E_NOTICE:
                throw new \Exception("PHP NOTICE: [$errno] $errstr $errfile Line:$errline");
                return true;
            default:
                break;
        }

        return false;
    }
    abstract function stop($signo);
}

PHP函数file_get_contents()使用 https 协议时报错:SSL operation failed

场景:

file_get_contents() 函数是用于将文件的内容读入到一个字符串中,是读取文件内容常用的函数之一。

但是有时在服务器上使用file_get_contents() 函数请求https 协议的url文件时会报错误,无法正确读取文件内容,

查看log日志,日志内容类似如下:

PHP Warning:  file_get_contents(): Failed to enable crypto in ......
PHP Warning:  file_get_contents......: failedream: operation failed in ......
PHP Warning:  file_get_contents(): SSL operatwith code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verin ......

原因:

服务器未正确配置好https证书

解决方法:(三种解决方法)

方法一:

下载https证书到服务器

服务器 下载这个证书,http://curl.haxx.se/ca/cacert.pem
php.ini 配置

openssl.cafile = "/etc/ssl/certs/cacert.pem"//你实际下载证书的路径

重启 php 即可

方法二:

使用cURL 函数处理 https 的参数,获取文件内容

<?php
function getSSLPage($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSLVERSION,3); 
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

var_dump(getSSLPage("https://xxx.xxx.xxx"));

Xnip2024-02-28_09-10-42.png

https://stackoverflow.com/questions/14078182/openssl-file-get-contents-failed-to-enable-crypto

方法三:

使file_get_contents( 函数跳过https验证

$stream_opts = [
    "ssl" => [
        "verify_peer"=>false,
        "verify_peer_name"=>false,
    ]
]; 

$response = file_get_contents("https://xxx.xxx.xxx",false, stream_context_create($stream_opts));

开发中建议使用cURL 函数替代file_get_contents()函数。

MongoDB 提供哪些管理和监控工具?

MongoDB 提供哪些管理和监控工具?

MongoDB 提供一系列的管理和监控工具,用于简化数据库的运维和性能监控。以下是 MongoDB 的一些主要管理和监控工具:

  1. MongoDB Atlas: MongoDB Atlas 是 MongoDB 提供的云托管服务,它提供了一个易于使用的界面,允许用户在云中轻松部署、管理和监控 MongoDB 集群。MongoDB Atlas 还包括自动缩放、备份和安全性功能。
  2. MongoDB Compass: MongoDB Compass 是一个图形用户界面 (GUI) 工具,用于探索、分析和可视化 MongoDB 数据。它提供了直观的方式来执行查询、理解数据库结构,并支持地理空间数据的可视化。
  3. mongodumpmongorestore: 这两个命令用于备份和恢复 MongoDB 数据库。mongodump 用于创建数据库备份,而 mongorestore 用于将备份文件还原到 MongoDB。
  4. mongoimportmongoexport: 这两个命令用于导入和导出 MongoDB 数据。mongoimport 用于将数据从文件导入到 MongoDB,而 mongoexport 用于将数据导出为 JSON 或 CSV 文件。

5. MongoDB Ops Manager: MongoDB Ops Manager 是一个全面的管理工具,用于监控、备份、自动缩放和安全性管理。Ops Manager 还提供了性能和故障排除工具,用于分析和改进 MongoDB 部署。

  1. mongostatmongotop: mongostat 用于实时监控 MongoDB 实例的性能统计信息,包括连接、查询、更新等活动。mongotop 用于实时监控 MongoDB 实例中的每个集合的读写性能。
  2. MongoDB Cloud Manager: MongoDB Cloud Manager 是 MongoDB 提供的云服务,用于集中管理和监控 MongoDB 部署。它提供实时性能监控、自动化备份和警报功能。
  3. mongodmongos 日志: MongoDB 主要的服务进程 mongod 和路由进程 mongos 生成详细的日志文件,这些日志对于故障排除和性能分析非常有用。
  4. MMS(MongoDB Management Service): MMS 提供了对 MongoDB 部署的监控和管理,包括性能图表、慢查询分析、报警设置等。
  5. MongoDB Shell: MongoDB 提供了交互式的 JavaScript shell,允许用户通过命令行界面执行数据库操作和查询,用于管理和监控数据库。

如何在 MongoDB 中实现身份验证?

如何在 MongoDB 中实现身份验证?

MongoDB 中,可以通过设置身份验证来增加数据库的安全性。MongoDB 提供了多种身份验证方法,包括内置用户角色管理系统LDAPKerberos 等。以下是使用内置用户和角色管理系统进行身份验证的一般步骤:

  1. 启用身份验证: 在 MongoDB 配置文件中启用身份验证。编辑 MongoDB 的配置文件(通常是 mongod.conf),添加以下配置项:

      authorization: enabled

这将启用身份验证机制。

  1. 重启 MongoDB 服务: 在修改配置文件后,重启 MongoDB 服务以使配置生效。
  2. 创建管理员用户: 连接到 MongoDB 服务器,并使用管理员权限创建一个管理员用户。启动 mongo shell 并连接到 MongoDB,然后执行以下命令:

    use admin
    db.createUser({
      user: "adminUser",
      pwd: "adminPassword",
      roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase"]
    })

    这将创建一个名为 adminUser 的管理员用户,并授予管理权限。

  3. 重新连接并使用身份验证: 使用新创建的管理员用户重新连接到 MongoDB,并启用身份验证。

    mongo -u adminUser -p

    在连接时,输入管理员用户的密码。

  4. 创建应用程序用户: 为你的应用程序创建一个专用的数据库和用户。在连接到 MongoDBmongo shell 后,执行以下命令:
use yourDatabase
db.createUser({
  user: "yourAppUser",
  pwd: "yourAppPassword",
  roles: ["readWrite"]
})

这将创建一个名为 yourAppUser 的应用程序用户,并授予读写权限。

  1. 连接并使用应用程序用户: 使用新创建的应用程序用户连接到 MongoDB。

    mongo -u yourAppUser -p --authenticationDatabase yourDatabase

    在连接时,输入应用程序用户的密码。

通过执行上述步骤,你可以成功地在 MongoDB 中启用身份验证,并设置不同权限的用户以用于不同的操作。这提高了
MongoDB 数据库的安全性,确保只有经过身份验证的用户才能访问数据库。

什么是角色和权限?如何配置它们?

MongoDB 中,角色(Roles)和权限(Privileges)是用于管理数据库访问和操作的重要概念。

角色(Roles): 角色是 MongoDB 中定义的一组权限集合。每个角色代表一组特定的数据库权限,可以授予用户或用户组。MongoDB 包含一些内置角色,如读取权限、写入权限、数据库管理员权限等。

权限(Privileges): 权限是指用户或用户组对数据库和集合的操作权限。权限控制了用户对数据库的 CRUD 操作(创建、读取、更新、删除)以及其他操作的能力。

配置角色和权限:

  1. 创建角色: 使用 db.createRole() 命令在 MongoDB 中创建角色。指定角色的名称、角色包含的权限以及其他相关选项。

    
    db.createRole({
      role: "customRole",
      privileges: [
     { resource: { db: "yourDatabase", collection: "" }, actions: ["find", "insert", "update"] }
      ],
      roles: []
    })

    在上面的示例中,创建了一个名为 customRole 的自定义角色,具有对 yourDatabase 数据库的查找、插入和更新操作的权限。

  2. 创建用户并分配角色: 使用 db.createUser() 命令在 MongoDB 中创建用户,并将角色分配给用户。

    
    db.createUser({
      user: "yourUser",
      pwd: "yourPassword",
      roles: ["customRole"]
    })

    在上面的示例中,创建了一个名为 yourUser 的用户,并分配了 customRole 角色。

  3. 内置角色: MongoDB 提供了一些内置的常用角色,例如 readreadWritedbAdminuserAdmin 等。可以通过将这些角色分配给用户来快速配置权限。

    
    db.createUser({
      user: "anotherUser",
      pwd: "anotherPassword",
      roles: ["readWrite", "dbAdmin"]
    })
    
  4. 查看用户及其权限: 使用 db.getUser() 命令查看用户及其分配的角色和权限。

    db.getUser("yourUser")
  5. 更新用户权限: 使用 db.grantRolesToUser()db.revokeRolesFromUser() 命令来更新用户的权限。

    db.grantRolesToUser("yourUser", ["readWrite"])

    上面的命令将向 yourUser 用户授予 readWrite 角色。

通过配置角色和权限,你可以细粒度地控制用户对 MongoDB 数据库的访问和操作。这对于确保安全性和按需授予访问权限非常有用。

">