PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器异步TCP/UDP网络客户端异步MySQL异步Redis数据库连接池AsyncTask消息队列毫秒定时器异步文件读写异步DNS查询。 Swoole内置了Http/WebSocket服务器端/客户端Http2.0服务器端

Swoole底层内置了异步非阻塞、多线程的网络IO服务器。PHP程序员仅需处理事件回调即可,无需关心底层。与Nginx/Tornado/Node.js等全异步的框架不同,Swoole既支持全异步,也支持同步。

除了异步IO的支持之外,Swoole为PHP多进程的模式设计了多个并发数据结构和IPC通信机制,可以大大简化多进程并发编程的工作。其中包括了并发原子计数器并发HashTableChannelLock进程间通信IPC等丰富的功能特性。

Swoole从2.0版本开始支持了内置协程,可以使用完全同步的代码实现异步程序。PHP代码无需额外增加任何关键词,底层自动进行协程调度,实现异步。

Swoole可以广泛应用于互联网、移动通信、企业软件、网络游戏、物联网、车联网、智能家庭等领域。 使用PHP+Swoole作为网络通信框架,可以使企业IT研发团队的效率大大提升,更加专注于开发创新产品。

Swoole是开源免费的自由软件,授权协议是Apache2.0。企业和个人开发者均可免费使用Swoole的代码,并且在Swoole之上所作的修改可用于商业产品,无需开源(注:必须保留原作者的版权声明)。

Server

$serv = new swoole_server("127.0.0.1"9501);
$serv->on('connect'function ($serv, $fd){
    echo "Client:Connect.\n";
});
$serv->on('receive'function ($serv, $fd, $from_id, $data) {
    $serv->send($fd, 'Swoole: '.$data);
    $serv->close($fd);
});
$serv->on('close'function ($serv, $fd) {
    echo "Client: Close.\n";
});
$serv->start();

Client

$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$client->on("connect"function($cli) {
    $cli->send("hello world\n");
});
$client->on("receive"function($cli, $data = ""){
    echo "Receive: ".$data.PHP_EOL;
});
$client->on("error"function($cli){
    echo "connect fail\n";
});
$client->on("close"function($cli){
    echo "connection close\n";
});
$client->connect('127.0.0.1'95010.5);

Http服务器

$serv = new swoole_http_server("127.0.0.1"9502);

$serv->on('Request'function($request, $response) {
    var_dump($request->get);
    var_dump($request->post);

    $response->cookie("User""Swoole");
    $response->header("X-Server""Swoole");
    $response->end("Hello Swoole!");
});

$serv->start();

WebSocket服务器

$serv = new swoole_websocket_server("127.0.0.1"9502);

$serv->on('Open'function($server, $req) {
    echo "connection open: ".$req->fd;
});

$serv->on('Message'function($server, $frame) {
    echo "message: ".$frame->data;
    $server->push($frame->fd, json_encode(["hello""world"]));
});

$serv->on('Close'function($server, $fd) {
    echo "connection close: ".$fd;
});

$serv->start();

1.首先我们要安装swoole扩展的话,需要把它的包下载下来,下载地址是:

https://github.com/swoole/swoole-src

2.下载下来之后进行解压:

unzip swoole-src-master.zip

3.解压之后打开解压的目录,我是解压在目录/opt下面的,所以

cd /opt/swoole-src-master

4.然后使用phpize重新编译php,执行命令:

 /usr/bin/phpize

如果你找不到phpize文件在哪,可以用指令查找,最好在根目录下,这样它才能从根目录下开始查找:

find -name phpize

如果你系统没有安装phpize的话,执行命令安装就可以了,指令为:

yum install php-devel

5.然后再进行配置,指令为:

 ./configure --with-php-config=/usr/bin/php-config

因为我的php-config文件在/usr/bin/下面,所以只要你用自己的php-config路径就可以了,其他都一致

6.配置好之后,进行编译安装:

make && make install

但在这步可能会出现问题:

/usr/include/php/ext/pcre/php_pcre.h:29:18error: pcre.h: No such file or directory

该错误是因为没有安装pcre-devel导致的,所有只要安装下就可以了

yum install pcre-devel

7.安装好之后会输出一个路径,那个就是生成swoole.so的文件路径,然后配置php.ini,把该路径配置进去:

extension=/usr/lib/php/modules/swoole.so

8.然后重启服务器

service httpd restart
文章来源:https://my.oschina.net/surjur/blog/309664

PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js 、 GO 、 Python 不断地在挑战 PHP 的地位。这些技术的推动者非常热衷于唱衰 PHP , PHP 语言的未来在哪里?PHP 程序员当如何应对未来的变革?

