Nginx搭建负载均衡

Nginx负载均衡的分发方式有4种: 1.轮询,默认采取此方式,Nginx会按照请求时间的先后顺序进行轮询分发,若某台Web Server宕机,Nginx自动将其摘掉。 2.weight,权重,即轮询的几率,默认为1,值越大,被分发的可能性越大,用于后端服务器性能不均的情况。 3.ip_hash,每个请求按访问ip的hash结果分配(注意一定要Nginx当做前端而且后端IP固定,不然没法确保一个ip请求落到同样的web机器) PS:一般解决Session都是用的memcache共享 4.自定义规则
upstream test.phpfs.com {
	#ip_hash;
	server 10.200.11.213:8081 down;  
	server 10.200.11.213:8082 weight=5;  
	server 10.200.11.215:8082 weight=5;
	server 10.200.11.215:8081;	 
	server 10.200.11.215:80 backup;  
}
说明:test.phpfs.com只是为了起一个名字 down 表示当前的Web Server暂时不参与负载 weight 默认为1.weight越大,负载的权重就越大。 backup:其它所有的非backup Server down或者忙的时候,请求backup机器。所以这台机器压力会最轻。 场景 机器A:10.200.11.215 机器B:10.200.11.213 A开启80,8081,8082提供web服务,模拟三台Web服务器 B开启80作为分发机,8081,8082作为另外两台Web服务器 这样的相当于后端有5台机器提供web服务! A机器80站点根目录/home/80(备用机,暂时不提供服务) A机器8081站点根目录/home/8081(权重是1) A机器8082站点根目录/home/8082(权重是5) B机器8081站点根目录/home/8081(不提供服务) B机器8082站点根目录/home/8082(权重是5) PHP-FPM监听/var/run/php5-fpm.sock 配置10.200.11.213机器 /etc/nginx/conf.d/ 80.conf	存放存放负载配置 配置如下:
#upstream
upstream test {
	#ip_hash;
    	server 10.200.11.213:8081 down;
    	server 10.200.11.213:8082 weight=5;
    	server 10.200.11.215:8082 weight=5;
	server 10.200.11.215:8081;
    	server 10.200.11.215:80 backup;
}

server {
	listen 80;
	location / {
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_buffering off;#disabled cache
	proxy_pass http://test;
	}
}
8081.conf 存放8081端口网站
server {
	listen 8081;
	root /home/8081;
	index index.php index.html index.htm;
	server_name test.phpfs.com;
	location / {
		try_files $uri $uri/ =404;
	}
	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
	}

}
8082.conf 存放8082端口网站
server {
	listen 8082;
	root /home/8082;
	index index.php index.html index.htm;
	server_name test.phpfs.com;
	location / {
		try_files $uri $uri/ =404;
	}
	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
	}

}
配置10.200.11.215机器 /etc/nginx/conf.d/	80.conf	存放80端口网站
server {
	listen 80;
	root /home/80;
	index index.php index.html index.htm;
	server_name test.phpfs.com;
	location / {
		try_files $uri $uri/ =404;
	}
	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
	}

}
8081.conf 存放8081端口网站
server {
	listen 8081;
	root /home/8081;
	index index.php index.html index.htm;
	server_name test.phpfs.com;
	location / {
		try_files $uri $uri/ =404;
	}
	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
	}

}
8082.conf 存放8082端口网站
server {
	listen 8082;
	root /home/8082;
	index index.php index.html index.htm;
	server_name test.phpfs.com;
	location / {
		try_files $uri $uri/ =404;
	}
	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
	}

}
测试域名:test.phpfs.com 绑定host:10.200.11.213	test.phpfs.com
 
									
				

	

Discuz用户登录身份标识authcode函数

