RabbitMQ+PHP 教程二(Work Queues)

https://segmentfault.com/a/1190000011829380

CentOS7上安装RabbitMQ

https://www.jianshu.com/p/ce725e41edab

开启允许远程访问(非必须)

vim /etc/rabbitmq/rabbitmq.config

[{rabbit,[{loopback_users,[]}]}].

sudo rabbitmq-plugins enable rabbitmq_management

安装消息延迟插件

cd rabbitmq_server-3.6.6/plugins/

wget https://dl.bintray.com/rabbitmq/community-plugins/rabbitmq_delayed_message_exchange-0.0.1.ez

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

放行端口

firewall-cmd –add-port=15672/tcp –permanent

irewall-cmd –add-port=5672/tcp –permanent

环境版本不一致各种报错

 

centos 网卡设置

cd /etc/sysconfig/network-scripts/

vi ifcfg-eno16777736。进行修改网卡文件,不同机器网卡不同

我们需要首先找到ONBOOT=no ,需要修改为ONBOOT=yes然后保存退出。

然后执行命令 service network restart 重启网卡服务

https://segmentfault.com/a/1190000010693696

环境

  • VMware版本号:12.0.0
  • CentOS版本:CentOS 7.3.1611

注意事项

关闭防火墙

centos 6.x 关闭 iptables

$ service iptables stop # 关闭命令:

centos 7.x 关闭firewall

$ systemctl stop firewalld.service # 停止firewall

不想关闭防火墙,就开放15672端口,设置之后可以通过网页方式管理MQ

安装安装iptables防火墙

yum install iptables-services

编辑配置

$ vi /etc/sysconfig/iptables-config

添加配置

iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
iptables -I INPUT -p tcp --dport 15672 -j ACCEPT

保存配置

$ service iptables save

重启

systemctl restart iptables.service

设置开机自启动

systemctl enable iptables.service

CentOS7.3 安装 iptables 与详细使用

安装

安装 Erlang

RabbitMQ 安装需要依赖 Erlang 环境

$ cd /opt
$ wget http://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpm

$ yum install erlang-19.0.4-1.el7.centos.x86_64.rpm

安装 RabbitMQ

$ cd /opt
$ wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/rabbitmq-server-3.6.10-1.el7.noarch.rpm
$ yum install rabbitmq-server-3.6.10-1.el7.noarch.rpm

启动服务

$ service rabbitmq-server start

服务状态

$ service rabbitmq-server status
# service rabbitmq-server status
Redirecting to /bin/systemctl status  rabbitmq-server.service
 rabbitmq-server.service - RabbitMQ broker
   Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2017-08-16 11:43:33 CST; 8s ago
 Main PID: 17919 (beam)
   Status: "Initialized"
   CGroup: /system.slice/rabbitmq-server.service
           ├─17919 /usr/lib64/erlang/erts-8.0.3/bin/beam -W w -A 64 -P 1048576 -t 5000000 -stbt db -zdbbl 32000 -K true -- -root /usr/lib64/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /us...
           ├─18062 /usr/lib64/erlang/erts-8.0.3/bin/epmd -daemon
           ├─18160 erl_child_setup 1024
           ├─18165 inet_gethost 4
           └─18166 inet_gethost 4

Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: RabbitMQ 3.6.10. Copyright (C) 2007-2017 Pivotal Software, Inc.
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##  ##
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##########  Logs: /var/log/rabbitmq/rabbit@localhost.log
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ######  ##        /var/log/rabbitmq/rabbit@localhost-sasl.log
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##########
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: Starting broker...
Aug 16 11:43:33 localhost.localdomain rabbitmq-server[17919]: systemd unit for activation check: "rabbitmq-server.service"
Aug 16 11:43:33 localhost.localdomain systemd[1]: Started RabbitMQ broker.
Aug 16 11:43:33 localhost.localdomain rabbitmq-server[17919]: completed with 0 plugins.

查看日志

$ less /var/log/rabbitmq/rabbit@localhost.log
=INFO REPORT==== 16-Aug-2017::11:43:32 ===
Starting RabbitMQ 3.6.10 on Erlang 19.0.4
Copyright (C) 2007-2017 Pivotal Software, Inc.
Licensed under the MPL.  See http://www.rabbitmq.com/