作为老牌的 Web 后端编程语言,PHP 在全球市场占有率非常高,仅次于 Java ,从各个招聘网站的数据上来看PHP 开发的职位非常多,薪资水平也非常不错。实际在中小企业、互联网创业公司PHP的市场地位是高于 Java 的。Java 在超大型企业、传统软件行业、金融领域优势更大。目前来看 Node.js、 GO 、 Python 、 Ruby 等语言还难以企及 PHP 和 Java 。

PHP 语言之所以能有今天的地位,得益于PHP语言设计者一直遵从实用主义,将技术的复杂性隐藏在底层。PHP 语言入门简单,容易掌握,程序健壮性好,不容易出现像 Java 、 C++ 等其他语言那样复杂的问题,如内存泄漏和 Crash ,跟踪调试相对轻松很多。PHP 官方提供的标准库非常强大,各种功能函数都能在官方的标准库中找到,包括MySQL、Memcache、Redis、GD图形库、CURL、XML、JSON等等,免除了开发者到处找库的烦恼。PHP 的文档非常棒,每个函数都有详细的说明和使用示例。第三方类库和工具、代码、项目也很丰富。开发者可以快速、高效地使用 PHP 编写开发各类软件。到目前为止市面上仍然没有出现比 PHP 更简单易用的编程语言。所以 PHP 的前景还是很广阔的,与其纠结于编程语言的选择,不如好好地深入学习使用 PHP 。

作为一个资深的 PHP 开发者,在技术上给各位 PHP 程序十点未来的建议,希望对大家有所帮助。

1. Composer

第一点就要提 Composer ,自从 Composer 出现后,PHP 的依赖管理可以变得非常简单。程序内依赖一些类库和框架,直接使用 Composer 引入即可,通过使用 composer update 安装依赖的包。解决了过去加载外部库的各种难题。Composer 也有国内镜像,速度非常快。现在绝大部分PHP开源的项目都提供了 Composer 的支持,建议大家在项目中使用 Composer 来解决 PHP 代码包管理的问题,不要再使用下载源码、手工 include 的原始方法。

2. PHP7

PHP7 版本对 Zend 引擎做了大量修改,大幅提升了 PHP 语言的性能,使用 PHP7 可以使你的程序性能瞬间翻倍。即使是 WordPress 这样重量级的软件运行在 PHP7 都能有上千 QPS ,相当于一台服务器每天就能处理 8000 万次请求。使用 PHP7 ,做好 MySQL 优化,使用 Memcache 和 Redis 进行加速,这套技术架构完全可以应对相当大规模的系统。除了某些亿级用户的平台之外,一般规模的系统完全没有压力。

3. PSR

PSR 是 http://www.php-fig.org/ 组织制定的PHP语言开发规范,约定了很多方面的规则,如命名空间、类名
规范、编码风格标准、Autoload、公共接口等。现在已经成为PHP技术社区事实上的标准了。很多知名的 PHP 框架和类库都遵守了 PSR 规范。PHP 开发者应当学习掌握 PSR 规范,在开发程序时应当尽量遵循 PSR 规范。

4. Swoole

2017 年 PHP 还局限于做 Web 网站吗?No ,如果你还不知道 Swoole ,赶快去了解一下吧。Swoole 的口号是重新定义 PHP 语言,Swoole 是一个异步并行的通信引擎,作为 PHP 的扩展来运行。Node.js 的异步回调 Swoole 有,Go语言的协程 Swoole 也有,这完全颠覆了对 PHP 的认知。使用 Swoole PHP 可以实现常驻内存的 Server 程序,可以实现 TCP 、 UDP 异步网络通信的编程开发。过去PHP只能做一个 Web 网站,现在使用 Swoole 可以做 Java 、C++ 才能实现的通信服务,比如 WebSocket 即使通信、聊天、推送服务器、RPC 远程调用服务、网关、代理、游戏服务器等。如果你想用 PHP 做点 Web 系统之外的东西,Swoole 是最好的选择。

5. Laravel

最近几年最火热的 PHP 框架,官网号称是为 Web 艺术家设计的框架,可见这套框架有多优雅。Laravel 提供的功能模块丰富,API 设计简洁,表达力强。而且它的社区非常活跃,代码贡献者众多,第三方的插件非常多,生态系统相当繁荣。 Laravel 底层使用了很多 symfony2 组件,通过 composer 实现了依赖管理。如果还在纠结使用什么PHP框架,不如选择 Laravel 。 Laravel 提供的命令行工具基于 symfony.console 实现,功能强大,集成了各种项目管理、自动生成代码的功能。

6. Phar