php 
/**
 * $string 明文或密文
 * $operation 加密ENCODE或解密DECODE
 * $key 密钥
 * $expiry 密钥有效期
 */ 
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
    // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
    // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
    // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
    // 当此值为 0 时,则不产生随机密钥
    $ckey_length = 4;
    // 密匙
    // $GLOBALS['discuz_auth_key'] 这里可以根据自己的需要修改
    $key = md5($key ? $key : $GLOBALS['discuz_auth_key']); 
 
    // 密匙a会参与加解密
    $keya = md5(substr($key, 0, 16));
    // 密匙b会用来做数据完整性验证
    $keyb = md5(substr($key, 16, 16));
    // 密匙c用于变化生成的密文
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
    // 参与运算的密匙
    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性
    // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    // 产生密匙簿
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上并不会增加密文的强度
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    // 核心加解密部分
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        // 从密匙簿得出密匙进行异或,再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    if($operation == 'DECODE') {
        // substr($result, 0, 10) == 0 验证数据有效性
        // substr($result, 0, 10) - time() > 0 验证数据有效性
        // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
        // 验证数据有效性,请看未加密明文的格式
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
        // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码
        return $keyc.str_replace('=', '', base64_encode($result));
    }
}


$a = "blog.phpfs.com/login.php?a=abc&b=123";
$b = authcode($a, "ENCODE", "123456");
echo '加密之后:'. $b."
"; echo '解密之后:'.authcode($b, "DECODE", "123456"); ?>

 
使用场景:API接口加密以及身份标识有效期等!

基数排序

基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法

方法:最高位优先MSD、最低位优先LSD

思想:最低位优先LSD方案

1、  将待排数字根据个位上的数字进行排序

2、  将待第一步排序结果再按照十位上数字进行排序

3、  按照位数从低到高依次排序

示例:

 

$arr = array(1,4,5,89,22,44,5,33,6,7,82,332);
function getIndex($num, $index) {
    $val = pow(10, $index - 1);
    return ($num / $val) % 10;
}
function radix_sort($arr,$max_len) {
    for($i = 1; $i <= $max_len; $i++) {
        $temp = array_fill(0, 10, array());//填充桶
        foreach ($arr as $v) {
            echo $index = getIndex($v, $i);
            echo '#';
            $temp[$index][] = $v;
        }
        $arr = array();
        echo "\n第".$i. '次排序之后:';
        foreach ($temp as $v) {
            for($j =0 ;$j < count($v); $j++) {
                echo $v[$j] ."," ;
                $arr[] = $v[$j];
            }
        }
        echo "\n";
    }
    return $arr;
}
$arr = radix_sort($arr, 3);
print_r($arr);

 

以上示例有一个问题,如果排序的数字是负数呢?

$arr = array(1,4,5,89,22,44,-5,33,-6,7,-82,332);
function getIndex($num, $index) {
    $val = pow(10, $index - 1);
    return 10+($num / $val) % 10;
}
function radix_sort($arr,$max_len) {
    for($i = 1; $i <= $max_len; $i++) {
        $temp = array_fill(0, 19, array());//填充桶,负数填充-9~0~9对应0~10~19
        foreach ($arr as $v) {
            echo $index = getIndex($v, $i);
            echo '#';
            $temp[$index][] = $v;
        }
        $arr = array();
        echo "\n第".$i. '次排序之后:';
        foreach ($temp as $v) {
            for($j =0 ;$j < count($v); $j++) {
                echo $v[$j] ."," ;
                $arr[] = $v[$j];
            }
        }
        echo "\n";
    }
    return $arr;
}
$arr = radix_sort($arr, 3);
print_r($arr);

 

JS闭包

闭包定义
闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。就是在另一个作用域中保存了一份它从上一级函数或者作用域得到的变量,而这些变量是不会随上一级函数的执行完成而销毁。
前提条件
计算机中的内存变量如果有被引用着的话,则系统是不会将之回收的。只要我们能够一直持有这个引用,则就可以令局部变量避免被回收——这是闭包概念成立的前提
闭包用途
可以读取到函数内部的变量
可以让函数内部变量保持在内存中
避免全局变量的污染
私有成员的存在
注意事项
闭包会让函数中的变量都被保存到内存中,内存消耗较大,不能滥用闭包,否则会导致性能和内存泄漏问题(退出函数之前可以将不用的局部变量全部删除)
闭包能改变父函内部变量的值,一定要小心使用
示例

