扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
PHP是一种纯解释型在服务端执行的可以内嵌HTML的脚本语言,尤其适合开发Web应用程序。
创新互联专注于普洱企业网站建设,成都响应式网站建设公司,成都做商城网站。普洱网站建设公司,为普洱等地区提供建站服务。全流程按需制作,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务
请求一个 PHP 脚本时,PHP 会读取该脚本,并将其编译为 Zend 操作码,这是要执行的代码的一种二进制表示形式。随后,此操作码由 PHP 执行并丢弃。 PHP脚本在每次被解释时进行初始化,在解释完毕后终止运行。这种运行是互相独立的,每一次请求都会创建一个单独的进程或线程,来解释相应的页面文件。页面创建的变量和其他对象,都只在当前的页面内部可见,无法跨越页面访问。在终止运行后,页面中申请的、没有被代码显式释放的外部资源,包括内存、数据库连接、文件句柄、Socket连接等,都会被强行释放。也就是说,PHP无法在语言级别上实现直接访问跨越页面的变量,也无法创建驻留内存的对象。
PHP这种独特的工作模型的优势在于,基本上解决了令人头疼的资源泄漏问题。Web应用的特点是大量的、短时间的并发处理,对各种资源的申请和释放工作非常频繁,很容易导致泄漏甚至崩溃。PHP的运行机制决定它不存在常规的崩溃问题(顶多连接超时脚本停止执行),可以说PHP是较稳定的Web应用。但是,这种机制的缺点也非常明显。最直接的后果是,PHP在语言级别无法实现跨页面的缓冲机制。这种缓冲机制缺失造成的影响,可以分成两个方面:
一是对象的缓冲。众所周知,很多设计模式都依赖于对象的缓冲机制,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源,对于需要频繁应付大量并发的服务端软件更是如此。因此,对象缓冲的缺失,理论上会极大地降低速度。应尽可能减少创建和销毁对象的次数来提高服务程序的效率,由于 PHP目前还不支持多线程,也就无法像Java一样通过线程池调度来弥补这一缺陷;但可以使用第三方软件如Memcachd来实现PHP的对象缓冲机制,达到减少对象创建和销毁的时间来提高服务程序的效率。Memcachd将PHP编译后的 操作码缓存并在内存中保存这个操作码,并在下一次调用该页面时重用它,这会节省很多时间。比较常用的缓存还有有 eAccelerator,另一种流行的 eAccelerator 替代工具是 Alternative PHP Cache(APC)。
二是数据库连接的缓冲。对于MySQL,PHP提供了一种内置的数据库缓冲机制,即用mysql_pconnect()代替mysql_connect() 来打开数据库而已。PHP会自动回收被废弃的数据库连接,以供重复使用。在实际应用中,这种持久性数据库连接往往会导致数据库连接的伪泄漏现象:在某个时间,并发的数据库连接过多,超过了MySQL的最大连接数,从而导致新的进程无法连接数据库。但是过一段时间,当并发数减少时,PHP会释放掉一些连接,网站又会恢复正常。出现这种现象的原因是,当使用pconnect时,Apache 的httpd进程会不释放connect,而当Apache的httpd进程数超过了mysql的最大连接数时,就会出现无法连接的情况。因此,需要小心地调整Apache和Mysql的配置,以使Apache的httpd进程数不会超出MySQL的最大连接数。笔者经过实践,在PHP5和 Oracle10g的连接中,由于频于数据库连接,有时候还会出现数据库丢失连接的情况(Oracle官方有针对PHP的增强包,不知是否可以解决此问题,笔者未试)。
PHP的工作模型即是缺点也是优势,从本质上说,这就是PHP 的独特之处。
若以FastCGI模式运行php,解析php.ini、载入全部扩展并重初始化全部数据结构这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接可以工作。Nginx+PHP(FastCGI)是个不错的选择。
PHP是比较流行的脚本语言,WEB开发使用广泛,如何在C++程序中不依赖任何WEB
SERVER调用PHP,并取得执行结果完成交互。
PHP安装好后,在目录下有一个php-cgi.exe,我们只要执行这个CGI程序,并将数据通过命名管道传递给它,然后把执行结果通过命名管道读取出来即可,过程并不复杂!请看如下代码:
命名管道的创建:
SECURITY_ATTRIBUTES
sa
=
{sizeof(SECURITY_ATTRIBUTES)};
sa.bInheritHandle
=
1;
sa.lpSecurityDescriptor
=
NULL;
HANDLE
hStdoutR,
hStdoutW,
hStdinR,
hStdinW;
CreatePipe(hStdoutR,
hStdoutW,
sa,
0);
SetHandleInformation(hStdoutR,HANDLE_FLAG_INHERIT,
0);
CreatePipe(hStdinR,
hStdinW,
sa,
0);
SetHandleInformation(hStdinW,
HANDLE_FLAG_INHERIT,
0);
启动php-cgi进程:
STARTUPINFO
si
=
{sizeof(STARTUPINFO)};
PROCESS_INFORMATION
pi;
si.dwFlags
=
STARTF_USESTDHANDLES;
si.hStdOutput
=
hStdoutW;
si.hStdInput
=
hStdinR;
char
env[255]
=
"REQUEST_METHOD=POST\0CONTENT_LENGTH=18\0CONTENT_TYPE=
application/x-www-form-urlencoded\0SCRIPT_FILENAME=D:\\test.php";
if(!CreateProcess(NULL,
"d:\\php5\\php-cgi.exe
D:\\test.php",
NULL,
NULL,
1,
NORMAL_PRIORITY_CLASS,
env,
NULL,
si,
pi))
return
0;
CloseHandle(hStdoutW);
CloseHandle(hStdinR);
传递数据:if(!WriteFile(hStdinW,
"var=Hello
VCKBASE!",
18,
dwWritten,
NULL))
return
0;
CloseHandle(hStdinW);
读取返回数据:char
buf[1000]
=
{0};
DWORD
dwRead
=
0;
while(ReadFile(hStdoutR,
buf,
sizeof(buf),
dwRead,
NULL)
dwRead
!=
0){
printf(buf);
}
CloseHandle(hStdoutR);
D盘的test.php
?
echo
$_REQUEST["var"];
?
执行结果:
X-Powered-By:
PHP/5.3.1
Content-type:
text/html
Hello
VCKBASE!
实际上,C++调用其他CGI程序,例如PERL,方法也大同小异,如果你打算做一个自己的WEB服务器,调用CGI程序是少不了的。
PHP共享内存可以在单台服务器上进行进程间的数据通信和共享,但不能跨服务器,memcache和redis可专门独立部署做为内存服务器。
首先创建数据表,MySQL的SQL语句,CREATE TABLE `sess` ( `sesskey` varchar(32) NOT NULL default '', `expiry` bigint(20) NOT NULL default '0', `data` longtext NOT NULL, PRIMARY KEY (`sesskey`), KEY `expiry` (`expiry`) ) TYPE=MyISAM sesskey 为SESSION ID,expiry 为 SESSION 过期时间,data 用于保存 SESSION 数据。 默认情况下SESSION 数据是以文件方 式保存,想要使用数据库方式保存,就必 须重新定义SESSION 各个操作的处理函 数。PHP 提供了 session_set_save_handle() 函数,可以用此函数自定义SESSION 的处理过程,当然首先要先将 session.save_handler 改成user,可在 PHP 中进行设置:session_module_name('user');
linux下进程间通信的几种主要手段简介:
管道(Pipe)及有名管道(namedpipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列systemV消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和SystemV的变种都支持套接字。
实际上有一个非常简单的办法,你可以利用数据库操作的原子性来实现,不需要那么复杂的锁机制,甚至队列。就按你的方法来,假设任务数据表 task 里有两个字段 id, status,我们定义status三个状态
0: 待处理1: 正在处理2: 处理完成
假设你有一堆 PHP 进程都用如下 SQL 语句去取出数据库里的待处理任务
SELECT * FROM task WHERE status = 0
取出来以后,我们为了防止其他用户不再重复取出要把它的状态标记为 1
UPDATE task SET status = 1 WHERE id = xxx
但是等等,这样就会产生如你所说的资源抢夺,但如果加上一个简单的技巧就可以避免,你把语句变成这样
UPDATE task SET status = 1 WHERE id = xxx AND status = 0
熟悉一点数据库的人可能会说这样还是避免不了抢夺,只是避免了重复写入。
我要说的是,能避免重复写入就够了,我们的进程在执行完这条操作后,去获取 affected_rows ,即更新的条数,根据数据库的原子性,只有第一个抢占的进程才会返回 1,它可以进行后面的操作。而剩下返回 0 的进程,直接进入下一个等待流程即可。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流