PHP5.3 之后支持了类似 Java 的 jar 包,名为 phar。用来将多个 PHP 文件打包为一个文件。这个特性使得 PHP 也可以像 Java 一样方便地实现应用程序打包和组件化。一个应用程序可以打成一个 Phar 包,直接放到
PHP-FPM 中运行。配合 Swoole ,可以在命令行下执行 php server.phar 一键启动服务器。PHP 的代码包可以用 Phar 打包成组件,放到 Swoole 的服务器容器中去加载执行。

7. C/C++/GO

任何技术有优点就有缺点,PHP 作为一门动态脚本语言,优点是开发方便效率高。缺点就是性能差。在密集运算的场景下比 C 、 C++ 相差几十倍甚至上百倍。另外 PHP 不可以直接操作底层,需要依赖扩展库来提供 API 实现。PHP 程序员可以学习一门静态编译语言作为补充实现动静互补,C/C++/Go 都是不错的选择。而且静态语言的编程体验与动态语言完全不同,学习过程可以让你得到更大的提升。

掌握 C/C++ 语言后,还可以阅读 PHP 、 Swoole 、 Nginx 、Redis 、 Linux内核 等开源软件的源码,了解其底层运行原理。

现在最新版本的Swoole提供了C++扩展模块的支持,封装了Zend API,用C++操作PHP变得很简单,可以用C++实现PHP扩展函数和类。

8. HTML5

作为 Web 前端新一代标准,HTML5 未来前景非常广阔,市场需求量非常大。从 PC 网站、B/S 企业软件、移动端网页、APP,这些领域都在拥抱 HTML5,掌握了 HTML5 才能在下一波互联网技术大潮中存活下来。

9. Vue.js

PHP 程序员除了写后台程序之外,还有很大一部分工作在展现层,和浏览器前端打交道。2017 年你还在用 jQuery 操作 DOM 实现界面渲染吗?已经完全 out 了。现在用 Vue.js 可以非常方便地实现数据和 DOM 元素的绑定。通过 Ajax 请求后台接口返回数据后,更新前端数据自动实现界面渲染。2017 年再不学 Vue 就晚了。

如果你不光要写 Web 程序,同时还希望兼顾 Android 、IOS 、PC 客户端等平台,React Native 是一个不错的选择。

10. 深度学习/人工智能

互联网的未来属于人工智能,如果你还不了解机器学习、深度学习、人工智能这些概念,那你需要尽快学习了解一下。现在互联网巨头们都在布局人工智能,包括 Google 、 Facebook 、微软、亚马逊 和国内的百度。虽然现在还处于科学研究的阶段,但未来互联网的各个领域都会应用到人工智能,包括自动驾驶、大数据分析、网络游戏、图像识别、语言处理等。当然现在普通的工程师可能还无法参与到人工智能产品中,但至少应该理解深度学习/人工智能的基本概念和原理。