for(var i = 0; i < 10; i++) {
	setTimeout(function() {
     console.log(i);  
 }, 100);
}
输出10次10
for(var i = 0; i < 10; i++) {
 	(function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 100);
    })(i);
}
输出0-9


 
参考:http://www.2cto.com/kf/201410/342609.html

导出CSV格式

/**
 * 导出数据格式为csv
 */
function export_to_csv($data = array(), $title = array(), $filename=null) {
    if(empty($filename)) {
        $filename = date('Ymd');
    }
    header("Content-type:text/csv"); 
    header("Accept-Ranges:bytes");
    header("Content-type:application/vnd.ms-excel");
    header("Content-Disposition:attachment;filename=".$filename.".xls");
    header("Pragma: no-cache");
    header("Expires: 0");
    //导出xls 开始
    if (!empty($title)){
        foreach ($title as $k => $v) {
            $title[$k]=iconv("UTF-8", "GB2312",$v);
        }
        $title= implode("\t", $title);
        echo "$title\n";
    }
    if (!empty($data)){
        foreach($data as $key=>$val){
            foreach ($val as $ck => $cv) {
                $data[$key][$ck]='="'.iconv("UTF-8", "GB2312", $cv).'"';
            }
            $data[$key]=implode("\t", $data[$key]);
    
        }
        echo implode("\n",$data);
    }
}

 

Nginx搭建Https服务器

mkdir -p /etc/nginx/ssl
生成私钥
openssl genrsa -des3 -out server.key 1024
提示输入密码和确认密码
生成证书
openssl req -new -key server.key -out server.csr
提示输入密码,国家,省份,城市,组织等信息
生成无密码私钥
openssl rsa -in server.key -out public.key
颁发证书
openssl x509 -req -days 365 -in server.csr -signkey public.key -out server.crt
配置nginx站点

server {
    listen 443;
    ssl on;
    ssl_certificate  /etc/nginx/ssl/server.crt;
    ssl_certificate_key  /etc/nginx/ssl/public.key;
    server_name test.phpfs.com;
    root /data/html/test.phpfs.com/;
    location / {
       autoindex on;
    }
}

配置apache站点
提示:Invalid command ‘SSLEngine’, perhaps misspelled or defined by a module not included in the server configuration
Action ‘configtest’ failed.
需要启用sudo a2enmod ssl


	ServerName test.phpfs.com
	DocumentRoot /var/www/html/test
	SSLEngine on
    SSLCertificateFile /etc/nginx/ssl/server.crt
    SSLCertificateKeyFile /etc/nginx/ssl/public.key



nginx-https-1

Strace命令手册

strace简介
strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。
strace参数
-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]…
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\\.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-e abbrev=set
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
-e raw=set
将指 定的系统调用的参数以十六进制显示.
-e signal=set
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
-e read=set
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据.
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username 的UID和GID执行被跟踪的命令
用途
1、查找程序读取的配置文件(strace php 2>&1 |grep php.ini)
2、跟踪指定系统调用(strace -a open php)
3、跟踪进程(strace -p 1008)
4、系统调用概要,执行时间,错误等信息(strace -c php)
案例:
1、保存输出结构strace -o test.log -p 1008

 

WorkMan手册笔记-定时器类

一、定时执行某个函数或者类方法

int \Workerman\Lib\Timer::add(float $time_interval, callable $callback [,$args = array(), bool $persistent = true])

参数

time_interval

多长时间执行一次,单位秒,支持小数,可以精确到0.001,即精确到毫秒级别。

callback

回调函数注意:如果回调函数是类的方法,则方法必须是public属性

args

回调函数的参数,必须为数组,数组元素为参数值

persistent

