Deprecated
: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in
/www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php
on line
1057
首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
26
篇与
的结果
2023-08-10
php session阻塞页面分析及优化 (session_write_close session_commit使用)
php session阻塞页面分析及优化 (session_write_close session_commit使用)这个问题很多做PHP开发朋友应该都有遇到过,一个启用了session_start 页面,由于执行时间过长。导致用户访问另外一个很简单的启用session_start页面一直阻塞着。 直到第一个页面执行完了。第二个页面才可以读取。这个就是,我们常说的,session阻塞机制。也就是说session是有锁的,为防止并发的写会话数据,php自带的的文件保存会话数据是加了一个互斥锁(在session_start()的时候)。程序执行session_start(),此时当前程序就开始持有锁。程序结束,此时程序自动释放Session的锁。如果同一个客户端同时并发发送多个请求(如ajax在页面同时发送多个请求),且脚本执行时间较长,就会导致session文件阻塞,影响性能。因为对于每个请求,PHP执行session_start(),就会取得文件独占锁,只有在该请求处理结束后,才会释放独占锁。这样,同时多个请求就会引起阻塞。我用file 存放用户sessionsession默认以文件保存,当一个用户访问session_start页面后,这个时候,就会默认创建一个包含session_id文件名,并且这个时候,会对文件进行锁定。如果这个用户点击链接,又访问一个该站session_start网页。这是,由于session_id一样,这个页面也有读取锁定该用户存放session文件。 由于,第一个页面没有执行完,它一直锁定了该文件。 第2个页面就不能获取锁,一直处于等待状态。这样一个看似小的问题,实际上,如果网站上面有大量用户访问,会导致session读取文件一直阻塞等待着。用户浏览器一直跟服务器保持连接,会消耗很多服务器资源。web服务器活跃连接数也会增大,可能很快就会耗费完连接资源,出现拒绝服务器。我用memcache 存放用户session用memcache保存用户session,相比读取文件有很大速度提升。而且可以做到多服务器共享session。确实很方便,这个时候,我们发现不会出现用文件保存session锁定清理。memcached读取时候,是共享的,不会出现等待。但是,我们会发现,memcached连接数,还是会保持着。并且,连接数会增加,如果这个时候,你设置的memcached连接数过小,你会发现,很快memcached就挂死了。 这也是,做memcache接管session时候,经常遇到问题。 有时候,web服务器很多,session(memcache)很少。发现memcache莫名其妙死掉,可能跟这个有关系。太多反映很慢的页面(启动session),会导致占用了大量memcached连接数。改变session使用习惯、优化调用方法其实,通过file或者session,如果处理耗时页面,都会带来服务器资源很大消耗。其实我们一般写入session或者读取时候,如果自己能够控制。用完了,就关闭掉文件锁,或者mem连接。就会自动释放资源,其实,php里面的:session_write_close,session_commit 函数就能做到改功能。我们看下下面代码执行过程:<?phpini_set('session.save_path', './tmp/');function open($save_path, $session_name) {echo __FUNCTION__,"<br/>"; return (true);}function close(){echo __FUNCTION__,"<br/>"; return (true);}function read($id){echo __FUNCTION__,"<br/>";}function write($id, $sess_data){echo __FUNCTION__,"<br/>"; return (true);}function destroy($id){echo __FUNCTION__,"<br />"; return(true);}function gc($maxlifetime){echo __FUNCTION__,"<br />"; return true; }session_set_save_handler("open", "close", "read", "write", "destroy", "gc");register_shutdown_function('test');function test(){ echo __FUNCTION__,"";}session_start();echo 'aaaaa',"";/*结论->session_start开启后, 会自动执行open,read函数。等页面执行完后,会执行shutdown函数.最后后会把session写入进去,然后执行close关闭文件从session_start 到页面结束,会一直锁定文件或者保持连接的。*/然后通过1个实例子来理解 , 先执行 session2.php 代码, 20秒内执行 session3.phpsession2.php 文件<?php//执行 session2.php和session3.php, /*因为 session2.php 脚本一直没有结束,结束后 session才会执行写入和关闭操作 (看session1.php 结论), session一直被锁定了因此执行session3.php 时会发现 一直处于阻塞状态。 */session_start();$_SESSION['uname'] = 'lily';//当有session写入时会阻塞sleep(20);/*//如果用以下代码 就没问题了, 立即提交 写入关闭session_start();$_SESSION['uname'] = 'lemon';session_commit();sleep(20);*/session3.php 文件<?phpsession_start();echo $_SESSION['uname'];总结://可以用 session_commit (别名 session_write_close) 立即执行写入关闭 /*session_start();$_SESSION['aaaa'] = 1000;session_commit(); //执行commit后,直接会调用,wirte,close操作*//*1.只读取session页面,建议打开后,就直接commit,这是$_SESSION变量已经生成了。2.有对session进行写入页面,建议修改完$_SESSION后,直接调用commit3.多次打开并且写入,这个不建议使用,比较打开文件,写入都是耗费时间的。如果能一次搞定的,就不要做多次了。 除非,中间执行很耗时的业务。后记:其实,使用完session,随手commit也不是坏事,养成习惯后。可以节省性能,减少服务器开销。是个不错选择!欢迎大家交流!*/
2023年08月10日
15 阅读
0 评论
0 点赞
2023-08-09
php巧用TCP长连接优化
php巧用TCP长连接优化一、面向人群如果你的站点架构满足以下几点,那么本文的优化方案会非常适合你:1)使用php等脚本语言作为开发语言2)需要连接后端服务,例如RPC服务、memcache或redis等3)流量非常大二、解决的问题常见的web架构如上:1)最前端是APP或者web页面2)服务器上层是web-server进行接入3)php脚本语言调用后端数据,完成业务逻辑,拼接页面4)最后端是服务、缓存、数据库我们都知道,php是一种脚本语言,不像C++/Java那样进程能够常驻,所以它连接后端的服务都是使用短连接:上图是一种典型场景,站点php部署在机器A上,缓存memcache部署在机器B上,之间通过短连接通信,过程为:1)php建立tcp短连接2)按照memcache协议发送数据3)接收memcache返回的数据4)php关闭tcp短连接在站点流量小时,上述过程没有任何问题,当站点流量非常大,QPS很高的情况下,php对memcache的tcp建立+关闭tcp短连接的开销便不能忽略了,有可能成为性能的瓶颈,如何进行优化是本文即将讨论的核心。三、UNIX Domain Socket技术介绍话锋一转,先一起来看看UNIX Domain Socket技术。UNIX Domain Socket是一种进程间IPC通讯机制,它不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。它可以用于同一台主机上两个没有亲缘关系的进程,并且是全双工的,提供可靠消息传递(消息不丢失、不重复、不错乱)的IPC机制。四、优化方案可以看到,UNIX Domain Socket的效率会远高于tcp短连接,但它只能用于同一台主机间的进程通讯,而我们的php应用和后端服务往往是部署在不同的机器上的,此时我们能否利用它来进行优化呢,答案是肯定的。优化后的简易架构图如上,我们在php应用服务器上部署一个local-proxy,php与local-proxy之间使用UNIX Domain Socket来通讯,而local-proxy与后端服务进行TCP长连接通讯,这样就大大提升了通讯效率,免除了每次请求都要进行的建立+关闭tcp短连接的开销。五、local-proxy要点要实现上述优化方案,local-proxy是实现要点,在实现local-proxy时,有这么几点需要注意1)协议设计:local-proxy本身没有任何业务逻辑,只负责请求转发,上游发送过来memcache协议,透传给后端的memchace,这样的话,上游客户端不需要进行任何代码的修改2)通讯方式:如上文所述,local-proxy与上游使用UNIX Domain Socket进行通讯,与下游使用tcp长连接进行通信3)高效框架:这种方案是为了解决tcp短连接的效率损耗,这样对local-proxy的效率要求就非常高,可以选用成熟高效的网络框架(例如libevent)和tcp长连接连接池技术来实现4)请求映射:需要将上游发过来的请求与发往下游的请求一一映射起来,这样才能正确的对应上请求包与响应包六、具体应用优酷内部的Memcached Agent项目已经应用了这种方案。
2023年08月09日
13 阅读
0 评论
0 点赞
2023-08-09
让PHP7达到最高性能的几个Tips
让PHP7达到最高性能的几个TipsPHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下.PHP7 VS PHP5.6Opcache记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, 所以之前测试时期就发生了有人一直没有启用Opcache的事情. 启用Opcache非常简单, 在php.ini配置文件中加入:zend_extension=opcache.soopcache.enable=1opcache.enable_cli=1"使用新的编译器使用新一点的编译器, 推荐GCC 4.8以上, 因为只有GCC 4.8以上PHP才会开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升(Wordpres的QPS角度衡量)其实GCC 4.8以前的版本也支持, 但是我们发现它支持的有Bug, 所以必须是4.8以上的版本才会开启这个特性.HugePage我之前的文章也介绍过: 让你的PHP7更快之Hugepage , 首先在系统中开启HugePages, 然后开启Opcache的huge_code_pages.以我的CentOS 6.5为例, 通过:$sudo sysctl vm.nr_hugepages=512分配512个预留的大页内存:$ cat /proc/meminfo | grep HugeAnonHugePages: 106496 kBHugePages_Total: 512HugePages_Free: 504HugePages_Rsvd: 27HugePages_Surp: 0Hugepagesize: 2048 kB然后在php.ini中加入:opcache.huge_code_pages=1这样一来, PHP会把自身的text段, 以及内存分配中的huge都采用大内存页来保存, 减少TLB miss, 从而提高性能.Opcache file cache开启Opcache File Cache(实验性), 通过开启这个, 我们可以让Opcache把opcode缓存缓存到外部文件中, 对于一些脚本, 会有很明显的性能提升.在php.ini中加入:opcache.file_cache=/tmp这样PHP就会在/tmp目录下Cache一些Opcode的二进制导出文件, 可以跨PHP生命周期存在.PGO我之前的文章: 让你的PHP7更快(GCC PGO) 也介绍过, 如果你的PHP是专门为一个项目服务, 比如只是为你的Wordpress, 或者drupal, 或者其他什么, 那么你就可以尝试通过PGO, 来提升PHP, 专门为你的这个项目提高性能.具体的, 以wordpress 4.1为优化场景.. 首先在编译PHP的时候首先:$ make prof-gen然后用你的项目训练PHP, 比如对于Wordpress:$ sapi/cgi/php-cgi -T 100 /home/huixinchen/local/www/htdocs/wordpress/index.php >/dev/null也就是让php-cgi跑100遍wordpress的首页, 从而生成一些在这个过程中的profile信息.最后:$ make prof-clean$ make prof-use && make install这个时候你编译得到的PHP7就是为你的项目量身打造的最高性能的编译版本.
2023年08月09日
13 阅读
0 评论
0 点赞
2023-08-07
PHP 安全与性能
PHP 安全与性能Apache mod_php / php-fpm目录权限安全1.1. 用户权限web server 启动用户不能于运行用户为同一个用户web server 运行用户与php程序不能为同一个用户root 1082 0.0 0.1 11484 2236 ? Ss Mar01 0:00 nginx: master process /usr/sbin/nginxwww-data 13650 0.0 0.0 11624 1648 ? S 09:44 0:00 nginx: worker processwww-data 13651 0.0 0.0 11624 1132 ? S 09:44 0:00 nginx: worker processwww-data 13652 0.0 0.0 11624 1132 ? S 09:44 0:00 nginx: worker processwww-data 13653 0.0 0.0 11624 1132 ? S 09:44 0:00 nginx: worker process父进程root 启动 web server, 此时web server 父进程应该是 root,同时父进程监听80端口子进程父进程派生许多子进程,同时使用setuid,setgid将子进程权限切换为非root子进程用户可以通过httpd.conf设置User nobodyGroup nobodynginx.conf$ cat /etc/nginx/nginx.confuser www-data;fastcgi 进程root 13082 0.0 0.1 19880 2584 ? Ss 09:28 0:00 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)www-data 13083 0.0 0.1 20168 3612 ? S 09:28 0:00 php-fpm: pool wwwwww-data 13084 0.0 0.1 20168 2808 ? S 09:28 0:00 php-fpm: pool wwwwww-data 13085 0.0 0.1 20168 2812 ? S 09:28 0:00 php-fpm: pool wwwwww-data 13086 0.0 0.1 20168 2812 ? S 09:28 0:00 php-fpm: pool wwwphp-fpm 于apache类似,都是root父进程,然后派生子进程,由于fastcgi 使用 9000 所有我们可以不使用root启动php-fpm现在我们开始讲解安全配置问题我们目的是避免用户通过漏洞提升权限,或者由于权限配置不当产生漏洞1.1.1. ApacheApache 案例Apache : rootApache 子进程 : nobodyHTDOCS 目录 : /var/www/var/www|--include|--image|--temp|--...很多人会将/var/www用户与组设置为 nobody:nogroup / nobody:nobody, 同时因为images会上传文件需要设置777, 很多书本于教程上面也是这样讲的, 这样配置会有什么问题呢?我们来分析一下:我们假设,一个用户上传一个文件到images目录,会有几种情况:上传一个.php文件,我们可以通过程序禁止上传.php文件我们上传一个.jpg文件,OK 通过了,通过某种手段将他重命名位.php扩展名的文件,然后通过http://www.example.com/images/your.php 运行它,your.php 可以做什么呢? 它可以查看所有文件,修改所有文件,创建其他php文件,去你可include目录下看config.php然后下载数据库。内部开发人员偷偷将一个程序植入到系统中,这个做code review 可以避免如何避免这样问题出现,有一个办法,我们新建一个用户www, webserver 进程是nobody,程序目录/var/www中的代码是www用户,nobody可能读取但不能修改。/var/www/images 目录所有者是nobody可以上传图片chown www /var/www/chown nobody /var/www/imagesfind /var/www/ -type d -exec chmod 555 {} \;find /var/www/ -type f -exec chmod 444 {} \;chmod 755 /var/www/images使所有可能目录允许运行.php文件,http://www.example.com/images/your.php 将被拒绝. include 也是同样处理方式,只允许使用include_once,require_one 包含,不允许http://www.example.com/include/your.php运行Order Deny,Allow Deny from all Order allow,deny Deny from all Order allow,deny Deny from all<Files *.php> Order allow,deny Deny from all </Files>1.1.2. Nginx / lighttpd + fastcgiNginx / lighttpd 案例分析nginx / lighttpd : rootweb server 子进程 : nobodyphp-fpm : rootphp-fpm 子进程 : nobodyHTDOCS 目录 : /var/www/var/www|--include|--image|--temp|--...fastcgi 遇到的问题与上面apache案例中遇到的问题类似,不同是的fastcgi把动态于静态完全分开了,这样更容易管理,我们可以这样入手nginx / lighttpd : rootweb server 子进程 : nobodyphp-fpm : rootphp-fpm 子进程 : wwwchown nobody /var/www/chown www /var/www/imagesfind /var/www/ -type d -exec chmod 555 {} \;find /var/www/ -type f -exec chmod 444 {} \;chmod 755 /var/www/images/var/www所有权限给nobody, images权限给www, 同时保证www用户可以读取/var/www下的程序文件location ~ ^/upload/.*.php${ deny all;}location ~ ^/static/images/.*.php${ deny all;}location ~ /include/.*.php$ {deny all;}location ~ .*.(sqlite|sq3)$ {deny all;}vim /etc/php5/fpm/pool.d/www.confuser = wwwgroup = www/etc/php5/fpm/pool.d/www.confchdir = /改为chdir = /var/wwwchroot可以彻底解决cd跳转问题,单配置比较繁琐chroot = /var/www这样当用户试图通过chdir跳转到/var/www以外的目录是,将被拒绝1.2. web server 版本信息Apache:ServerTokens ProductOnlyServerSignature OffNginx:server_tokens off;1.3. php_flag / php_admin_flag你在php.ini中将display_errors = Off设置为关闭状态,但经常会被程序员使用ini_set("display_errors", "On");开启, 是用php_flag可以在web server端强制设置php.ini参数php_flag register_globals offphp_flag magic_quotes_gpc offphp_admin_value(php_admin_flag) 与 php_value(php_flag) 有何不同?不同的地方是:php_admin_value(php_admin_flag) 命令只能用在apache的httpd.conf文件中, 而php_value(php_flag)则是用在.htacces在.htaccess中停用全局变量php_flag register_globals 0php_flag magic_quotes_gpc 0php_flag magic_quotes_runtime 01.4. 防止URL注入if ($request_uri ~* (.*)(insert|select|delete|update|count|concat|cost|union|drop|table|*|%|master|truncate|declare|'|;|and|or|(|)|exec)(.*)$ ) {return 403; }if ( $query_string ~ ".[;'<>].*" ){return 403;}php.ini2.1. Magic quotes限于5.2。x 版本magic_quotes_gpc = Onmagic_quotes_runtime = On测试程序 STR: <?phpif (get_magic_quotes_gpc()) {$str = $_POST['str']; echo '这里是get_magic_quotes_gpc()转义过后的:' ,$str, '<hr />';} else {$str = addslashes($_POST['str']); echo '现在通过addslashes传递过来的值是:' ,$_POST['str'], '<br>';}function stringFilter($str){if (ini_get('magic_quotes_gpc)') { return $str; } else { return addslashes($str); }}2.2. 危险PHP函数这些函数应该尽量避免使用它们exec, system, ini_alter, readlink, symlink, leak, proc_open, popepassthru, chroot, scandir, chgrp, chown, escapeshellcmd, escapeshellarg, shell_exec, proc_get_status, max_execution_time, opendir,readdir, chdir ,dir, unlink,delete,copy,rename对于后门植入主要是用下面几个方法eval, gzinflate, str_rot13, base64_decode针对目录与文件的函数disable_functions=chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir,rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown针对 php.ini 操作的函数ini_set,2.2.1. chdir()函数安全演示$ cat chdir.php 运行结果current:/wwwchdir:/Line #0 : root:x:0:0:root:/root:/bin/bashLine #1 : daemon:x:1:1:daemon:/usr/sbin:/bin/shLine #2 : bin:x:2:2:bin:/bin:/bin/shLine #3 : sys:x:3:3:sys:/dev:/bin/shLine #4 : sync:x:4:65534:sync:/bin:/bin/syncLine #5 : games:x:5:60:games:/usr/games:/bin/sh2.3. 隐藏PHP版本信息expose_php Off2.4. session名字可以泄露你的服务器采用php技术session.name = PHPSESSID伪装成Tomcatsession.name = JSESSIONID2.5. 隐藏PHP出错信息display_errors = Off同时开启error_log日志error_log = php_errors.log2.6. open_basedir 防止操作web环境意外文件目录open_basedir = /www/:/tmp/测试脚本<?phpchdir('/etc');printf(file('/etc/fstab'));实际效果Warning: chdir(): open_basedir restriction in effect. File(/etc) is not within the allowed path(s): (/www/:/tmp/) in /www/index.php on line 2Warning: file(): open_basedir restriction in effect. File(/etc/fstab) is not within the allowed path(s): (/www/:/tmp/) in /www/index.php on line 2Warning: file(/etc/fstab): failed to open stream: Operation not permitted in /www/index.php on line 2开发于安全3.1. 彻底解决目录于文件的安全选择一个MVC开发框架,它们的目录结构一般是这样的:/www/www/htdocs/index.php htdocs目录下只有一个index.php文件,他是MVC/HMVC框架入口文件/www/htdocs/static 这里防止静态文件/www/app/ 这里放置php文件然后放行index.php文件,在URL上不允许请求任何其他php文件,并返回404错误3.2. Session / Cookie安全session.save_path 默认session 存储在/tmp, 并且一明文的方式将变量存储在以sess_为前缀的文件中$ cat session.php<?phpsession_start();if(isset($_SESSION['views'])) $_SESSION['views']=$_SESSION['views']+1;else $_SESSION['views']=1;echo "Views=". $_SESSION['views'];?>http://www.example.com/session.php 我们刷新几次再看看sess_文件中的变化$ cat /tmp/sess_d837a05b472390cd6089fc8895234d1aviews|i:3;经过侧记你可以看到session文件中存储的是明文数据,所以不要将敏感数据放到Session中,如果必须这样作。建议你加密存储的数据有一个办法比较好,就是封装一下session.不再采用$_SESSION方式调用Class Encrype{}Class Session extend Encrype {function set($key,$value,$salt){ $value = Encrype($value) $_SESSION[$key] = $value } function get($key){ return $_SESSION[$key] }}Class Cookie extend Encrype {function set($key,$value,$salt){ $value = Encrype($value) $_COOKIE[$key] = $value } function get($key){ return $_COOKIE[$key] }}Cookiecookie 也需要作同样的处理,上面代码仅供参考,未做过运行测试3.3. 注入安全3.3.1. 禁止输出调试信息error_reporting(0);3.3.2. 预防SQL注入攻击SQL 注入<?php$mysql_server_name="172.16.0.4"; $mysql_username="dbuser"; $mysql_password="dbpass"; $mysql_database="dbname"; $conn=mysql_connect($mysql_server_name, $mysql_username, $mysql_password); $strsql=""; if($_GET['id']){ $strsql="select * from `order` where id=".$_GET['id']; }else{ $strsql="select * from `order` limit 100"; } echo $strsql; $result=@mysql_db_query($mysql_database, $strsql, $conn); $row=mysql_fetch_row($result); echo '<font face="verdana">'; echo '<table border="1" cellpadding="1" cellspacing="2">'; echo "\n<tr>\n"; for ($i=0; $i<mysql_num_fields($result); $i++) { echo '<td bgcolor="#000F00"><b>'. mysql_field_name($result, $i); echo "</b></td>\n"; } echo "</tr>\n"; mysql_data_seek($result, 0); while ($row=mysql_fetch_row($result)) { echo "<tr>\n"; for ($i=0; $i<mysql_num_fields($result); $i++ ) { echo '<td bgcolor="#00FF00">'; echo "$row[$i]"; echo '</td>'; } echo "</tr>\n"; } echo "</table>\n"; echo "</font>"; mysql_free_result($result); mysql_close(); mysql_real_escape_string() / mysqli_real_escape_string() 可以转义 SQL 语句中使用的字符串中的特殊字符$username = mysqli_real_escape_string( $GET['username'] );mysql_query( “SELECT * FROM tbl_employee WHERE username = ’”.$username.“‘”);<?php// 转义用户名和密码,以便在 SQL 中使用$user = mysql_real_escape_string($user);$pass = mysql_real_escape_string($pass);$sql = "SELECT * FROM users WHERE user='" . $user . "' AND password='" . $pwd . "'"// 更多代码?>3.3.3. SHELL 命令注入SHELL 命令注入, 原理是PHP中``符号或者system,exec等等函数会执行系统命令。<?phpsystem("iconv -f ".$_GET['from']." -t ".$_GET['from']." ".$_GET['file'])<?php$c=urldecode($_GET['c']);if($c){$c;}示例:http://www.example.com/file.php?c=echo%20helloworld>test.txt!$_GET['c']||{$_GET['c']};执行效率如果是web应用程序,通常我们必须将执行时间控制在30秒以内, 10秒最佳. 否则用户是没有耐心等待你的网站打开.4.1. timeout下面的流程展示了从用户打开浏览器到页面展示出来的整个流程, 每个流程都可能出现 timeoutuser -> dns -> web server -> app server -> cache -> database严格限制运行时间外部引用域名必须写入hosts文件, 防止解析时间过长必须设置严格的超时策略, 方式程序长时间等待不退出, 占用系统资源<?php$ctx = stream_context_create(array( 'http' => array( 'timeout' => 1 //设置一个超时时间,单位为秒 )));file_get_contents("http://example.com/file.ext", false, $ctx);?><?php$ctx = stream_context_create(array( 'http' => array( 'method' => 'GET', 'header' => 'Accept-Encoding: gzip, deflate', 'timeout' => 1 )));$html = file_get_contents("http://www.163.com/", false, $ctx);echo strlen($html);?>4.1.1. mysqlshow variables like '%timeout%'4.2. 浏览器上传文件尺寸控制Nginxclient_max_body_size 8M设置不能过大,因为可以通过你的网站上传功能,持续上传实现攻击。
2023年08月07日
15 阅读
0 评论
0 点赞
2023-08-07
PHP性能优化技巧【译】
PHP性能优化技巧【译】今天在逛微博的时候看到了别人转的一篇谷歌的的文章《PHP performance tips》,看了觉得很有用,于是就翻译保存下来。概括出你的代码的瓶颈所在当你尝试让你的网站更快的时候,你需要记住Hoare的名言:不成熟的优化是万恶之源。在你修改你的代码之前,你需要明确是什么造成了网站运行的慢。更新你的PHP版本这些年,PHP开发团队为PHP引擎做了很多重大的性能的提升。如果你的服务器上还是运行的比较老的PHP版本(比如PHP3 或者 PHP4)的话,那在你优化你的代码之前你需要先升级你的PHP版本Migrating from PHP 4 to PHP 5.0.xMigrating from PHP 5.0.x to PHP 5.1.xMigrating from PHP 5.1.x to PHP 5.2.x使用缓存使用类似Memcache或者Smarty这样支持缓存的模板引擎的缓存模块,通过缓存数据库中数据或者已经渲染好的页面的方法可以提高网站的性能。使用输出缓冲PHP使用内存缓冲区来保存脚本要输出的所有的数据。由于缓存区必须被填满之后才会将数据发送给用户,所以你的页面看上去会比较慢Output Buffering Control尽量避免使用setter和getter当使用PHP的类的时候,直接使用类中的属性比使用setter和getter可以节省编码时间,也能让你的脚本的运行速度更快。在下面的例子中,dog类中使用setName()和getName()方法来访问name属性:class dog { public $name = ''; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }注意,在这里setName和getName除了存储和返回name的值,其他什么也不做。$rover = new dog(); $rover->setName('rover'); echo $rover->getName();直接设置和调用name属性可以让运行效率提升一倍,也能减少我们的开发时间。$rover = new dog(); $rover->name = 'rover'; echo $rover->name;不要随便就复制变量有时候为了使 PHP 代码更加整洁,一些 PHP 新手(包括我)会把预定义好的变量复制到一个名字更简短的变量中,其实这样做的结果是增加了一倍的内存消耗,只会使程序更加慢。试想一下,在 下面的例子中,如果用户恶意插入 512KB 字节的文字到文本输入框中,这样就会导致 1MB 的内存被消耗!BAD:$description = $_POST['description']; echo $description;GOOD:echo $_POST['description'];对字符串使用单引号PHP 引擎允许使用单引号和双引号来封装字符串变量,但是这个是有很大的差别的!使用双引号的字符串告诉 PHP 引擎首先去读取字符串内容,查找其中的变量,并改为变量对应的值。一般来说字 符串是没有变量的,所以使用双引号会导致性能不佳。最好是使用字符串连接而不是双引号字符串。BAD:$output = "This is a plain string";GOOD:$output = 'This is a plain string';GOOD经过测试并不是原文上所说的那样,所以加以改正:$type = "mixed"; $output = "This is a $type string";BAD:$type = 'mixed'; $output = 'This is a ' . $type .' string';使用 echo 函数来输出字符串使用 echo() 函数来打印结果出了有更容易阅读之外,在下个例子中,你还可以看到有更好的性能。BAD:print($myVariable);GOOD:echo $myVariable;不要在 echo 中使用连接符很多 PHP 程序员(有包括我)不知道在用 echo 输出多个变量的时候,其实可以使用逗号来分开的,而不必用字符串先把他们先连起来,如下面的第一个例子中,由于使用了连接符就会有性能问题,因为这样就会需要 PHP 引擎首先把所有的变量连接起来,然后在输出,而在第二个例子中,PHP 引擎就会按照循序输出他们。BAD:echo 'Hello, my name is' . $firstName . $lastName . ' and I live in ' . $city;GOOD:echo 'Hello, my name is' , $firstName , $lastName , ' and I live in ' , $city;使用 switch/case 代替 if/else对于只有单个变量的判断,使用 switch/case 语句而不是 if/else 语句,会有更好的性能,并且代码更加容易阅读和维护。BAD:if($_POST['action'] == 'add') { addUser(); } elseif ($_POST['action'] == 'delete') { deleteUser(); } elseif ($_POST['action'] == 'edit') { editUser(); } else { defaultAction(); }GOOD:switch($_POST['action']) { case 'add': addUser(); break; case 'delete': deleteUser(); break; case 'edit': editUser(); break; default: defaultAction(); break; }避免在循环里面执行sql一个很常见的问题就是在循环里面执行sql。这样多次连接并从数据库得到数据会显著的将脚本运行速度变慢。在下面的例子中,你可以改变之前的循环执行,将SQL改造成一条单独的sql然后一次性插入你的所有数据。foreach ($userList as $user) { $query = 'INSERT INTO users (first_name,last_name) VALUES("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; mysql_query($query); }插入语句:INSERT INTO users (first_name,last_name) VALUES("John", "Doe")代替使用循环,可以将所有的数据组合进一条单独的sql中并执行。$userData = array(); foreach ($userList as $user) { $userData[] = '("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; } $query = 'INSERT INTO users (first_name,last_name) VALUES' . implode(',', $userData); mysql_query($query);插入语句:INSERT INTO users (first_name,last_name) VALUES("John", "Doe"),("Jane", "Doe")...自己第一次翻译,英语比较差,所以练习一下,也增进自己的自己,好记性不如烂笔头嘛。
2023年08月07日
13 阅读
0 评论
0 点赞
1
...
4
5
6