来源:segmentfault 作者:韩天峰(matyhtf

Gearman是一个用来把工作委派给其他机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来在调用其它语言的函数的系统。

 

编译安装 gearmand

Php代码  收藏代码
  1. cd gearmand-1.1.12
  2. [root@AY1403121111165237f2Z gearmand-1.1.12]# ls
  3. aclocal.m4  build-aux     configure.ac  gear_config.in  libgearman-1.0     libhashkit-1.0  Makefile.am  README   tests
  4. AUTHORS     ChangeLog     COPYING       gearmand        libgearmancore     libhostile      Makefile.in  rpm      THANKS
  5. benchmark   configmake.h  docs          HACKING         libgearman-server  libtest         man          scripts  util
  6. bin         configure     examples      libgearman      libhashkit         m4              NEWS         support  version.m4
  7. [root@AY1403121111165237f2Z gearmand-1.1.12]# ./configure
  8. configure: error: could not find boost 错误解决
  9. [root@AY1403121111165237f2Z gearmand-1.1.12]#yum install boost-devel*
  10. configure: error: could not find gperf 错误解决
  11. [root@AY1403121111165237f2Z gearmand-1.1.12]#yum install gperf*
  12. configure: error: Unable to find libevent 错误解决
  13. [root@AY1403121111165237f2Z gearmand-1.1.12]#yum install libevent-devel*
  14. configure: error: Unable to find libuuid 错误解决
  15. [root@AY1403121111165237f2Z gearmand-1.1.12]#yum install libuuid-devel

上面错误的原因是编译器找不到 头文件

 

Php代码  收藏代码
  1. [root@AY1403121111165237f2Z gearmand-1.1.12]#make
  2. [root@AY1403121111165237f2Z gearmand-1.1.12]#make install
  3. 测试
  4. [root@AY1403121111165237f2Z /]# gearman -w -f wc — wc -l
  5. [root@AY1403121111165237f2Z /]# gearman -f wc < /etc/passwd

运行过程

 

一个Gearman请求的处理过程涉及三个角色:Client -> Job -> Worker。

Client:请求的发起者,可以是 C,PHP,Perl,MySQL UDF 等等。

Job:请求的调度者,用来负责协调把 Client 发出的请求转发给合适的 Work。

Worker:请求的处理者,可以是 C,PHP,Perl 等等。

因为 Client,Worker 并不限制用一样的语言,所以有利于多语言多系统之间的集成。

我们可以通过增加更多的 Worker,可以很方便的实现应用程序的分布式负载均衡架构。

 

Gearman PHP扩展安装

Php代码  收藏代码
  1. [root@AY1403121111165237f2Z gearman-1.1.2]# /www/wdlinux/php/bin/phpize
  2. [root@AY1403121111165237f2Z gearman-1.1.2]# ./configure –with-php-config=/www/wdlinux/php/bin/php-config
  3. [root@AY1403121111165237f2Z gearman-1.1.2]# make
  4. [root@AY1403121111165237f2Z gearman-1.1.2]# make install

修改PHP的配置文件 重新启动 Apache

测试Gearman PHP扩展

Php代码  收藏代码
  1. work.php
  2. <?php
  3. $workernew GearmanWorker();
  4. $worker->addServer(“127.0.0.1”, 4730);
  5. $worker->addFunction(“title”,“title_function”);
  6. while ($worker->work());
  7. function title_function($job)
  8. {
  9.     $str = $job->workload();
  10.     return strlen($str);
  11. }
  12. ?>
  13. ———————————————–
  14. client.php
  15. <?php
  16. $clientnew GearmanClient();
  17. $client->addServer(“127.0.0.1”, 4730);
  18. print $client->do(“title”,“Linvo”);
  19. ?>

祝大家玩的开心

作者 范遥 [@buddy-L]

这篇文章主要介绍了PHP高级编程实例:编写守护进程,守护进程是脱离于终端并且在后台运行的进程,本文讲解使用PHP编写守护进程,并给出了代码实例,需要的朋友可以参考下

1.什么是守护进程

守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。

例如 apache, nginx, mysql 都是守护进程

2.为什么开发守护进程

很多程序以服务形式存在,他没有终端或UI交互,它可能采用其他方式与其他程序交互,如TCP/UDP Socket, UNIX Socket, fifo。程序一旦启动便进入后台,直到满足条件他便开始处理任务。

3.何时采用守护进程开发应用程序

以我当前的需求为例,我需要运行一个程序,然后监听某端口,持续接受服务端发起的数据,然后对数据分析处理,再将结果写入到数据库中; 我采用ZeroMQ实现数据收发。

如果我不采用守护进程方式开发该程序,程序一旦运行就会占用当前终端窗框,还有受到当前终端键盘输入影响,有可能程序误退出。

4.守护进程的安全问题

我们希望程序在非超级用户运行,这样一旦由于程序出现漏洞被骇客控制,攻击者只能继承运行权限,而无法获得超级用户权限。

我们希望程序只能运行一个实例,不运行同事开启两个以上的程序,因为会出现端口冲突等等问题。

5.怎样开发守护进程

例 1. 守护进程例示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<?php
class ExampleWorker extends Worker {
 #public function __construct(Logging $logger) {
 # $this->logger = $logger;
 #}
 #protected $logger;
 protected static $dbh;
 public function __construct() {
 }
 public function run(){
  $dbhost = '192.168.2.1'// 数据库服务器
  $dbport = 3306;
   $dbuser = 'www'// 数据库用户名
 $dbpass = 'qwer123';    // 数据库密码
  $dbname = 'example'// 数据库名
  self::$dbh = new PDO("mysql:host=$dbhost;port=$dbport;dbname=$dbname", $dbuser, $dbpass, array(
   /* PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'', */
   PDO::MYSQL_ATTR_COMPRESS => true,
   PDO::ATTR_PERSISTENT => true
   )
  );
 }
 protected function getInstance(){
 return self::$dbh;
  }
}
/* the collectable class implements machinery for Pool::collect */
class Fee extends Stackable {
 public function __construct($msg) {
  $trades = explode(",", $msg);
  $this->data = $trades;
  print_r($trades);
 }
 public function run() {
  #$this->worker->logger->log("%s executing in Thread #%lu", __CLASS__, $this->worker->getThreadId() );
  try {
   $dbh = $this->worker->getInstance();
   
   $insert = "INSERT INTO fee(ticket, login, volume, `status`) VALUES(:ticket, :login, :volume,'N')";
   $sth = $dbh->prepare($insert);
   $sth->bindValue(':ticket', $this->data[0]);
   $sth->bindValue(':login', $this->data[1]);
   $sth->bindValue(':volume', $this->data[2]);
   $sth->execute();
   $sth = null;
   
   /* ...... */
   
   $update = "UPDATE fee SET `status` = 'Y' WHERE ticket = :ticket and `status` = 'N'";
   $sth = $dbh->prepare($update);
   $sth->bindValue(':ticket', $this->data[0]);
   $sth->execute();
   //echo $sth->queryString;
   //$dbh = null;
  }
  catch(PDOException $e) {
   $error = sprintf("%s,%s\n", $mobile, $id );
   file_put_contents("mobile_error.log", $error, FILE_APPEND);
  }
 }
}
class Example {
 /* config */
 const LISTEN = "tcp://192.168.2.15:5555";
 const MAXCONN = 100;
 const pidfile = __CLASS__;
 const uid = 80;
 const gid = 80;
 
 protected $pool = NULL;
 protected $zmq = NULL;
 public function __construct() {
  $this->pidfile = '/var/run/'.self::pidfile.'.pid';
 }
 private function daemon(){
  if (file_exists($this->pidfile)) {
   echo "The file $this->pidfile exists.\n";
   exit();
  }
  
  $pid = pcntl_fork();
  if ($pid == -1) {
    die('could not fork');
  } else if ($pid) {
    // we are the parent
    //pcntl_wait($status); //Protect against Zombie children
   exit($pid);
  } else {
   // we are the child
   file_put_contents($this->pidfile, getmypid());
   posix_setuid(self::uid);
   posix_setgid(self::gid);
   return(getmypid());
  }
 }
 private function start(){
  $pid = $this->daemon();
  $this->pool = new Pool(self::MAXCONN, \ExampleWorker::class, []);
  $this->zmq = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_REP);
  $this->zmq->bind(self::LISTEN);
  
  /* Loop receiving and echoing back */
  while ($message = $this->zmq->recv()) {
   //print_r($message);
   //if($trades){
     $this->pool->submit(new Fee($message));
     $this->zmq->send('TRUE');
   //}else{
   // $this->zmq->send('FALSE');
   //}
  }
  $pool->shutdown();
 }
 private function stop(){
  if (file_exists($this->pidfile)) {
   $pid = file_get_contents($this->pidfile);
   posix_kill($pid, 9);
   unlink($this->pidfile);
  }
 }
 private function help($proc){
  printf("%s start | stop | help \n", $proc);
 }
 public function main($argv){
  if(count($argv) < 2){
   printf("please input help parameter\n");
   exit();
  }
  if($argv[1] === 'stop'){
   $this->stop();
  }else if($argv[1] === 'start'){
   $this->start();
  }else{
   $this->help($argv[0]);
  }
 }
}
$cgse = new Example();
$cgse->main($argv);