是否是持久的,如果只想定时执行一次,则传递false(只执行一次的任务在执行完毕后会自动销毁,不必调用Timer::del())。默认是true,即一直定时执行。

返回值

返回一个整数,代表计时器的timerid,可以通过调用Timer::del($timerid)销毁这个计时器。

二、删除定时器

参数

timer_id

定时器的id,即add接口返回的整型

返回值

Boolean

三、注意事项

1、只能在onXXXX回调中添加定时器。全局的定时器推荐在onWorkerStart回调中设置,针对某个连接的定时器推荐在onConnect中设置。

2、添加的定时任务在当前进程执行,如果任务很重(特别是涉及到网络IO的任务),可能会导致该进程阻塞,暂时无法处理其它业务。所以最好将耗时的任务放到单独的进程运行,例如建立一个/多个Worker进程运行

3、当一个任务没有在预期的时间运行完,这时又到了下一个运行周期,则会等待当前任务完成才会运行。也就是说当前进程的任务都是串行执行的,如果是多进程则进程间的任务运行是并行的。

4、需要注意多进程设置了定时任务造成并发问题。

5、可能会有1毫秒左右的误差。

WorkerMan手册笔记二-TcpConnection类说明

一、介绍

每个客户端连接对应一个Connection对象,可以设置对象的onMessage、onClose等回调,同时提供了向客户端发送数据send接口与关闭连接close接口,以及其它一些必要的接口。

可以说Worker是一个监听容器,负责接受客户端连接,并把连接包装成connection对象式提供给开发者操作。

二、属性

名称

说明

int Connection::$id

连接的id。这是一个自增的整数。

注意:workerman是多进程的,每个进程内部会维护一个自增的connection id,所以多个进程之间的connecion id会有重复。 如果想要不重复的connection id 可以根据需要给connection->id重新赋值,例如加上worker->id前缀。

string Connection::$protocol

设置当前连接的协议类

Worker Connection::$worker

此属性为只读属性,即当前connection对象所属的worker实例

int Connection::$maxSendBufferSize

此属性用来设置当前连接的应用层发送缓冲区大小。不设置默认为Connection::$defaultMaxSendBufferSize(1MB)。Connection::$maxSendBufferSize 和 Connection::$defaultMaxSendBufferSize均可以动态设置。

此属性影响onBufferFull回调

static int Connection::$defaultMaxSendBufferSize

此属性为全局静态属性,用来设置所有连接的默认应用层发送缓冲区大小。不设置默认为1MB。 Connection::$defaultMaxSendBufferSize可以动态设置,设置后只对之后产生的新连接有效

static int Connection::$maxPackageSize

此属性为全局静态属性,用来设置每个连接能够接收的最大包包长。不设置默认为10MB。

三、回调属性

名称

说明

callback Connection::$onMessage

作用与Worker::$onMessage回调相同,区别是只针对当前连接有效,也就是可以针对某个连接的设置onMessage回调。

callback Connection::$onClose

此回调与Worker::$onClose回调作用相同,区别是只针对当前连接有效,也就是可以针对某个连接的设置onClose回调

callback Connection::$onBufferFull

作用与Worker::$onBufferFull回调相同,区别是只针对当前连接起作用,即可以单独设置某个连接的onBufferFull回调

callback Connection::$onBufferDrain

作用与Worker::$onBufferDrain回调相同,区别是只针对当前连接起作用,即可以单独设置某个连接的onBufferDrain回调

callback Connection::$onError

作用与Worker::$onError回调相同,区别是只针对当前连接起作用,即可以单独设置某个连接的onError回调

四、接口

名称

参数

返回值

说明

mixed Connection::send(mixed $data [,$raw = false])

$data 要发的数据

$row 是否发原始数据

true 表示发送成功

null 表示放入待发送队列,等待异步发送

false 表示发送失败,失败原因可能是客户端连接已经关闭,或者该连接的应用层发送缓冲区已满

向客户端发送数据

string Connection::getRemoteIp()

String