=INFO REPORT==== 16-Aug-2017::11:43:32 ===
node           : rabbit@localhost
home dir       : /var/lib/rabbitmq
config file(s) : /etc/rabbitmq/rabbitmq.config (not found)
cookie hash    : kuUba2xGLitNNO48qE0Hrg==
log            : /var/log/rabbitmq/rabbit@localhost.log
sasl log       : /var/log/rabbitmq/rabbit@localhost-sasl.log
database dir   : /var/lib/rabbitmq/mnesia/rabbit@localhost

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Memory limit set to 390MB of 976MB total.

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Enabling free disk space monitoring

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Disk free limit set to 50MB

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Limiting to approx 924 file handles (829 sockets)

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
FHC read buffering:  OFF
FHC write buffering: ON

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Database directory at /var/lib/rabbitmq/mnesia/rabbit@localhost is empty. Initialising from scratch...

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Waiting for Mnesia tables for 30000 ms, 9 retries left

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Waiting for Mnesia tables for 30000 ms, 9 retries left

这里显示的是没有找到配置文件,我们可以自己创建这个文件

config file(s) : /etc/rabbitmq/rabbitmq.config (not found)

创建rabbitmq.config

$ cd /etc/rabbitmq/
$ vi rabbitmq.config

编辑内容如下:

[{rabbit, [{loopback_users, []}]}].
  • 这里的意思是开放使用,rabbitmq默认创建的用户guest,密码也是guest,这个用户默认只能是本机访问,localhost或者127.0.0.1,从外部访问需要添加上面的配置。

保存配置后重启服务

$ service rabbitmq-server restart

开启管理UI

$ /sbin/rabbitmq-plugins enable rabbitmq_management

重启服务

$ service rabbitmq-server restart

访问管理UI

通过 http://ip:15672 使用guest,guest 进行登陆了

如果不能访问,请检查防火墙
图片描述

授权操作

添加用户

处于安全的考虑,guest这个默认的用户只能通过http://localhost:15672 来登录,其他的IP无法直接使用这个账号。 这对于服务器上没有安装桌面的情况是无法管理维护的,除非通过在前面添加一层代理向外提供服务,这个又有些麻烦了,这里通过配置文件来实现这个功能

命令格式

rabbitmqctl add_user <username> <newpassword>
$ rabbitmqctl add_user ymq 123456
Creating user "ymq"

删除用户

命令格式

rabbitmqctl delete_user <username>
$ rabbitmqctl  delete_user penglei
Deleting user "penglei"

修改密码

命令格式

rabbitmqctl change_password <username> <newpassword>
$ rabbitmqctl  change_password  ymq 123456
Changing password for user "ymq"

用户授权

命令格式

rabbitmqctl set_permissions [-pvhostpath] {user} {conf} {write} {read}

该命令使用户ymq /(可以访问虚拟主机) 中所有资源的配置、写、读权限以便管理其中的资源

$ rabbitmqctl set_permissions -p "/" ymq ".*" ".*" ".*"
Setting permissions for user "ymq" in vhost "/"

查看用户授权

命令格式

rabbitmqctl list_permissions [-p VHostPath]
$ rabbitmqctl list_permissions -p /
Listing permissions in vhost "/"
guest    .*    .*    .*
ymq    .*    .*    .*

查看当前用户列表

可以看到添加用户成功了,但不是administrator角色

$ rabbitmqctl list_users
Listing users
guest    [administrator]
ymq    []

添加角色

这里我们也将ymq用户设置为administrator角色

命令格式

rabbitmqctl set_user_tags <username> <tag>
$ rabbitmqctl set_user_tags ymq administrator
Setting tags for user "ymq" to [administrator]

再次查看权限

$ rabbitmqctl list_users
Listing users
guest    [administrator]
ymq    [administrator]

清除权限信息

命令格式

rabbitmqctl clear_permissions [-p VHostPath] ymq
rabbitmqctl  clear_permissions  -p /  ymq
Clearing permissions for user "ymq" in vhost "/"

官方文档

后台操作

登录新用户

可以看到 ymq 和 guest 的权限 一样
图片描述

添加用户

鼠标点击,划红线的角色,选择一种
图片描述

设置权限

该用户无权访问任何虚拟主机
图片描述

点击 Set permission

  • 设置可以访问虚拟主机 中所有资源的配置、写、读权限以便管理其中的资源

图片描述

推荐阅读

CentOs7.3 搭建 RabbitMQ 3.6 Cluster 集群服务

Contact

  • 作者:鹏磊
  • 出处:http://www.ymq.io
  • Email:admin@souyunku.com
  • 版权归作者所有,转载请注明出处
  • Wechat:关注公众号,搜云库,专注于开发技术的研究与知识分享

用php-x写php扩展

https://yuerblog.cc/wp-content/uploads/%E9%9F%A9%E5%A4%A9%E5%B3%B0%E2%80%94%E2%80%94%E4%BD%BF%E7%94%A8C++%E5%BC%80%E5%8F%91PHP7%E6%89%A9%E5%B1%95.pdf