5.1. 程序启动

下面是程序启动后进入后台的代码

通过进程ID文件来判断,当前进程状态,如果进程ID文件存在表示程序在运行中,通过代码file_exists($this->pidfile)实现,但而后进程被kill需要手工删除该文件才能运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private function daemon(){
  if (file_exists($this->pidfile)) {
   echo "The file $this->pidfile exists.\n";
   exit();
  }
  
  $pid = pcntl_fork();
  if ($pid == -1) {
    die('could not fork');
  } else if ($pid) {
   // we are the parent
   //pcntl_wait($status); //Protect against Zombie children
   exit($pid);
  } else {
   // we are the child
   file_put_contents($this->pidfile, getmypid());
   posix_setuid(self::uid);
   posix_setgid(self::gid);
   return(getmypid());
  }
 }

程序启动后,父进程会推出,子进程会在后台运行,子进程权限从root切换到指定用户,同时将pid写入进程ID文件。

5.2. 程序停止

程序停止,只需读取pid文件,然后调用posix_kill($pid, 9); 最后将该文件删除。

1
2
3
4
5
6
7
8
private function stop(){
  if (file_exists($this->pidfile)) {
   $pid = file_get_contents($this->pidfile);
   posix_kill($pid, 9);
   unlink($this->pidfile);
  }
 }

如对本文有疑问,请提交到交流社区,广大热心网友会为你解答!! 点击进入社区

安装Gearman

========================================================

向一个机器添加Gearman需要两步:

1.构建并启动这个守护进程(gearmand)

2.构建与php版本相匹配的PHP扩展。

========================================================

安装gearmand

========================================================

我安装版本是gearmand 1.1.12:

1. 首先安装依赖包:

sudo yum -y install autoconf bison flex libtool libboost-all-dev libcurl4-openssl-dev curl libevent-dev uuid-dev libsqlite3-dev libmysqlclient-dev mysql-devel

2.下载Gearmand版本

在https://launchpad.net/gearmand下载最新版本

3.解压、编译、安装源码包

tar xvzf gearmand-1.1.12.tar.gzcd gearmand-1.1.12./configuremakemake install