获得该连接的客户端ip

int Connection::getRemotePort()

获得该连接的客户端端口

void Connection::close(mixed $data = ”)

$data   可选参数,要发送的数据(如果有指定协议,则会自动调用协议的encode方法打包$data数据),当数据发送完毕后关闭连接,随后会触发onClose回调

调用close会等待发送缓冲区的数据发送完毕后才关闭连接,并触发连接的onClose回调

void Connection::destroy()

与close不同之处是,调用destroy后即使该连接的发送缓冲区还有数据未发送到对端,连接也会立刻被关闭,并立刻触发该连接的onClose回调。

void Connection::pauseRecv(void)

使当前连接停止接收数据。该连接的onMessage回调将不会被触发。此方法对于上传流量控制非常有用

void Connection::resumeRecv(void)

使当前连接继续接收数据。此方法与Connection::pauseRecv配合使用,对于上传流量控制非常有用

void Connection::pipe(TcpConnection $target_connection)

将当前连接的数据流导入到目标连接。内置了流量控制。此方法做TCP代理非常有用

Workman手册笔记一

安装workerman参考:http://www.workerman.net/install

下载workerman扩展包git clone https://github.com/walkor/Workerman

手册参考:http://doc3.workerman.net/

一、WorkerMan代码规范

1、  类采用首字母大写的驼峰式命名,类文件名称必须与文件内部类名相同,以便自动加载。

2、  使用命名空间,命名空间名字与目录路径对应,并以开发者的项目根目录为基准

3、  普通函数及变量名采用小写加下划线方式

4、  类成员及类的方法采用首字母小写的驼峰形式

5、  函数及类的参数采用小写加下划线方式

二、Worker类属性说明

名称 类型 说明
$id Int 当前worker进程的id编号,范围为0到$worker->count-1
$count Int 设置当前Worker实例启动多少个进程,不设置时默认为1
$name String 设置当前Worker实例的名称,方便运行status命令时识别进程。不设置时默认为none
$user String 设置当前Worker实例以哪个用户运行。此属性只有当前用户为root时才能生效。不设置时默认以当前用户运行
$reloadable Bool 设置当前Worker实例是否可以reload,即收到reload信号后是否退出重启。不设置默认为true,收到reload信号后自动重启进程
$transport String 设置当前Worker实例所使用的传输层协议,目前只支持两种,tcp和udp。不设置默认为tcp
$connections Array 此属性中存储了当前进程的所有的客户端连接
$daemonize Static Bool 此属性为全局静态属性,表示是否以daemon(守护进程)方式运行。如果启动命令使用了 -d参数,则该属性会自动设置为true。也可以代码中手动设置
$stdoutFile Static String 此属性为全局静态属性,如果以守护进程方式(-d启动)运行,则所有向终端的输出(echo var_dump等)都会被重定向到stdoutFile指定的文件中。

 

如果不设置,并且是以守护进程方式运行,则所有终端输出全部重定向到/dev/null

$pidFile Static String 如果无特殊需要,建议不要设置此属性

 

此属性为全局静态属性,用来设置WorkerMan进程的pid文件路径。

 

此项设置在监控中比较有用,例如将WorkerMan的pid文件放入固定的目录中,可以方便一些监控软件读取pid文件,从而监控WorkerMan进程状态。

 

$logFile Static String

 

用来指定workerman日志文件位置。

此文件记录了workerman自身相关的日志,包括启动、停止等。

如果没有设置,文件名默认为workerman.log,文件位置位于Workerman的上一级目录中。

备注:只记录workman自身相关日志

$globalEvent Static Event 此属性为全局静态属性,为全局的eventloop实例,可以向其注册文件描述符的读写事件或者信号事件
$reusePort Bool 设置当前worker是否开启监听端口复用(socket的SO_REUSEPORT选项),默认为false,不开启。

 

开启监听端口复用后允许多个无亲缘关系的进程监听相同的端口,并且由系统内核做负载均衡,决定将socket连接交给哪个进程处理,避免了惊群效应,可以提升多进程短连接应用的性能。

 