Zookeeper学习系列【一】 教会你Zookeeper的一些基础概念

https://segmentfault.com/a/1190000018927058

https://wiki.swoole.com/wiki/page/972.html

如何基于 PHP-X 快速开发一个 PHP 扩展

https://segmentfault.com/a/1190000011111074?utm_source=coffeephp.com

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。

GitHub中PR(pull Request)操作

GitHub中PR(pull Request)操作
GitHub已经成为所有程序员的天堂和地狱。
众多程序员在此网站上活跃,想为开源贡献代码,就必须要学会提交PR。PR即是Pull Request操作
本人gitHub地址: https://github.com/thinkingfioa
1. 贡献代码
贡献代码,通俗的说,就是自己修改了代码,希望合并到别人的Repository(仓库)中。将自己的智慧贡献给开源社区。下面将详细讲解步骤

1.1 第一步:fork
在GitHub社区闲逛时,看中了某个项目代码,如:spring-projects/spring-framework,点击页面Fork按钮,会生成一个自己的Repository(仓库:thinkingfioa/spring-framework),如下图:

 

1.2 第二步:修改
fork成功后,通过git clone、修改、commit、push等操作后,将修改的内容,提交到自己仓库(thinkingfioa/spring-framework)中。如果对git clone、commit和push不知道的,自行百度。如下图:

 

1.3 第三步:请求合并代码(Pull Request)
在1.2步骤时,我们修改了自己的仓库(thinkingfioa/spring-framework)代码。我们希望贡献自己的一份力量,将修改的Commit也提交到别人的仓库(spring-projects/spring-framework)中。则要进行Pull Request。

1.3.1 创建PR

 

1.3.2 Create pull request
请特别注意下图中标红的部分,不能搞反了。点击: Create pull request 绿色按钮,完成提交PR。

 

1.3.3 等待
提交PR完成后,等待对方仓库(spring-projects/spring-framework)的管理员审核,如果他同意,则贡献代码完成了。

2. 同步最新代码
PR除了贡献代码外,还可以同步对方最新代码。通俗的说,fork某个仓库(如: spring-projects/spring-framework)代码一段时间后,为了同步自己仓库(thinkingfioa/spring-framework)和对方仓库(spring-projects/spring-framework)代码,保证自己仓库代码是最新版本。

2.1 同步最新代码
2.1.1 Create pull request
这一步和上面1.3.2一样的,只是要注意箭头,哪个仓库合并哪个仓库。请自习注意下图标红部分

 

2.1.2 点击绿色按钮,完成代码同步

———————
作者:thinking_fioa
来源:CSDN
原文:https://blog.csdn.net/thinking_fioa/article/details/79516352
版权声明:本文为博主原创文章,转载请附上博文链接!

php pcntl多进程

需要安装PHP扩展 pcntl posix

<?php
/**
 * Created by PhpStorm.
 * User: zhangheg
 * Date: 2019/4/14
 * Time: 18:06
 */
$a = 1;

$ppid = posix_getpid();//获取当前的进程号
echo $ppid.PHP_EOL;
//创建多个进程
for($i=0;$i<2;$i++){
    $pid = pcntl_fork(); //创建成功返回子进程ID
    if($pid<0){
        //父进程空间
        exit('创建失败了');
    }else if($pid>0){
        //父进程空间返回子进程ID
        $a = 2;

        $status = 0;//等待回收僵尸进程
        $pid = pcntl_wait($status); //结束的子进程信息,阻塞状态
        echo "字进程回收了id:$pid".PHP_EOL;
    }else{
        //返回为0子进程空间
        //子进程创建成功
        sleep(10);

    }
}

PHP 模拟开发 单进程阻塞网络服务器 -理解swoole实现

1 单进程阻塞网络服务器

一个连接-请求-阻塞-返回数据

原理 :创建-绑定-监听-接收请求-回复-逻辑处理-关闭

说明:

1、创建一个socket,绑定服务器端口(bind),监听端口(listen),在PHP中用stream_socket_server一个函数就能完成上面3个步骤

2、进入while循环,阻塞在accept操作上,等待客户端连接进入。此时程序会进入睡眠状态,直到有新的客户端发起connect到服务器,操作系统会唤醒此进程。accept函数返回客户端连接的socket

3、利用fread读取客户端socket当中的数据收到数据后服务器程序进行处理然后使用fwrite向客户端发送响应。长连接的服务会持续与客户端交互,而短连接服务一般收到响应就会close。

缺点:

1、一次只能处理一个连接,不支持多个连接同时处理

 

每个连接进入到我们的服务端的时候,单独创建一个进程/线程提供服务

