假设Linux系统中有一个文件名叫“-ee”,如果我们想对它进行操作,例如要删除它,按照一般的删除方法在命令行中输入rm -ee命令,界面会提示我们是“无效选项”(invalid option),原来由于文件名的第一个字符为“-”,Linux把文件名当作选项了,我们可以使用“--”符号来解决这个问题,输入“rm -- -ee”命令便可顺利删除名为“-ee”的文件。如果是其他特殊字符的话可以在特殊字符前加一个“”符号,或者用双引号把整个文件名括起来。
下面是我同事碰到的一个文件夹:
ls -lart
-d //文件夹名称
删除方法:rm -- -d 就可以删除!
ls -lart
-d //文件夹名称
删除方法:rm -- -d 就可以删除!
Apache配置文件 httpd.conf:
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
AddType application/x-httpd-php-source .phps
php做一个图片上传的页面:用 input type=”file” 进行文件上传,然后$_FILES接收上传的文件进行处理。结果发现由于浏览器的不同在$_FILES[inputname][type]中获取的图片类型也不同。
经过多次测试,问题终于解决了。原因是ie会把 jpg、jpeg翻译成image/pjpeg,png翻译成image/x-png 。而火狐则很标准:jpg、jpeg翻译成image/jpeg,png翻译成image/png。
为了避免这个问题,我在多个浏览器上做了测试,结果如下:
firefox image/jpeg image/bmp image/gif image/png
ie 6 image/pjpeg image/bmp image/gif image/x-png
ie 7 image/pjpeg image/bmp image/gif image/x-png
ie 8 image/pjpeg image/bmp image/gif image/x-png
附 PHP 的全局数组 $_FILES的内容:
* $_FILES["file"]["name"] – 被上传文件的名称
* $_FILES["file"]["type"] – 被上传文件的类型
* $_FILES["file"]["size"] – 被上传文件的大小,以字节计
* $_FILES["file"]["tmp_name"] – 存储在服务器的文件的临时副本的名称
* $_FILES["file"]["error"] – 由文件上传导致的错误代码
使用时form要添加 enctype规定了在提交表单时要使用哪种内容类型如:enctype=”multipart/form-data”。
兼容:
没有conf文件结尾的,在Firefox下是这样的类型:
[name] => httpd.conf
[type] => application/octet-stream
而在IE下:
下面归纳了大部分上传图片的类型,而这种问题可以通过查询下面的返回类型来解决:
阅读全文
经过多次测试,问题终于解决了。原因是ie会把 jpg、jpeg翻译成image/pjpeg,png翻译成image/x-png 。而火狐则很标准:jpg、jpeg翻译成image/jpeg,png翻译成image/png。
为了避免这个问题,我在多个浏览器上做了测试,结果如下:
firefox image/jpeg image/bmp image/gif image/png
ie 6 image/pjpeg image/bmp image/gif image/x-png
ie 7 image/pjpeg image/bmp image/gif image/x-png
ie 8 image/pjpeg image/bmp image/gif image/x-png
附 PHP 的全局数组 $_FILES的内容:
* $_FILES["file"]["name"] – 被上传文件的名称
* $_FILES["file"]["type"] – 被上传文件的类型
* $_FILES["file"]["size"] – 被上传文件的大小,以字节计
* $_FILES["file"]["tmp_name"] – 存储在服务器的文件的临时副本的名称
* $_FILES["file"]["error"] – 由文件上传导致的错误代码
使用时form要添加 enctype规定了在提交表单时要使用哪种内容类型如:enctype=”multipart/form-data”。
兼容:
$typeMap = array ('image/gif' => 'gif', 'image/jpeg' => 'jpg', 'image/png' => 'png','image/pjpeg'=>'jpg');
没有conf文件结尾的,在Firefox下是这样的类型:
[name] => httpd.conf
[type] => application/octet-stream
而在IE下:
下面归纳了大部分上传图片的类型,而这种问题可以通过查询下面的返回类型来解决:
阅读全文
IE6下没有用:
修改为:
OK!
<a href="url.php">
<input type="button" name="Submit" value=" " class="applybut" />
</a>
无法跳转到url.php!<input type="button" name="Submit" value=" " class="applybut" />
</a>
修改为:
<input type="button" name="Submit" value=" " class="applybut" onclick="javascript:location.href='/2010expo/c/user/regform'" />
OK!
g++ test.cpp -I/usr/local/rudiments/include -L/usr/local/rudiments/lib/ -lrudiments
test.cpp
刚一运行a.out奶奶的报错:难怪sqlrelay老是很多麻烦,呵呵
解决步骤:
1、vi /etc/ld.so.conf.d/fuse.conf (新增一个文件)
写入:/usr/local/rudiments/lib( librudiments-0.32.so.1所在位置)
2、ldconfig(重新载入系统)
[root@localhost sqlrelay]# ./a.out
17526: child looping...
17525: parent looping...
[root@localhost sqlrelay]# 17526: child looping...
大功告成!
这样指定也可以:
更多相关编程,参考如下网站:
来源:
http://rudiments.sourceforge.net/rudiments/programming/baseclasses.html#daemon
test.cpp
// Copyright (c) 2001 David Muse
// See the file COPYING for more information
#include <rudiments/daemonprocess.h>
#include <rudiments/permissions.h>
#include <rudiments/process.h>
#include <rudiments/file.h>
#include <rudiments/snooze.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#ifdef RUDIMENTS_NAMESPACE
using namespace rudiments;
#endif
daemonprocess *dmn;
// define a function to shut down the process cleanly
RETSIGTYPE shutDown() {
printf("%d: shutting down\n",process::getProcessId());
// clean up
delete dmn;
file::remove("/tmp/dmn.pidfile");
exit(0);
}
int main(int argc, const char **argv) {
dmn=new daemonprocess();
// set up signal handlers for clean shutdown
dmn->handleShutDown((RETSIGTYPE *)shutDown);
dmn->handleCrash((RETSIGTYPE *)shutDown);
// change the user/group that the daemon is running as
dmn->runAsUser("nobody");
dmn->runAsGroup("nobody");
// make sure that only one instance is running
int pid=dmn->checkForPidFile("/tmp/dmn.pidfile");
if (pid>-1) {
printf("Sorry, an instance of this daemon is already running with process id: %d\n",pid);
delete dmn;
exit(0);
}
// detach from the controlling terminal
dmn->detach();
// create a pid file which is used to make sure that only one instance
// is running and can also be used to kill the process
dmn->createPidFile("/tmp/dmn.pidfile",permissions::ownerReadWrite());
if (!fork()) {
for (;;) {
printf("%d: child looping...\n",
process::getProcessId());
snooze::macrosnooze(1);
}
}
// loop, printing "looping..." once per second
for (;;) {
printf("%d: parent looping...\n",
process::getProcessId());
snooze::macrosnooze(1);
}
}
// See the file COPYING for more information
#include <rudiments/daemonprocess.h>
#include <rudiments/permissions.h>
#include <rudiments/process.h>
#include <rudiments/file.h>
#include <rudiments/snooze.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#ifdef RUDIMENTS_NAMESPACE
using namespace rudiments;
#endif
daemonprocess *dmn;
// define a function to shut down the process cleanly
RETSIGTYPE shutDown() {
printf("%d: shutting down\n",process::getProcessId());
// clean up
delete dmn;
file::remove("/tmp/dmn.pidfile");
exit(0);
}
int main(int argc, const char **argv) {
dmn=new daemonprocess();
// set up signal handlers for clean shutdown
dmn->handleShutDown((RETSIGTYPE *)shutDown);
dmn->handleCrash((RETSIGTYPE *)shutDown);
// change the user/group that the daemon is running as
dmn->runAsUser("nobody");
dmn->runAsGroup("nobody");
// make sure that only one instance is running
int pid=dmn->checkForPidFile("/tmp/dmn.pidfile");
if (pid>-1) {
printf("Sorry, an instance of this daemon is already running with process id: %d\n",pid);
delete dmn;
exit(0);
}
// detach from the controlling terminal
dmn->detach();
// create a pid file which is used to make sure that only one instance
// is running and can also be used to kill the process
dmn->createPidFile("/tmp/dmn.pidfile",permissions::ownerReadWrite());
if (!fork()) {
for (;;) {
printf("%d: child looping...\n",
process::getProcessId());
snooze::macrosnooze(1);
}
}
// loop, printing "looping..." once per second
for (;;) {
printf("%d: parent looping...\n",
process::getProcessId());
snooze::macrosnooze(1);
}
}
刚一运行a.out奶奶的报错:难怪sqlrelay老是很多麻烦,呵呵
[root@localhost sqlrelay]# ./a.out
./a.out: error while loading shared libraries: librudiments-0.32.so.1: cannot open shared object file: No such file or directory
./a.out: error while loading shared libraries: librudiments-0.32.so.1: cannot open shared object file: No such file or directory
解决步骤:
1、vi /etc/ld.so.conf.d/fuse.conf (新增一个文件)
写入:/usr/local/rudiments/lib( librudiments-0.32.so.1所在位置)
2、ldconfig(重新载入系统)
[root@localhost sqlrelay]# ./a.out
17526: child looping...
17525: parent looping...
[root@localhost sqlrelay]# 17526: child looping...
大功告成!
这样指定也可以:
g++ test.cpp -I/usr/local/rudiments/include/ -L/usr/local/rudiments/lib -lrudiments
更多相关编程,参考如下网站:
来源:
http://rudiments.sourceforge.net/rudiments/programming/baseclasses.html#daemon
我个人认为是有五个指头握成一个拳头,这五个指头是:
1.用户体验,快速迭代
2.数据挖掘是重武器?数据为王
3.重事实,看观点,商业与我如浮云烟
4.低调的华丽,意境方能高远
5.人才储备加公司文化的厚积薄发
-----------------------------------------------------------------------------------------
接下来我来抄袭别人的评论,别笑,我只是觉得好玩,点穴确实也很到位!
转载:我就喜欢转,一直在抄袭,一直喜欢模仿,哈哈!
腾讯和淘宝,是国内目前it公司两家有领头位置的企业,但是特性却很奇怪,截然不同
1.淘宝是Java路线,腾讯是C++路线
2.腾讯的马化腾是技术出身,精于技术;本身就是个技术大牛,但是又不会沉迷于脱离用户的技术,懂得把技术转换为生产力
淘宝的马云是非技术出身,完全不懂技术,也不屑于懂技术,成功的三因素之一,还是不懂技术。他是个很好的商人。
3.腾讯的软件基因更多,淘宝的互联网基因更多
4.淘宝更加的开放,腾讯相对的封闭,成因和技术路线有关,淘宝的技术平台,本来就是在开源基础上的,而腾讯,基本上是自主开发的。
腾讯的技术,基本上是以马化腾为领头羊的,从那篇文章就看出了,他决定了整个公司的技术文化,而在这个基础上,才形成了其它文化。
淘宝的文化,是以马云为核心的,具体哪个是马化腾角色的,左右整个公司的技术风格的,作为外人尚不可知。但是可以知道的是,这个风格是受马云的影响很深的。
这两家最大的公司,也许将来会分庭抗礼。但是更好的结局,不是你死我活,而是双赢,这样对中国的总体IT和技术水平,才能有更好的提高。
来源:http://www.dbanotes.net/review/tencent.html
1.用户体验,快速迭代
2.数据挖掘是重武器?数据为王
3.重事实,看观点,商业与我如浮云烟
4.低调的华丽,意境方能高远
5.人才储备加公司文化的厚积薄发
-----------------------------------------------------------------------------------------
接下来我来抄袭别人的评论,别笑,我只是觉得好玩,点穴确实也很到位!
转载:我就喜欢转,一直在抄袭,一直喜欢模仿,哈哈!
腾讯和淘宝,是国内目前it公司两家有领头位置的企业,但是特性却很奇怪,截然不同
1.淘宝是Java路线,腾讯是C++路线
2.腾讯的马化腾是技术出身,精于技术;本身就是个技术大牛,但是又不会沉迷于脱离用户的技术,懂得把技术转换为生产力
淘宝的马云是非技术出身,完全不懂技术,也不屑于懂技术,成功的三因素之一,还是不懂技术。他是个很好的商人。
3.腾讯的软件基因更多,淘宝的互联网基因更多
4.淘宝更加的开放,腾讯相对的封闭,成因和技术路线有关,淘宝的技术平台,本来就是在开源基础上的,而腾讯,基本上是自主开发的。
腾讯的技术,基本上是以马化腾为领头羊的,从那篇文章就看出了,他决定了整个公司的技术文化,而在这个基础上,才形成了其它文化。
淘宝的文化,是以马云为核心的,具体哪个是马化腾角色的,左右整个公司的技术风格的,作为外人尚不可知。但是可以知道的是,这个风格是受马云的影响很深的。
这两家最大的公司,也许将来会分庭抗礼。但是更好的结局,不是你死我活,而是双赢,这样对中国的总体IT和技术水平,才能有更好的提高。
来源:http://www.dbanotes.net/review/tencent.html
sqlrelay 效率 xml配置
看到有朋友讨论如何提高命中率,那么我也来分享下我的经验吧
缓存命中
1.缓存时间设置,顾名思义,缓存时间设置的越长那么命中率也会相对较高。
缓存与更新是一对矛盾的概念,既要做到高命中又要做到快速更新这个就需要自己对自己网站内容的了解然后指定合适的缓存策略。
2.缓存能缓存的内容,什么是能缓存的内容呢?我认为所有用户访问都是一样的,这种文件都可以缓存,除了时间等实时变化内容。例如有些动态文件实际上也可以缓存,另外还有些特殊类型的url也可以缓存如 "http://abc.com/aa.swf?=参数" 等类似的url,忽略掉参数缓存成一份文件。
3.注意vary头部,一般来说我们配置了vary:accept-econding。实际上这样会缓存四五份文件,每一种用户请求头中的accept-econding都会使squid缓存一份文件。各个浏览器的请求头部格式不一样,因此缓存的份数也不一样。那么例如有的网站配置了vary:uesr-agent,那就悲剧了。
4.URL-Hash能够提高多台缓存服务器集群情况下的命中,使每台机器上都缓存不一样的文件,提高存储利用率和命中率。
用户命中
实际上不仅CDN架构会有命中的概念,用户浏览器也会对网页文件进行缓存,提高用户cached也很重要。
1. 设置有效时间;在能缓存的文件HTTP头部添加expire头部或max-age头部,不要小看这个配置,这个配置能为你的网站节省大量的流量,在用户行为里经常会使用浏览器前进或后退功能,如果没有添加这些头部会产生一个验证请求到上游服务器,添加了浏览器验证是在有效时间内则直接调用浏览器缓存。
2.源站命中
文件更新验证;为什么我们刷新网站一般都会比第一次打开网站快的多?浏览器知道我们是经常请求重复文件,会有一个验证机制,如果超过了浏览器缓存时间或点击刷新都会产生很多验证请求。验证请求中最主要的就是if-modify-since和if-none-match头部,对应的是响应文件的Last-modify和Etag头部
如果说只有单一的源站这些可能都不是问题,如果有多台源端服务器,那么last-modify时间可能会是不一样的即使文件内容一样。此时源站可以通过URL Hash或仅使用Etag来作为文件验证的标准。
既然说到Etag,那就再提两句。Etag主要解决文件验证的单一性,如果你的Etag标签里是按照时间戳生成的那就悲剧了。一般情况下web服务器会同时验证last-modify和Etag,只有两个条件都满足才会返回304状态码。
来源:http://www.linuxtone.org/html/61/t-5961.html
缓存命中
1.缓存时间设置,顾名思义,缓存时间设置的越长那么命中率也会相对较高。
缓存与更新是一对矛盾的概念,既要做到高命中又要做到快速更新这个就需要自己对自己网站内容的了解然后指定合适的缓存策略。
2.缓存能缓存的内容,什么是能缓存的内容呢?我认为所有用户访问都是一样的,这种文件都可以缓存,除了时间等实时变化内容。例如有些动态文件实际上也可以缓存,另外还有些特殊类型的url也可以缓存如 "http://abc.com/aa.swf?=参数" 等类似的url,忽略掉参数缓存成一份文件。
3.注意vary头部,一般来说我们配置了vary:accept-econding。实际上这样会缓存四五份文件,每一种用户请求头中的accept-econding都会使squid缓存一份文件。各个浏览器的请求头部格式不一样,因此缓存的份数也不一样。那么例如有的网站配置了vary:uesr-agent,那就悲剧了。
4.URL-Hash能够提高多台缓存服务器集群情况下的命中,使每台机器上都缓存不一样的文件,提高存储利用率和命中率。
用户命中
实际上不仅CDN架构会有命中的概念,用户浏览器也会对网页文件进行缓存,提高用户cached也很重要。
1. 设置有效时间;在能缓存的文件HTTP头部添加expire头部或max-age头部,不要小看这个配置,这个配置能为你的网站节省大量的流量,在用户行为里经常会使用浏览器前进或后退功能,如果没有添加这些头部会产生一个验证请求到上游服务器,添加了浏览器验证是在有效时间内则直接调用浏览器缓存。
2.源站命中
文件更新验证;为什么我们刷新网站一般都会比第一次打开网站快的多?浏览器知道我们是经常请求重复文件,会有一个验证机制,如果超过了浏览器缓存时间或点击刷新都会产生很多验证请求。验证请求中最主要的就是if-modify-since和if-none-match头部,对应的是响应文件的Last-modify和Etag头部
如果说只有单一的源站这些可能都不是问题,如果有多台源端服务器,那么last-modify时间可能会是不一样的即使文件内容一样。此时源站可以通过URL Hash或仅使用Etag来作为文件验证的标准。
既然说到Etag,那就再提两句。Etag主要解决文件验证的单一性,如果你的Etag标签里是按照时间戳生成的那就悲剧了。一般情况下web服务器会同时验证last-modify和Etag,只有两个条件都满足才会返回304状态码。
来源:http://www.linuxtone.org/html/61/t-5961.html
域名(首页):
www.qiyi.com
CODE:
[root@s1 ~]# curl -I www.qiyi.com
HTTP/1.1 200 OK
Server: nginx //哥也喜欢nginx,他实在太猛了!(不过看着是像用nginx做反向代理,后端可能是apache或者其它http server)
Date: Mon, 26 Apr 2010 07:37:23 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Expires: Mon, 26 Apr 2010 07:41:43 GMT
Cache-Control: max-age=300
ETag: "4212873865" (//哥开启etag了,这个东西是开放好还是关闭好?讨论问题比较多)
Last-Modified: Sun, 25 Apr 2010 14:03:57 GMT
Content-Length: 35430[root@s1 ~]# dig www.qiyi.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> www.qiyi.com +trace
;; global options: printcmd
。。。。。
。。。。。
www.qiyi.com. 3600 IN A 220.181.73.5 //哥用的是DNS轮询
www.qiyi.com. 3600 IN A 220.181.73.6
qiyi.com. 900 IN NS ns2.qiyi.com.
qiyi.com. 900 IN NS ns1.qiyi.com.
;; Received 130 bytes from 202.108.14.6#53(ns1.qiyi.com) in 49 ms域名(静态文件,CSS/JS)
static.qiyi.com
[root@s1 ~]# curl -I http://static.qiyi.com/vrs/top/phb_dianying_day_50.js
CODE:
HTTP/1.1 200 OK
Server: nginx //
Date: Mon, 26 Apr 2010 07:42:28 GMT
Content-Type: text/javascript
Connection: keep-alive
Expires: Mon, 26 Apr 2010 08:16:54 GMT
Cache-Control: max-age=3600 //过期时间
ETag: "4030706110" //
Last-Modified: Sun, 25 Apr 2010 18:01:02 GMT //哥带宽比较富裕,目前不考虑gzip压缩?
Content-Length: 24970
Accept-Ranges: bytes[root@s1 ~]# dig static.qiyi.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> static.qiyi.com +trace
。。。。。。。
。。。。。。。
static.qiyi.com. 3600 IN A 220.181.73.6 //哥依旧喜欢dns轮询
static.qiyi.com. 3600 IN A 220.181.73.5
qiyi.com. 900 IN NS ns2.qiyi.com.
qiyi.com. 900 IN NS ns1.qiyi.com.域名(图片)
[root@s1 ~]# curl -I
CODE:
HTTP/1.1 200 OK
Server: nginx/0.8.34
Date: Mon, 26 Apr 2010 08:45:18 GMT
Content-Type: image/jpeg
Connection: keep-alive
Expires: Fri, 21 May 2010 16:37:51 GMT
Cache-Control: max-age=2592000
ETag: "114431829"
Last-Modified: Mon, 05 Apr 2010 10:27:06 GMT
Content-Length: 7628
Accept-Ranges: bytes[root@s1 ~]# dig www.qiyipic.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> www.qiyipic.com +trace
。。。。。。。。
。。。。。。。。
www.qiyipic.com. 3600 IN A 202.108.14.16 // 哥对DNS轮询情有独钟!
www.qiyipic.com. 3600 IN A 202.108.14.15综述:
1.奇艺视频网站按业务类型域名分类(不用说,现在中小型网站都这样做)
好处:一个好处容易区分业务;一个好处是可以减少读取cookie对图片服务器的压力和提高安全性,避免cookie泄露
2.采用DNS轮询
好处:架构之初,简单方便,我相信奇艺运维人员还会做很多工作。
3.HTTP Server
采用nginx做反向代理,nginx反向代理还是强劲不用说:)后端感觉到是像apache
4.gzip
没有对任何文件进行压缩,不知道为什么?哥有钱?
etag (到底要还是不要,应该如何优化?)
5.....
6... //待论坛里的哥哥们继续分析研究!
来源:http://www.linuxtone.org/html/34/t-5934.html
www.qiyi.com
CODE:
[root@s1 ~]# curl -I www.qiyi.com
HTTP/1.1 200 OK
Server: nginx //哥也喜欢nginx,他实在太猛了!(不过看着是像用nginx做反向代理,后端可能是apache或者其它http server)
Date: Mon, 26 Apr 2010 07:37:23 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Expires: Mon, 26 Apr 2010 07:41:43 GMT
Cache-Control: max-age=300
ETag: "4212873865" (//哥开启etag了,这个东西是开放好还是关闭好?讨论问题比较多)
Last-Modified: Sun, 25 Apr 2010 14:03:57 GMT
Content-Length: 35430[root@s1 ~]# dig www.qiyi.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> www.qiyi.com +trace
;; global options: printcmd
。。。。。
。。。。。
www.qiyi.com. 3600 IN A 220.181.73.5 //哥用的是DNS轮询
www.qiyi.com. 3600 IN A 220.181.73.6
qiyi.com. 900 IN NS ns2.qiyi.com.
qiyi.com. 900 IN NS ns1.qiyi.com.
;; Received 130 bytes from 202.108.14.6#53(ns1.qiyi.com) in 49 ms域名(静态文件,CSS/JS)
static.qiyi.com
[root@s1 ~]# curl -I http://static.qiyi.com/vrs/top/phb_dianying_day_50.js
CODE:
HTTP/1.1 200 OK
Server: nginx //
Date: Mon, 26 Apr 2010 07:42:28 GMT
Content-Type: text/javascript
Connection: keep-alive
Expires: Mon, 26 Apr 2010 08:16:54 GMT
Cache-Control: max-age=3600 //过期时间
ETag: "4030706110" //
Last-Modified: Sun, 25 Apr 2010 18:01:02 GMT //哥带宽比较富裕,目前不考虑gzip压缩?
Content-Length: 24970
Accept-Ranges: bytes[root@s1 ~]# dig static.qiyi.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> static.qiyi.com +trace
。。。。。。。
。。。。。。。
static.qiyi.com. 3600 IN A 220.181.73.6 //哥依旧喜欢dns轮询
static.qiyi.com. 3600 IN A 220.181.73.5
qiyi.com. 900 IN NS ns2.qiyi.com.
qiyi.com. 900 IN NS ns1.qiyi.com.域名(图片)
[root@s1 ~]# curl -I
CODE:
HTTP/1.1 200 OK
Server: nginx/0.8.34
Date: Mon, 26 Apr 2010 08:45:18 GMT
Content-Type: image/jpeg
Connection: keep-alive
Expires: Fri, 21 May 2010 16:37:51 GMT
Cache-Control: max-age=2592000
ETag: "114431829"
Last-Modified: Mon, 05 Apr 2010 10:27:06 GMT
Content-Length: 7628
Accept-Ranges: bytes[root@s1 ~]# dig www.qiyipic.com +trace
CODE:
; <<>> DiG 9.3.4-P1 <<>> www.qiyipic.com +trace
。。。。。。。。
。。。。。。。。
www.qiyipic.com. 3600 IN A 202.108.14.16 // 哥对DNS轮询情有独钟!
www.qiyipic.com. 3600 IN A 202.108.14.15综述:
1.奇艺视频网站按业务类型域名分类(不用说,现在中小型网站都这样做)
好处:一个好处容易区分业务;一个好处是可以减少读取cookie对图片服务器的压力和提高安全性,避免cookie泄露
2.采用DNS轮询
好处:架构之初,简单方便,我相信奇艺运维人员还会做很多工作。
3.HTTP Server
采用nginx做反向代理,nginx反向代理还是强劲不用说:)后端感觉到是像apache
4.gzip
没有对任何文件进行压缩,不知道为什么?哥有钱?
etag (到底要还是不要,应该如何优化?)
5.....
6... //待论坛里的哥哥们继续分析研究!
来源:http://www.linuxtone.org/html/34/t-5934.html
php 判断是否为搜索引擎蜘蛛,整理了一些比较常用的引擎蜘蛛。
/**
* 判断是否为搜索引擎蜘蛛
*
* @author Eddy
* @return bool
*/
function isCrawler() {
$agent= strtolower($_SERVER['HTTP_USER_AGENT']);
if (!empty($agent)) {
$spiderSite= array(
"TencentTraveler",
"Baiduspider+",
"BaiduGame",
"Googlebot",
"msnbot",
"Sosospider+",
"Sogou web spider",
"ia_archiver",
"Yahoo! Slurp",
"YoudaoBot",
"Yahoo Slurp",
"MSNBot",
"Java (Often spam bot)",
"BaiDuSpider",
"Voila",
"Yandex bot",
"BSpider",
"twiceler",
"Sogou Spider",
"Speedy Spider",
"Google AdSense",
"Heritrix",
"Python-urllib",
"Alexa (IA Archiver)",
"Ask",
"Exabot",
"Custo",
"OutfoxBot/YodaoBot",
"yacy",
"SurveyBot",
"legs",
"lwp-trivial",
"Nutch",
"StackRambler",
"The web archive (IA Archiver)",
"Perl tool",
"MJ12bot",
"Netcraft",
"MSIECrawler",
"WGet tools",
"larbin",
"Fish search",
);
foreach($spiderSite as $val) {
$str = strtolower($val);
if (strpos($agent, $str) !== false) {
return true;
}
}
} else {
return false;
}
}
* 判断是否为搜索引擎蜘蛛
*
* @author Eddy
* @return bool
*/
function isCrawler() {
$agent= strtolower($_SERVER['HTTP_USER_AGENT']);
if (!empty($agent)) {
$spiderSite= array(
"TencentTraveler",
"Baiduspider+",
"BaiduGame",
"Googlebot",
"msnbot",
"Sosospider+",
"Sogou web spider",
"ia_archiver",
"Yahoo! Slurp",
"YoudaoBot",
"Yahoo Slurp",
"MSNBot",
"Java (Often spam bot)",
"BaiDuSpider",
"Voila",
"Yandex bot",
"BSpider",
"twiceler",
"Sogou Spider",
"Speedy Spider",
"Google AdSense",
"Heritrix",
"Python-urllib",
"Alexa (IA Archiver)",
"Ask",
"Exabot",
"Custo",
"OutfoxBot/YodaoBot",
"yacy",
"SurveyBot",
"legs",
"lwp-trivial",
"Nutch",
"StackRambler",
"The web archive (IA Archiver)",
"Perl tool",
"MJ12bot",
"Netcraft",
"MSIECrawler",
"WGet tools",
"larbin",
"Fish search",
);
foreach($spiderSite as $val) {
$str = strtolower($val);
if (strpos($agent, $str) !== false) {
return true;
}
}
} else {
return false;
}
}
wget http://www.vanheusden.com/httping/httping-1.4.1.tgz
tar zxvf httping-1.4.1.tgz -C /tmp/
cd /tmp/httping-1.4.1/
make&&make install
tar zxvf httping-1.4.1.tgz -C /tmp/
cd /tmp/httping-1.4.1/
make&&make install
默认就安装在/usr下了。如果不想,直接改Makefile去。
然后使用:
httping -options
-g url
-h hostname
-p port
-x host:port(如果是测squid,用-x,不要用-h;和curl的不一样,curl -H指定的是发送的hostname,这个-h是指定给DNS解析的hostname)
-c count
-t timeout
-s statuscode
-S 将时间分开成连接和传输两部分显示
-G GET(默认是HEAD)
-b 在使用了GET的前提下显示传输速度KB/s
-B 同-b,不过使用了压缩
-I useragent
-R referer
-C cookie=*
-l SSL
-U username
-P password
-n a,b 提供给nagios监控用的,当平均响应时间>=a时,返回1;>=b,返回2;默认为0
-N c 提供给nagios监控用的,一切正常返回0,否则只要有失败的就返回c
举例如下:
httping -x 211.151.78.37:80 http://bj.qu114.com/ -SGbs -c 10
Using proxyserver: 211.151.78.37:80
PING bj.qu114.com:80 (http://bj.qu114.com/):
connected to bj.qu114.com:80, seq=0 time=27.00+2945.88=2972.87 ms 200 OK 16KB/s
connected to bj.qu114.com:80, seq=1 time=27.09+2233.38=2260.47 ms 200 OK 17KB/s
connected to bj.qu114.com:80, seq=2 time=26.90+168.70=195.60 ms 200 OK 400KB/s
connected to bj.qu114.com:80, seq=3 time=26.89+2524.52=2551.41 ms 200 OK 15KB/s
connected to bj.qu114.com:80, seq=4 time=26.90+1939.48=1966.37 ms 200 OK 20KB/s
connected to bj.qu114.com:80, seq=5 time=26.79+2085.52=2112.31 ms 200 OK 18KB/s
connected to bj.qu114.com:80, seq=6 time=27.04+1294.78=1321.82 ms 200 OK 32KB/s
connected to bj.qu114.com:80, seq=7 time=26.97+2527.29=2554.26 ms 200 OK 15KB/s
connected to bj.qu114.com:80, seq=8 time=26.88+1498.28=1525.16 ms 200 OK 27KB/s
connected to bj.qu114.com:80, seq=9 time=27.21+1208.70=1235.91 ms 200 OK 34KB/s
--- http://bj.qu114.com/ ping statistics ---
10 connects, 10 ok, 0.00% failed
round-trip min/avg/max = 195.6/1869.6/2972.9 ms
Transfer speed: min/avg/max = 15/59/400 KB
Using proxyserver: 211.151.78.37:80
PING bj.qu114.com:80 (http://bj.qu114.com/):
connected to bj.qu114.com:80, seq=0 time=27.00+2945.88=2972.87 ms 200 OK 16KB/s
connected to bj.qu114.com:80, seq=1 time=27.09+2233.38=2260.47 ms 200 OK 17KB/s
connected to bj.qu114.com:80, seq=2 time=26.90+168.70=195.60 ms 200 OK 400KB/s
connected to bj.qu114.com:80, seq=3 time=26.89+2524.52=2551.41 ms 200 OK 15KB/s
connected to bj.qu114.com:80, seq=4 time=26.90+1939.48=1966.37 ms 200 OK 20KB/s
connected to bj.qu114.com:80, seq=5 time=26.79+2085.52=2112.31 ms 200 OK 18KB/s
connected to bj.qu114.com:80, seq=6 time=27.04+1294.78=1321.82 ms 200 OK 32KB/s
connected to bj.qu114.com:80, seq=7 time=26.97+2527.29=2554.26 ms 200 OK 15KB/s
connected to bj.qu114.com:80, seq=8 time=26.88+1498.28=1525.16 ms 200 OK 27KB/s
connected to bj.qu114.com:80, seq=9 time=27.21+1208.70=1235.91 ms 200 OK 34KB/s
--- http://bj.qu114.com/ ping statistics ---
10 connects, 10 ok, 0.00% failed
round-trip min/avg/max = 195.6/1869.6/2972.9 ms
Transfer speed: min/avg/max = 15/59/400 KB
求平均 web页面响应时间
httping -c5 -g http://bbs.linuxtone.org | tail -n1 | awk '{print $4}' | cut -d/ -f2
来源:http://raocl.spaces.live.com/Blog/cns!3F6CFF93FD0E3B79!896.entry
我的系统是linux,最近新装好的mysql在进入mysql工具时,总是有错误提示:
# mysql -uroot -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
使用网上介绍的方法修改root用户的密码:
# mysqladmin -uroot -p password 'newpassword'
Enter password:
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: YES)'
现在终于被我找到了解决方法,如下(请先测试方法三,谢谢!):
方法一:
# /etc/init.d/mysql stop
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &
# mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# /etc/init.d/mysql restart
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>
mysql>
方法二:
直接使用/etc/mysql/debian.cnf文件中[client]节提供的用户名和密码:
# mysql -udebian-sys-maint -p
Enter password: <输入[client]节的密码>
mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>
mysql>
方法三:
这种方法我没有进行过测试,因为我的root用户默认密码已经被我修改过了,那位有空测试一下,把结果告诉我,谢谢!!
# mysql -uroot -p
Enter password: <输入/etc/mysql/debian.cnf文件中[client]节提供的密码>
至此,困惑多时的问题解决了!
阅读全文
# mysql -uroot -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
使用网上介绍的方法修改root用户的密码:
# mysqladmin -uroot -p password 'newpassword'
Enter password:
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: YES)'
现在终于被我找到了解决方法,如下(请先测试方法三,谢谢!):
方法一:
# /etc/init.d/mysql stop
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &
# mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# /etc/init.d/mysql restart
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>
mysql>
方法二:
直接使用/etc/mysql/debian.cnf文件中[client]节提供的用户名和密码:
# mysql -udebian-sys-maint -p
Enter password: <输入[client]节的密码>
mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>
mysql>
方法三:
这种方法我没有进行过测试,因为我的root用户默认密码已经被我修改过了,那位有空测试一下,把结果告诉我,谢谢!!
# mysql -uroot -p
Enter password: <输入/etc/mysql/debian.cnf文件中[client]节提供的密码>
至此,困惑多时的问题解决了!
阅读全文
unset LD_PRELOAD
unset LD_LIBRARY_PATH
问:unset LD_PRELOAD, unset LD_LIBRARY_PATH: 这两条命令用于取消设置 LD_PRELOAD 和 LD_LIBRARY_PATH 环境变量。这些环境变量通常用于动态链接器的路径搜索,取消设置它们可以避免对脚本执行环境的影响。
答:当你运行一个程序时,操作系统会使用动态链接器(如ld.so或者ld-linux.so)来加载程序所需要的共享库(或动态链接库)。动态链接器会根据一系列环境变量来确定从哪些目录中查找共享库。
其中,`LD_PRELOAD` 和 `LD_LIBRARY_PATH` 是两个影响动态链接器行为的重要环境变量:
1. `LD_PRELOAD`: 这个环境变量指定了在程序启动时先加载指定的共享库。这个功能通常用于在运行时对系统调用或者库函数进行劫持,或者在运行时注入一些额外的功能。取消设置 `LD_PRELOAD` 可以避免不必要的库的加载,确保程序运行在清晰的环境下。
2. `LD_LIBRARY_PATH`: 这个环境变量定义了动态链接器在加载共享库时应该搜索的目录列表。如果设置了 `LD_LIBRARY_PATH`,动态链接器会优先搜索指定的目录来查找共享库,而不是默认的系统目录。取消设置 `LD_LIBRARY_PATH` 可以确保程序不会在不可预测的目录中加载共享库,从而保证了系统的安全性和稳定性。
在脚本中使用 `unset LD_PRELOAD` 和 `unset LD_LIBRARY_PATH` 的目的是为了确保脚本在一个干净的环境下执行,不受这些环境变量的影响,从而避免了一些潜在的问题和安全隐患。
问:unset LD_PRELOAD
unset LD_LIBRARY_PATH
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
置空后,还是会去系统的动态链接库目录找相应的库文件吧?ldconfig -p 里面的动态链接均能用吧。
答:在脚本中使用 unset LD_PRELOAD 和 unset LD_LIBRARY_PATH 命令将这两个环境变量设置为空,系统仍然会按照默认的方式去查找动态链接库。这意味着系统会根据预定义的目录(如 /lib、/usr/lib、/lib64、/usr/lib64 等)来查找动态链接库,而不会受到 LD_LIBRARY_PATH 的影响。
在使用动态链接器(ld.so 或 ld-linux.so)加载程序时,它会按照一定的搜索顺序来查找动态链接库。这个搜索顺序通常是由系统配置文件中定义的,如 /etc/ld.so.conf 及其在 /etc/ld.so.conf.d/ 目录下的配置文件。
===============================================================================================
Linux 运行的时候,是如何管理共享库(*.so)的?在 Linux 下面,共享库的寻找和加载是由 /lib/ld.so 实现的。 ld.so 在标准路经(/lib, /usr/lib) 中寻找应用程序用到的共享库。
但是,如果需要用到的共享库在非标准路经,ld.so 怎么找到它呢?
目前,Linux 通用的做法是将非标准路经加入 /etc/ld.so.conf,然后运行 ldconfig 生成 /etc/ld.so.cache。 ld.so 加载共享库的时候,会从 ld.so.cache 查找。
传 统上, Linux 的先辈 Unix 还有一个环境变量 - LD_LIBRARY_PATH 来处理非标准路经的共享库。ld.so 加载共享库的时候,也会查找这个变量所设置的路经。但是,有不少声音主张要避免使用 LD_LIBRARY_PATH 变量,尤其是作为全局变量。这些声音是:
* LD_LIBRARY_PATH is not the answer - http://prefetch.net/articles/linkers.badldlibrary.html
* Why LD_LIBRARY_PATH is bad - http://xahlee.org/UnixResource_dir/_/ldpath.html
* LD_LIBRARY_PATH - just say no - http://blogs.sun.com/rie/date/20040710
解决这一问题的另一方法是在编译的时候通过 -R<path> 选项指定 run-time path。
1. 往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig,不然这个library会找不到
2. 想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到
比如安装了一个mysql到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在程序运行时被找到。
3. 如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用。
4. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
5. 总之,就是不管做了什么关于library的变动后,最好都ldconfig一下,不然会出现一些意想不到的结果。不会花太多的时间,但是会省很多的事。
http://hi.baidu.com/fanzier/blog/item/222ba3ec74cb9a2463d09fb5.html
LD_LIBRARY_PATH
这个环境变量是大家最为熟悉的,它告诉loader:在哪些目录中可以找到共享库。可以设置多个搜索目录,这些目录之间用冒号分隔开。在linux下,还
提供了另外一种方式来完成同样的功能,你可以把这些目录加到/etc/ld.so.conf中,或则在/etc/ld.so.conf.d里创建一个文
件,把目录加到这个文件里。当然,这是系统范围内全局有效的,而环境变量只对当前shell有效。按照惯例,除非你用上述方式指明,loader是不会在
当前目录下去找共享库的,正如shell不会在当前目前找可执行文件一样。
阅读全文
unset LD_LIBRARY_PATH
问:unset LD_PRELOAD, unset LD_LIBRARY_PATH: 这两条命令用于取消设置 LD_PRELOAD 和 LD_LIBRARY_PATH 环境变量。这些环境变量通常用于动态链接器的路径搜索,取消设置它们可以避免对脚本执行环境的影响。
答:当你运行一个程序时,操作系统会使用动态链接器(如ld.so或者ld-linux.so)来加载程序所需要的共享库(或动态链接库)。动态链接器会根据一系列环境变量来确定从哪些目录中查找共享库。
其中,`LD_PRELOAD` 和 `LD_LIBRARY_PATH` 是两个影响动态链接器行为的重要环境变量:
1. `LD_PRELOAD`: 这个环境变量指定了在程序启动时先加载指定的共享库。这个功能通常用于在运行时对系统调用或者库函数进行劫持,或者在运行时注入一些额外的功能。取消设置 `LD_PRELOAD` 可以避免不必要的库的加载,确保程序运行在清晰的环境下。
2. `LD_LIBRARY_PATH`: 这个环境变量定义了动态链接器在加载共享库时应该搜索的目录列表。如果设置了 `LD_LIBRARY_PATH`,动态链接器会优先搜索指定的目录来查找共享库,而不是默认的系统目录。取消设置 `LD_LIBRARY_PATH` 可以确保程序不会在不可预测的目录中加载共享库,从而保证了系统的安全性和稳定性。
在脚本中使用 `unset LD_PRELOAD` 和 `unset LD_LIBRARY_PATH` 的目的是为了确保脚本在一个干净的环境下执行,不受这些环境变量的影响,从而避免了一些潜在的问题和安全隐患。
问:unset LD_PRELOAD
unset LD_LIBRARY_PATH
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
置空后,还是会去系统的动态链接库目录找相应的库文件吧?ldconfig -p 里面的动态链接均能用吧。
答:在脚本中使用 unset LD_PRELOAD 和 unset LD_LIBRARY_PATH 命令将这两个环境变量设置为空,系统仍然会按照默认的方式去查找动态链接库。这意味着系统会根据预定义的目录(如 /lib、/usr/lib、/lib64、/usr/lib64 等)来查找动态链接库,而不会受到 LD_LIBRARY_PATH 的影响。
在使用动态链接器(ld.so 或 ld-linux.so)加载程序时,它会按照一定的搜索顺序来查找动态链接库。这个搜索顺序通常是由系统配置文件中定义的,如 /etc/ld.so.conf 及其在 /etc/ld.so.conf.d/ 目录下的配置文件。
===============================================================================================
Linux 运行的时候,是如何管理共享库(*.so)的?在 Linux 下面,共享库的寻找和加载是由 /lib/ld.so 实现的。 ld.so 在标准路经(/lib, /usr/lib) 中寻找应用程序用到的共享库。
但是,如果需要用到的共享库在非标准路经,ld.so 怎么找到它呢?
目前,Linux 通用的做法是将非标准路经加入 /etc/ld.so.conf,然后运行 ldconfig 生成 /etc/ld.so.cache。 ld.so 加载共享库的时候,会从 ld.so.cache 查找。
传 统上, Linux 的先辈 Unix 还有一个环境变量 - LD_LIBRARY_PATH 来处理非标准路经的共享库。ld.so 加载共享库的时候,也会查找这个变量所设置的路经。但是,有不少声音主张要避免使用 LD_LIBRARY_PATH 变量,尤其是作为全局变量。这些声音是:
* LD_LIBRARY_PATH is not the answer - http://prefetch.net/articles/linkers.badldlibrary.html
* Why LD_LIBRARY_PATH is bad - http://xahlee.org/UnixResource_dir/_/ldpath.html
* LD_LIBRARY_PATH - just say no - http://blogs.sun.com/rie/date/20040710
解决这一问题的另一方法是在编译的时候通过 -R<path> 选项指定 run-time path。
1. 往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig,不然这个library会找不到
2. 想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到
比如安装了一个mysql到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在程序运行时被找到。
3. 如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用。
4. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
5. 总之,就是不管做了什么关于library的变动后,最好都ldconfig一下,不然会出现一些意想不到的结果。不会花太多的时间,但是会省很多的事。
http://hi.baidu.com/fanzier/blog/item/222ba3ec74cb9a2463d09fb5.html
LD_LIBRARY_PATH
这个环境变量是大家最为熟悉的,它告诉loader:在哪些目录中可以找到共享库。可以设置多个搜索目录,这些目录之间用冒号分隔开。在linux下,还
提供了另外一种方式来完成同样的功能,你可以把这些目录加到/etc/ld.so.conf中,或则在/etc/ld.so.conf.d里创建一个文
件,把目录加到这个文件里。当然,这是系统范围内全局有效的,而环境变量只对当前shell有效。按照惯例,除非你用上述方式指明,loader是不会在
当前目录下去找共享库的,正如shell不会在当前目前找可执行文件一样。
阅读全文
数据文件:*.myd
索引文件:*.myi
表定义文件:*.frm
PHP数据库抽象层与数据库抽象类
1 什么是数据库抽象层
2 常用的数据库抽象层
3 数据库抽象层ADODB-实例
[编辑本段]PHP数据库抽象层与数据库抽象类
目前,在PHP的网站及众多书籍中,很少讲到数据库抽象层,有的PHP开发者虽然已做了几年开发工作,但似乎也没有意识到它的存在。
很多人并不理解数据抽象的重要性,也不了解mysql或mysqli扩展与PDO的区别,PDO与ADODB又有什么区别。
在本章中将讲述以下内容,通过学习,上面的问题都会迎刃而解。
使用数据库抽象层的原因;
数据库抽象层的发展;
一些流行新抽象层的介绍;
PDO数据库抽象层开发技术;
ADODB数据库抽象层开发技术。
[编辑本段]1 什么是数据库抽象层
使用数据库抽象层,意味着当从一个数据库系统向另一个数据库系统迁移时,几乎不用更改太多的程序代码,如将MS SQL Server迁移到MySQL。
首先,代码规划必须规范,即整个系统使用同一个数据对象实例,并且使用同一个较好的数据库抽象层。如果有一天用户要求将Oracle切换到MySQL,则只需要改变系统的配置文件即可。
在当今工业领域中,每个数据库开发商如微软、Oracle、MySQL,都有自己的一套SQL标准,它们声称是按照ANSI SQL92标准而增加自己的特性,以达到垄断或占领市场的目的。
优秀的数据库抽象层,会根据我们现在使用的数据库自动调整一些SQL性能。当没有使用数据库本身特定的特性时,就不必更改太多的数据库连接和数据库SQL查询。
使用数据库抽象层的其他好处是:其性质、概念简化了复杂的任务。因此,我们不必学习某个数据库系统的全新特性,而只用一个标准的抽象层的代码特性即可。
虽然这是一种理想化,但随着技术的发展,相信数据库抽象层会为我们做更多的事。
目前,使用PHP进行不同的数据库系统开发,这些系统很不相同,而许多数据库抽象层在PHP的层次有所不同,但彼此使用方法相当,它的发展无疑会提高开发效率。
请看图17-1,观察有数据抽象层和没有数据抽象层的区别。
数据库抽象层的主要性能指标是速度,由于数据库抽象层是额外的代码层,因为面向不同的架构与体系,因此有的效率较高,有的则相对比较慢些。
如Metabase是PHP中较慢的一个数据抽象层,它使用C语言编写,因为它的设计与可移植性最高,而PDO和ADODB是当今世界最快的数据库抽象类。
阅读全文
1 什么是数据库抽象层
2 常用的数据库抽象层
3 数据库抽象层ADODB-实例
[编辑本段]PHP数据库抽象层与数据库抽象类
目前,在PHP的网站及众多书籍中,很少讲到数据库抽象层,有的PHP开发者虽然已做了几年开发工作,但似乎也没有意识到它的存在。
很多人并不理解数据抽象的重要性,也不了解mysql或mysqli扩展与PDO的区别,PDO与ADODB又有什么区别。
在本章中将讲述以下内容,通过学习,上面的问题都会迎刃而解。
使用数据库抽象层的原因;
数据库抽象层的发展;
一些流行新抽象层的介绍;
PDO数据库抽象层开发技术;
ADODB数据库抽象层开发技术。
[编辑本段]1 什么是数据库抽象层
使用数据库抽象层,意味着当从一个数据库系统向另一个数据库系统迁移时,几乎不用更改太多的程序代码,如将MS SQL Server迁移到MySQL。
首先,代码规划必须规范,即整个系统使用同一个数据对象实例,并且使用同一个较好的数据库抽象层。如果有一天用户要求将Oracle切换到MySQL,则只需要改变系统的配置文件即可。
在当今工业领域中,每个数据库开发商如微软、Oracle、MySQL,都有自己的一套SQL标准,它们声称是按照ANSI SQL92标准而增加自己的特性,以达到垄断或占领市场的目的。
优秀的数据库抽象层,会根据我们现在使用的数据库自动调整一些SQL性能。当没有使用数据库本身特定的特性时,就不必更改太多的数据库连接和数据库SQL查询。
使用数据库抽象层的其他好处是:其性质、概念简化了复杂的任务。因此,我们不必学习某个数据库系统的全新特性,而只用一个标准的抽象层的代码特性即可。
虽然这是一种理想化,但随着技术的发展,相信数据库抽象层会为我们做更多的事。
目前,使用PHP进行不同的数据库系统开发,这些系统很不相同,而许多数据库抽象层在PHP的层次有所不同,但彼此使用方法相当,它的发展无疑会提高开发效率。
请看图17-1,观察有数据抽象层和没有数据抽象层的区别。
数据库抽象层的主要性能指标是速度,由于数据库抽象层是额外的代码层,因为面向不同的架构与体系,因此有的效率较高,有的则相对比较慢些。
如Metabase是PHP中较慢的一个数据抽象层,它使用C语言编写,因为它的设计与可移植性最高,而PDO和ADODB是当今世界最快的数据库抽象类。
阅读全文
背景
过去两年多来,我们的网站一直运行Apache+mod_php模块,大多数时候这个组合应付得过来,但随着流量的增加,我们注意到Apache已经显得很吃力了,它开始疯狂地吃内存,CPU也被全部抢占去了,我们需要找到一个更快的方法来解决问题。
Nginx是一个不错的选择,很多指标都超过了Apache,如I/O、CPU、内存和请求数/秒等,如果需要,随时可以从Google搜索相关信息。从我个人的测试结果来看,Nginx和Apache之间的差异是很明显的,不好意思,因为是非正式测试,因此相关数字我就不公布了,这也不是本文的重点。让我更自信的是,我只需要几个步骤就可以让性能远超Apache。
PHP-FPM?
很多人配置Nginx时可能都会选择来自LightTPD项目的spawn-fcgi解析PHP,但使用spawn-fcgi有些问题,因此我打算放弃它另觅别的办法。PHP-FPM是PHP FastCGI Process Manager的缩写,即PHP FastCGI进程管理器,实际上它是PHP的一个补丁,旨在将FastCGI进程管理整合进PHP包中。
注意:即使你坚持使用Apache,也有很多原因跳过mod_php,直接通过FastCGI解析PHP。使用mod_php时,Apache处理载入PHP的每个请求会载入所有的库,这是一个巨大的无畏开销。如果使用FastCGI,PHP的行为更象应用程序服务器,PHP-FPM以及spawn-fcgi按需要载入和杀掉PHP实例,这样做有很多好处,其中很重要的一点就是减少内存开销。
过去两年多来,我们的网站一直运行Apache+mod_php模块,大多数时候这个组合应付得过来,但随着流量的增加,我们注意到Apache已经显得很吃力了,它开始疯狂地吃内存,CPU也被全部抢占去了,我们需要找到一个更快的方法来解决问题。
Nginx是一个不错的选择,很多指标都超过了Apache,如I/O、CPU、内存和请求数/秒等,如果需要,随时可以从Google搜索相关信息。从我个人的测试结果来看,Nginx和Apache之间的差异是很明显的,不好意思,因为是非正式测试,因此相关数字我就不公布了,这也不是本文的重点。让我更自信的是,我只需要几个步骤就可以让性能远超Apache。
PHP-FPM?
很多人配置Nginx时可能都会选择来自LightTPD项目的spawn-fcgi解析PHP,但使用spawn-fcgi有些问题,因此我打算放弃它另觅别的办法。PHP-FPM是PHP FastCGI Process Manager的缩写,即PHP FastCGI进程管理器,实际上它是PHP的一个补丁,旨在将FastCGI进程管理整合进PHP包中。
注意:即使你坚持使用Apache,也有很多原因跳过mod_php,直接通过FastCGI解析PHP。使用mod_php时,Apache处理载入PHP的每个请求会载入所有的库,这是一个巨大的无畏开销。如果使用FastCGI,PHP的行为更象应用程序服务器,PHP-FPM以及spawn-fcgi按需要载入和杀掉PHP实例,这样做有很多好处,其中很重要的一点就是减少内存开销。
〈一〉如何实现C中调用C++
如何用c语言调用c++做成的动态链接库, 转至
http://blog.donews.com/xzwenlan/archive/2005/05/31/405799.aspx
链接库头文件:
//head.h
class A
{
public:
A();
virtual ~A();
int gt();
int pt();
private:
int s;
};
.cpp
//firstso.cpp
#include <iostream>
#include "head.h"
A::A(){}
A::~A(){}
int A::gt()
{
s=10;
}
int A::pt()
{
std::cout<<s<<std::endl;
}
编译命令如下:
g++ -shared -o libmy.so firstso.cpp
这时候生成libmy.so文件,将其拷贝到系统库里面:/usr/lib/
进行二次封装:
.cpp
//secso.cpp
#include <iostream>
#include "head.h"
extern "C"
{
int f();
int f()
{
A a;
a.gt();
a.pt();
return 0;
}
}
编译命令:
gcc -shared -o sec.so secso.cpp -L. -lmy
这时候生成第二个.so文件,此时库从一个类变成了一个c的接口.
拷贝到/usr/lib
下面开始调用:
//test.c
#include "stdio.h"
#include "dlfcn.h"
#define SOFILE "sec.so"
int (*f)();
int main()
{
void *dp;
dp=dlopen(SOFILE,RTLD_LAZY);
f=dlsym(dp,"f");
f();
return 0;
}
编译命令如下:
运行Z$./myapp
10
$
关于这个文章的一点补充,转至http://blogs.sun.com/lirincy/
这篇blog写了怎样用C调用C++的库,我试验了一下,在linux上成功,
有两个地方要改一下,最后的编译语句应该是:
gcc -rdynamic -s -o -ldl myapp test.c
还有就是test.c最后应该加上:
dlclose(dp);
否则会CoreDump。
实际上他是把类的方法变成了一个可以外部调用的C函数,用extern C。
二〉C++程序如何调用C语言写的库,如a.lib等,有对应的库头文件a.h。假设a.h中定义了函数:
int WhyCoding(int a, float b);
做法是,
extern "C" {
#include "a.h"
}
或
extern "C" {
int WhyCoding(int a, float b);
}
从上面可以看出,extern "C" 是用在C和C++之间的桥梁。之所以需要这个桥梁是因为C编译器编译函数时不带
函数的类型信息,只包含函数符号名字,如C编译器把函数int a(float x)编译成类似_a这样的符号,C连接器只要
找到了调用函数的符号,就可以连接成功,它假设参数类型信息是正确的,这是C编译连接器的缺点。而C++
编译器为了实现函数重载,编译时会带上函数的类型信息,如他把上面的a函数可能编译成_a_float这样的
符号为了实现重载,注意它还是没有带返回值得信息,这也是为什么C++不支持采用函数返回值来区别函数
重载的原因之一,当然,函数的使用者对函数返回值的处理方式(如忽略)也是重要原因。
基于以上,C调用C++,首先需要用封装函数把对C++的类等的调用封装成C函数以便C调用,于是extern "C" 的
作用是:让编译器知道这件事,然后以C语言的方式编译和连接封装函数.(通常是把封装函数用C++编译器按C++
方式编译,用了extern "C" 后,编译器便依C的方式编译封装接口,当然接口函数里面的C++语法还是按C++方式
编译;对于C语言部分--调用者,还是按C语言编译;分别对C++接口部分和C部分编译后,再连接就可以实现C
调用C++了).
相反,C++调用C函数,extern "C" 的作用是:让C++连接器找调用函数的符号时采用C的方式,即使用_a而不是
_a_float来找调用函数。
chai, zheng 1:20 AM, Nov 29, 2006 at nanjing, China
如何用c语言调用c++做成的动态链接库, 转至
http://blog.donews.com/xzwenlan/archive/2005/05/31/405799.aspx
链接库头文件:
//head.h
class A
{
public:
A();
virtual ~A();
int gt();
int pt();
private:
int s;
};
.cpp
//firstso.cpp
#include <iostream>
#include "head.h"
A::A(){}
A::~A(){}
int A::gt()
{
s=10;
}
int A::pt()
{
std::cout<<s<<std::endl;
}
编译命令如下:
g++ -shared -o libmy.so firstso.cpp
这时候生成libmy.so文件,将其拷贝到系统库里面:/usr/lib/
进行二次封装:
.cpp
//secso.cpp
#include <iostream>
#include "head.h"
extern "C"
{
int f();
int f()
{
A a;
a.gt();
a.pt();
return 0;
}
}
编译命令:
gcc -shared -o sec.so secso.cpp -L. -lmy
这时候生成第二个.so文件,此时库从一个类变成了一个c的接口.
拷贝到/usr/lib
下面开始调用:
//test.c
#include "stdio.h"
#include "dlfcn.h"
#define SOFILE "sec.so"
int (*f)();
int main()
{
void *dp;
dp=dlopen(SOFILE,RTLD_LAZY);
f=dlsym(dp,"f");
f();
return 0;
}
编译命令如下:
gcc -rdynamic -s -o myapp test.c
运行Z$./myapp
10
$
关于这个文章的一点补充,转至http://blogs.sun.com/lirincy/
这篇blog写了怎样用C调用C++的库,我试验了一下,在linux上成功,
有两个地方要改一下,最后的编译语句应该是:
gcc -rdynamic -s -o -ldl myapp test.c
还有就是test.c最后应该加上:
dlclose(dp);
否则会CoreDump。
实际上他是把类的方法变成了一个可以外部调用的C函数,用extern C。
二〉C++程序如何调用C语言写的库,如a.lib等,有对应的库头文件a.h。假设a.h中定义了函数:
int WhyCoding(int a, float b);
做法是,
extern "C" {
#include "a.h"
}
或
extern "C" {
int WhyCoding(int a, float b);
}
从上面可以看出,extern "C" 是用在C和C++之间的桥梁。之所以需要这个桥梁是因为C编译器编译函数时不带
函数的类型信息,只包含函数符号名字,如C编译器把函数int a(float x)编译成类似_a这样的符号,C连接器只要
找到了调用函数的符号,就可以连接成功,它假设参数类型信息是正确的,这是C编译连接器的缺点。而C++
编译器为了实现函数重载,编译时会带上函数的类型信息,如他把上面的a函数可能编译成_a_float这样的
符号为了实现重载,注意它还是没有带返回值得信息,这也是为什么C++不支持采用函数返回值来区别函数
重载的原因之一,当然,函数的使用者对函数返回值的处理方式(如忽略)也是重要原因。
基于以上,C调用C++,首先需要用封装函数把对C++的类等的调用封装成C函数以便C调用,于是extern "C" 的
作用是:让编译器知道这件事,然后以C语言的方式编译和连接封装函数.(通常是把封装函数用C++编译器按C++
方式编译,用了extern "C" 后,编译器便依C的方式编译封装接口,当然接口函数里面的C++语法还是按C++方式
编译;对于C语言部分--调用者,还是按C语言编译;分别对C++接口部分和C部分编译后,再连接就可以实现C
调用C++了).
相反,C++调用C函数,extern "C" 的作用是:让C++连接器找调用函数的符号时采用C的方式,即使用_a而不是
_a_float来找调用函数。
chai, zheng 1:20 AM, Nov 29, 2006 at nanjing, China