注意:此特性需要PHP版本>=7.0

$protocol String 设置当前Worker实例的协议类。

 

注:协议处理类可以直接在初始化Worker在监听参数时直接指定

 

三、回调属性

名称 参数 说明
callback Worker::$onWorkerStart $worker 设置Worker启动时的回调函数,即当Worker启动后立即执行Worker::onWorkerStart成员指定的回调函数

callback Worker::$onWorkerReload

$worker 设置Worker收到reload信号后执行的回调。

 

可以利用onWorkerReload回调做很多事情,例如在不需要重启进程的情况下重新加载业务配置文件

注意:

 

子进程收到reload信号默认的动作是退出重启,以便新进程重新加载业务代码完成代码更新。所以reload后子进程在执行完onWorkerReload回调后便立刻退出是正常现象。

 

如果在收到reload信号后只想让子进程执行onWorkerReload,不想退出,可以在初始化Worker实例时设置对应的Worker实例的reloadable属性为false

callback Worker::$onWorkerStop $worker 设置Workert停止时的回调函数,即当Worker收到stop信号后执行Worker::onWorkerStop指定的回调函数
callback Worker::$onConnect $connection 当有客户端连接时触发的回调函数
callback Worker::$onMessage $connection

$data 客户端发送的数据

当有客户端的连接上有数据发来时触发
callback Worker::$onClose $connection 当客户端的连接断开时触发,不管连接是如何断开的,只要断开就会触发
callback Worker::$onBufferFull $connection 每个连接都有一个单独的应用层发送缓冲区,缓冲区大小由TcpConnection::$maxSendBufferSize决定,默认值为1MB,可以手动设置更改大小,更改后会对所有连接生效。

更多:http://doc3.workerman.net/worker-development/on-buffer-full.html

callback Worker::$onBufferDrain $connection 每个连接都有一个单独的应用层发送缓冲区,缓冲区大小由TcpConnection::$maxSendBufferSize决定,默认值为1MB,可以手动设置更改大小,更改后会对所有连接生效。

 

该回调在应用层发送缓冲区数据全部发送完毕后触发。一般与onBufferFull配合使用,例如在onBufferFull时停止向对端继续send数据,在onBufferDrain恢复写入数据。

callback Worker::$onError $connection

$code

$msg

当客户端的连接上发生错误时触发。

目前错误类型有

 

1、调用Connection::send由于客户端连接断开导致的失败 (code:WORKERMAN_SEND_FAIL msg:client closed)

 

2、在触发onBufferFull后,仍然调用Connection::send,并且发送缓冲区仍然是满的状态,导致发送失败 (code:WORKERMAN_SEND_FAIL msg:send buffer full and drop package)

 

3、使用AsyncTcpConnection异步连接失败时 (code:WORKERMAN_CONNECT_FAIL msg:stream_socket_client返回的错误消息)

 

四、接口

名称 参数 返回值 说明
void Worker::runAll(void) 运行所有worker实例
void Worker::stopAll(void) 停止当前进程(子进程)的所有Worker实例并退出。

 

此方法用于安全退出当前子进程,作用相当于调用exit/die退出当前子进程。

 

与直接调用exit/die区别是,直接调用exit或者die无法触发onWorkerStop回调,并且会导致一条WORKER EXIT UNEXPECTED错误日志。

void Worker::listen(void)     用于实例化Worker后执行监听。

 

此方法主要用于在Worker进程启动后动态创建新的Worker实例,能够实现同一个进程监听多个端口,支持多种协议。

 

例如一个http Worker启动后实例化一个websocket Worker,那么这个进程即能通过http协议访问,又能通过websocket协议访问。由于websocket Worker和http Worker在同一个进程中,所以它们可以访问共同的内存变量,共享所有socket连接。可以做到接收http请求,然后操作websocket客户端完成向客户端推送数据类似的效果。