注:这个过程中可能无法编译成功,而且几率很大,我安装的时候出现各种问题,但主要都是缺少共享库,这时候要根据个人实际情况,看它报的是什么错,然后根据报错,更新或者安装共享库。

sudo yum install ***等。

4.为大多数最新的共享库创建必须的链接和缓存。其中可能报:

error: gearman: error while loading shared libraries: libgearman.so.8: cannot open shared object file: No such file or directory

解决办法:sudo ldconfig,我安装的时候就出现了这种情况,一开始不知道怎么回事,百度了很久才找到这个方法。

安装php 的gearman 扩展

========================================================

下载最新版本:

$ wget http://pecl.php.net/get/gearman-1.1.1.tgz$ tar zxvf gearman-1.1.1.tgz$ cd gearman-1.1.1/$ phpize

$ ./configure –with-php-config=/usr/local/php/bin/php-config

$ make$ make install

6. 在php.ini文件末尾添加”extension=gearman.so”

7. 检测扩展是否安装成功

$ php –info | grep “gearman support”gearman support => enabled

显示出:gearman support => enabled,就表示安装成功啦。

测试

========================================================

1)sudo ldconfig

2)启动gearmand: gearmand -d &

这一步可能会遇到:

启动这个 agent,即 Gearman 守护程序:/usr/local/sbin/gearmand –daemon报错:Could not open log file “/usr/local/var/log/gearmand.log”, from “/usr/sbin”, switching to stderr. (No such file or directory)解决:mkdir -p /usr/local/var/log/cd /usr/local/var/log/touch gearmand.log再次尝试启动:/usr/local/sbin/gearmand –daemon成功运行.查看进程:ps -ef | grep gearmandroot 19390 1 0 17:50 ?00:00:00 gearmand –daemonroot 19403 1 0 17:54 ?00:00:00 /usr/local/sbin/gearmand –daemonroot 19406 1556 0 17:54 pts/300:00:00 grep gearmand

3)查看gearmand是否在运行:ps aux | grep [g]earmand

4)检查germand的任务检测端口4730:sudo lsof -i tcp:4730

例子:从PHP使用Gearman

=====================================================

从 PHP 使用 Gearman 类似于之前的示例,惟一的区别在于这里是在 PHP 内创建 producer 和 consumer。每个 consumer 的工作均封装在一个或多个 PHP 函数内。先用 PHP 编写的一个 Gearman worker。将这些代码保存在一个名为 worker.php 的文件中。<?php $worker= new GearmanWorker(); $worker->addServer(); $worker->addFunction(“title”, “title_function”); while ($worker->work()); function title_function($job) {return ucwords(strtolower($job->workload())); }?>再用 PHP 编写的一个 producer,或 client。将此代码保存在一个名为 client.php 的文件内。<?php $client= new GearmanClient(); $client->addServer(); print $client->do(“title”, “All The World’s a stage!”); print “/n”;?>现在,可以用如下的命令行连接客户机与 worker 了:php worker.php &php client.php结果:All The World’s a stage!

  • 安装Gearman服务端
    1. # yum install -y uuid-devel libuuid libuuid-devel uuid boost-devel libevent libevent-devel gperf
    2. # wget https://launchpad.net/gearmand/1.2/1.1.7/+download/gearmand-1.1.7.tar.gz
    3. # tar zxvf gearmand-1.1.7.tar.gz
    4. # cd gearmand-1.1.7
    5. # ./configure –prefix=/usr/local/gearmand
    6. # make && make install

    启动Gearman服务端:

    # gearmand -L ip -p 端口(默认4730) -uroot -d

    • -b,–backlog= 储备的监听连接数量
    • -d, –daemon 后台运行
    • -f, –file-descriptors= 文件描述符的数量
    • -h, –help 帮助
    • -j, –job-retries= 在ob server移除不可用job之前运行的次数,防止不断运行导致其他可用worker崩溃。默认没有限制
    • -l, -log-file= 日志文件存放位置(默认记录最简单日志)
    • -L, –listen= 监听的IP,默认全部接受
    • -p, –port= 指定监听端口
    • -P, –pid-file= 指定进程ID写入位置
    • -r, –protocol= 加载协议模块
    • -q, –queue-type= 指定持久化队列
    • -t, –threads= 使用的I/9线程数量。默认为0
    • -u, –user= 启动后,切换到指定用户
    • -v, –verbose 增加一级详细程度
    • -V, –version 显示版本信息

    出现Could not open log file这种错误,需要使用–log-file指定日志文件

    安装PHP扩展

    1. # wget http://pecl.php.net/get/gearman-1.1.1.tgz
    2. # tar zxvf gearman-1.1.1.tgz
    3. # cd gearman-1.1.1
    4. # /usr/local/server/php/bin/phpize
    5. # ./configure –with-php-config=php-config目录
    6. # make && make install

    如果出现错误:libgearman version 0.21 or later required,说明libgearman版本过低,libgearman所有版本地址:

    http://fr2.rpmfind.net/linux/rpm2html/search.php?query=libgearman-devel&system=&arch=

    rpm包地址:http://dl.fedoraproject.org/pub/epel/6/x86_64/

    如果仍然出错,可考虑换一个低版本的gearman:http://pecl.php.net/package/gearman上述步骤会输出扩展安装目录:/usr/local/server/php-5.4.14/lib/php/extensions/no-debug-non-zts-20100525/
    修改php.ini,以下加入语句加入:
    extension=/usr/local/server/php-5.4.14/lib/php/extensions/no-debug-non-zts-20100525/gearman.so

    重启php-fpm,用phpinfo查看是否安装成功
    # service php-fpm restart

    Note:

    安装PHP扩展时候,有可能因为版本问题导致安装失败。所以最好去官网看下最新版本。

    参考:

为大家介绍下在php.ini文件中配置php文件上传功能的方法,涉及到一些重要的选项,关系到php上传文件大小的限制等,有需要的朋友参考下

昨天分享了在PHP网站开发中如何在php.ini中配置实现session功能的PHP教程,今天继续分享在利用PHP实现文件上传功能时几点关键php.ini的配置。

说到在php.ini中的文件上传的配置,其实在之前介绍PHP文件上传功能代码实例教程以及Jquery AjaxUpload实现文件上传功能代码实例教程时我都有所提及。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项。

php.ini中文件上传功能配置选项说明

打开php.ini配置文件找到File Uploads

file_uploads = On

默认允许HTTP文件上传,此选项不能设置为OFF。

upload_tmp_dir =

默认为空,此选项在手动配置PHP运行环境时,也容易遗忘,如果不配置这个选项,文件上传功能就无法实现,这个选项设置的是文件上传时存放文件的临时目录,你必须给这个选项赋值,比如upload_tmp_dir =’/leapsoulcn’,代表在C盘目录下有一个leapsoulcn目录,和session配置一样,如果你是在linux环境下,你必须赋予这个目录可写权限。

如何上传超过8M的大文件?

上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项。

php.ini配置文件中的默认文件上传大小为2M,php初学者容易犯的一个错误是在编写文件上传功能时通过设置上传文件最大大小的表单区域,即允许上传文件的最大值,max_file_size(隐藏值域)的值来规定上传文件的大小,其实一般别人可以绕过这个值,所以安全起见,最好是在php.ini配置文件中配置upload_max_filesize选项,设定文件上传的大小。

默认upload_max_filesize = 2M,即文件上传的大小为2M,如果你想上传超过8M的文件,比如20M,你必须设定upload_max_filesize = 20M。

但是光设置upload_max_filesize = 20M还是无法实现大文件的上传功能,你必须修改php.ini配置文件中的post_max_size选项,其代表允许POST的数据最大字节长度,默认为8M。如果POST数据超出限制,那么$_POST和$_FILES将会为空。要上传大文件,你必须设定该选项值大于upload_max_filesize指令的值,我一般设定upload_max_filesize和post_max_size值相等。另外如果启用了内存限制,那么该值应当小于memory_limit选项的值。

  文件上传的其他注意事项

在上传大文件时,你会有上传速度慢的感觉,当超过一定的时间,会报脚本执行超过30秒的错误,这是因为在php.ini配置文件中max_execution_time配置选项在作怪,其表示每个脚本最大允许执行时间(秒),0 表示没有限制。你可以适当调整max_execution_time的值,不推荐设定为0。

至此,在php.ini配置文件中对文件上传选项进行配置的PHP教程就介绍完毕了,通过上面的步骤实践与学习,再结合PHP程序,文件上传功能就可以实现了。

下面是一些补充:
本文介绍了如何配置php.ini实现PHP文件上传功能。其中涉及到php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,这些选项是文件上传成败的关键。我们以php.5.3.5的Windows版本为例说明。

php.ini中文件上传功能配置选项说明
用文本工具(推荐EditPlus)打开php.ini 配置文件,查找 File Uploads ,在这个区域有以下3个选项:

file_uploads = On

是否允许HTTP文件上传。默认值为On允许HTTP文件上传,此选项不能设置为Off。

upload_tmp_dir =

文件上传的临时存放目录。如果没指定则PHP会使用系统默认的临时目录。该选项默认为空,此选项在手动配置PHP运行环境时,也容易遗忘,如果不配置这个选项,文件上传功能就无法实现,你必须给这个选项赋值,比如upload_tmp_dir = “d:/fileuploadtmp” ,代表在D盘目录下有一个fileuploadtmp目录,并且给这目录读写权限。