<?php
//多个客户端发起请求,观察服务端状态
//ab -n 请求数 -c 并发数 -k 保持连接
 class Worker{
     //监听socket
     protected $socket = NULL;
     //连接事件回调
     public $onConnect = NULL;
     //接收消息事件回调
     public $onMessage = NULL;
     public function __construct($socket_address) {
        //监听地址+端口 相当于socket 绑定监听
         $this->socket = stream_socket_server($socket_address);
     }

     public function start() {
        while (true){

         $clientSocket = stream_socket_accept($this->socket); //阻塞监听

         if(!empty($clientSocket) && is_callable($this->onConnect)){
             //有客户端进来
             call_user_func($this->onConnect,$clientSocket); //连接建立成功触发
         }
         //从连接当中读取客户端内容
         $buffer = fread($clientSocket,65535); //缓冲区
         //正常读取到数据,触发消息接收事件,响应内容
         if(!empty($buffer) && is_callable($this->onRecive)){
             call_user_func($this->onRecive,$clientSocket,$buffer);
         }
        fclose($clientSocket);
        }

     }
 }



$worker = new Worker('tcp://0.0.0.0:9812');

 //事件
$worker->onConnect = function ($fd) {
        echo '连接事件触发'.(int)$fd.PHP_EOL;
};
$worker->onRecive = function ($conn, $message) {
    //事件回调当中写业务逻辑
    var_dump($conn,$message);
    //http 响应头
    $content = '响应http了';
    $http_resonse = "HTTP/1.1 200 OK\r\n";
    $http_resonse .= "Content-Type: text/html;charset=UTF-8\r\n";
    $http_resonse .= "Connection: keep-alive\r\n"; //连接保持
    $http_resonse .= "Server: php socket server\r\n";
    $http_resonse .= "Content-length: ".strlen($content)."\r\n\r\n";
    $http_resonse .= $content;
    fwrite($conn, $http_resonse);

};

$worker->start();


linux go 环境

1、下载地址(自备梯子):https://golang.org/dl/

2、解压 到指定目录 tar -C /usr/local -zxf go1.12.1.linux-amd64.tar.gz

3、声明 root 用户登录。
$ vim /etc/profile
打开/etc/profile后//最后一行插入
export GOROOT=/usr/local/go //这里我的go解压后是在/user/local/go
export GOPATH=~/golib:~/goproject
export GOBIN=~/gobin
export PATH=$PATH:$GOROOT/bin:$GOBIN

/然后 按ESC键 跳到命令模式,然后保存退出
:wq //再按确认键盘
//输入下面才会命令生效
$ source /etc/profile //ok

4、go version

go version go1.12.1 linux/amd64

 

 

 

讲解C栈和PHP递归调用push和pop stack的过程。

https://biglive.xueersi.com/LivePlayBack/index/2-2480-93250

讲解C栈和PHP递归调用push和pop stack的过程。

这个视频内容可以和 Swoole4 协程结合着看。很透彻地把 Swoole4 的实现原理讲明白了。普通的 PHP 程序就是一个 C栈、一个 PHP的栈。而 Swoole4 的协程,变成多个 C栈和PHP栈,可以在不同的栈之间切换,这就是协程的本质。然后底层又使用 Epoll 去做事件驱动,去实现协程调度。

线程、进程结构

[root@localhost ~]# pstree -ap | grep server.php
|-php,7900 server.php
| |-php,7901 server.php
| | `-php,7903 server.php
| | |-grep,8558 –color=auto server.php
| `-php,8548 server.php
| |-php,8549 server.php
| | `-php,8551 server.php

http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

进程与线程的一个简单解释

三、进程线程的区别

3.1进程

1、进程之间不共享任何状态

2、进程的调度由操作系统完成

3、每个进程都有自己独立的内存空间

4、进程间通讯主要是通过信号传递的方式来实现的,实现方式有多种,信号量、管道、事件等,任何一种方式的通讯效率都需要过内核,导致通讯效率比较低

5、由于是独立的内存空间,上下文切换的时候需要保存先调用栈的信息、cpu各寄存器的信息、虚拟内存、以及打开的相关句柄等信息,所以导致上下文进程间切换开销很大,通讯麻烦。

3.2线程

1、线程之间共享变量,解决了通讯麻烦的问题对于变量的访问需要锁

2、一个进程可以拥有多个线程,但是其中每个线程会共享父进程像操作系统申请资源,这个包括虚拟内存、文件等,由于是共享资源,所以创建线程所需要的系统资源占用比进程小很多,相应的可创建的线程数量也变得相对多很多。

3、另外在调度方面也是由于内存是共享的,所以上下文切换的时候需要保存的东西就像对少一些,这样一来上下文的切换也变得高效。