upload_max_filesize = 2M

上传文件的最大尺寸。这个选项默认值为2M,即文件上传的大小为2M,如果你想上传一个50M的文件,你必须设定 upload_max_filesize = 50M。
但是仅设置upload_max_filesize = 50M 还是无法实现大文件的上传功能,我们还必须修改php.ini文件中的 post_max_size 选项。

继续在 php.ini 中查找 Data Handling ,在这个区域有1个选项:

post_max_size = 8M

指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默认为8M。如果POST数据超出限制,那么$_POST和$_FILES将会为空。
要上传大文件,你必须设定该选项值大于upload_max_filesize选项的值,例如你设置了upload_max_filesize = 50M ,这里可以把post_max_size = 100M。
另外如果启用了内存限制,那么该值应当小于memory_limit 选项的值。

继续在 php.ini 中查找 Resource Limits ,在这个区域有3个选项:

max_execution_time = 30

每个PHP页面运行的最大时间值(单位秒),默认30秒。当我们上传一个较大的文件,例如50M的文件,很可能要几分钟才能上传完,但php默认页面最久执行时间为30秒,超过30秒,该脚本就停止执行,这就导致出现无法打开网页的情况。因此我们可以把值设置的较大些,如 max_execution_time = 600。 如果设置为0,则表示无时间限制。

max_input_time = 60

每个PHP脚本解析请求数据所用的时间(单位秒),默认60秒。当我们上传大文件时,可以将这个值设置的较大些。 如果设置为0,则表示无时间限制。

memory_limit = 128M

这个选项用来设置单个PHP脚本所能申请到的最大内存空间。这有助于防止写得不好的脚本消耗光服务器上的可用内存。如果不需要任何内存上的限制将其设为 -1。
php5.2.0以前的版本默认8M; php.5.2.0版本默认为16M。php 5.2.0之后的版本默认为 128M;

php.ini 配置上传文件功能示例
假设要上传一个50M的大文件。配置 php.ini 如下:
file_uploads = On
upload_tmp_dir = “d:/fileuploadtmp”
upload_max_filesize = 50M
post_max_size = 100M
max_execution_time = 600
max_input_time = 600
memory_limit = 128M

提示:需要保持 memory_limit > post_max_size > upload_max_filesize

此例仅供参考,你可以根据实际情况调整。

 

文章来源:网络

nginx 出现413 Request Entity Too Large问题的解决方法

使用PHP上传图片(大小1.9M),出现 nginx: 413 Request Entity Too Large 错误。

根据经验是服务器限制了上传文件的大小,但php默认的文件上传是2M,应该不会出现问题。

打开php.ini,把 upload_max_filesize 和 post_max_size 修改为20M,然后重启。

再次上传,问题依旧,可以排除php方面的问题。

原来nginx默认上传文件的大小是1M,可nginx的设置中修改。

解决方法如下:

1.打开nginx配置文件 nginx.conf, 路径一般是:/etc/nginx/nginx.conf。

2.在http{}段中加入 client_max_body_size 20m; 20m为允许最大上传的大小。

3.保存后重启nginx,问题解决。

如果用php的+-*/计算浮点数的时候,可能会遇到一些计算结果错误的问题,所以基本上大部分语言都提供了精准计算的类库或函数库,比如php有BC高精确度函数库,下面我们介绍一下一些常用的BC高精确度函数使用。

bc是Binary Calculator的缩写。bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_operand, string $right_operand[, int $scale]),如果scale没有提供,就用bcscale的缺省值。这里大数直接用一个由0-9组成的string表示,计算结果返回的也是一个 string。

bcadd — 将两个高精度数字相加
bccomp — 比较两个高精度数字,返回-1, 0, 1
bcdiv — 将两个高精度数字相除
bcmod — 求高精度数字余数
bcmul — 将两个高精度数字相乘
bcpow — 求高精度数字乘方
bcpowmod — 求高精度数字乘方求模,数论里非常常用
bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=”
bcsqrt — 求高精度数字平方根
bcsub — 将两个高精度数字相减

首先看一段代码:

1
2
3
4
<?php
$a = 0.1;
$b = 0.7;
var_dump(($a + $b) == 0.8);

打印出来的值居然为 boolean false

这是为啥?PHP手册对于浮点数有以下警告信息:

Warning
浮点数精度
显然简单的十进制分数如同 0.1 或 0.7 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999…。
这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数。例如,十进制的 1/3 变成了 0.3333333. . .。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

那么上面的算式我们应该改写为

1
2
3
4
<?php
$a = 0.1;
$b = 0.7;
var_dump(bcadd($a,$b,2) == 0.8);

这样就能解决浮点数的计算问题了