nginx proxy_cache

从nginx-0.7.44版开始,nginx支持了类似squid较为正规的cache功能,这个缓存是把链接用md5编码hash后保存,所以它可以支持任意链接,同时也支持404/301/302这样的非200状态。

 

开启缓存

使用 proxy_cache_path 配置缓存空间(必须放在 http 上下文的顶层位置),然后在目标上下文中使用 proxy_cache 指令。

proxy_cache_path /path/to/cache levels=1:2 keys_zone=NAME:10m inactive=5m max_size=10g clean_time=1m;

1、levels指定该缓存空间有两层hash目录,第一层目录是1个字母,第二层为2个字母,保存的文件名就会类似/path/to/cache/c/29/b7f54b2df7773722d382f4809d65029c;

2、keys_zone 设置一个共享内存区,该内存区用于存储缓存键和元数据,有些类似计时器的用途。将键的拷贝放入内存可以使NGINX在不检索磁盘的情况下快速决定一个请求是HIT还是MISS,这样大大提高了检索速度。一个1MB的内存空间可以存储大约8000个key,那么上面配置的10MB内存空间可以存储差不多80000个key。

3、inactive 指定项目在不被访问的情况下能够在内存中保持的时间。上述例子,如果一个文件在5分钟之内没有被请求,则缓存管理将会自动将其在内存中删除,不管该文件是否过期。该参数默认值为10分钟(10m)。注意,非活动内容有别于过期内容。NGINX不会自动删除由缓存控制头部指定的过期内容(例Cache-Control:max-age=120)。过期内容只有在inactive指定时间内没有被访问的情况下才会被删除。如果过期内容被访问了,那么NGINX就会将其从原服务器上刷新,并更新对应的inactive计时器。

4、max_size设置了缓存的上限(在上面的例子中是10G);这是一个可选项,如果不指定就允许缓存不断增长,占用所有可用的磁盘空间。当缓存达到这个上限,处理器便调用cache manager来移除最近最少被使用的文件,这样把缓存的空间降低至这个限制之下。

5、clean_time指定一分钟清理一次缓存。

6、NGINX最初会将注定写入缓存的文件先放入一个临时存储区域, use_temp_path=off命令指示NGINX将在缓存这些文件时将它们写入同一个目录下。强烈建议将参数设置为off来避免在文件系统中不必要的数据拷贝。use_temp_path在NGINX1.7版本中有所介绍

 

访问过期缓存

NGINX内容缓存的一个非常强大的特性是:当无法从原始服务器获取最新的内容时,NGINX可以分发缓存中的陈旧(stale,编者注:即过期内容)内容。这种情况一般发生在关联缓存内容的原始服务器宕机或者繁忙时。比起对客户端传达错误信息,NGINX可发送在其内存中的陈旧的文件。NGINX的这种代理方式,为服务器提供额外级别的容错能力,并确保了在服务器故障或流量峰值的情况下的正常运行。为了开启该功能,只需要添加proxy_cache_use_stale命令即可:

location / {

...

proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;

}

按照上面例子中的配置,当NGINX收到服务器返回的error,timeout或者其他指定的5xx错误,并且在其缓存中有请求文件的陈旧版本,则会将这些陈旧版本的文件而不是错误信息发送给客户端。

 

配置后端服务器组:

upstream my_upstream {

server 192.168.61.1:9080max_fails=10 fail_timeout=10s weight=5;

}

 

配置例子:

NGINX提供了丰富的可选项配置用于缓存性能的微调。

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m
use_temp_path=off;
server {
...
location / {
proxy_cache my_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_pass http://my_upstream;
}
}

1、proxy_cache_revalidate指示NGINX在刷新来自服务器的内容时使用GET请求。如果客户端的请求项已经被缓存过了,但是在缓存控制头部中定义为过期,那么NGINX就会在GET请求中包含If-Modified-Since字段,发送至服务器端。这项配置可以节约带宽,因为对于NGINX已经缓存过的文件,服务器只会在该文件请求头中Last-Modified记录的时间内被修改时才将全部文件一起发送。

2、proxy_cache_min_uses设置了在NGINX缓存前,客户端请求一个条目的最短时间。当缓存不断被填满时,这项设置便十分有用,因为这确保了只有那些被经常访问的内容才会被添加到缓存中。该项默认值为1。

3、proxy_cache_use_stale中的updating参数告知NGINX在客户端请求的项目的更新正在原服务器中下载时发送旧内容,而不是向服务器转发重复的请求。第一个请求陈旧文件的用户不得不等待文件在原服务器中更新完毕。陈旧的文件会返回给随后的请求直到更新后的文件被全部下载。

4、当proxy_cache_lock被启用时,当多个客户端请求一个缓存中不存在的文件(或称之为一个MISS),只有这些请求中的第一个被允许发送至服务器。其他请求在第一个请求得到满意结果之后在缓存中得到文件。如果不启用proxy_cache_lock,则所有在缓存中找不到文件的请求都会直接与服务器通信。

 

指定哪些方法的请求被缓存

例如 proxy_cache_methods GET HEAD POST;

 

缓存跳过

例如 proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;

如果任何一个参数值不为空,或者不等于0,nginx就不会查找缓存,直接进行代理转发

例子:

location / {
proxy_pass http://www.sudone.com/;

proxy_cache NAME;#使用NAME这个keys_zone

proxy_cache_valid 200 302 1h;#200和302状态码保存1小时
proxy_cache_valid 301 1d;#301状态码保存一天
proxy_cache_valid any 1m;#其它的保存一分钟
}

 

应用案例:

server {
listen 80;
server_name _;
server_tokens off;
location / {
proxy_pass http://127.0.0.1:8080/;
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_cache my-cache;
proxy_cache_valid 3s;
proxy_no_cache $cookie_PHPSESSID;
proxy_cache_bypass $cookie_PHPSESSID;
proxy_cache_key "schemehost$request_uri";
add_header X-Cache $upstream_cache_status;
}
}

server {
listen 8080;
server_name _;
root /var/www/your_document_root/;
index index.php index.html index.htm;
server_tokens off;
location ~ \.php$ {
try_files $uri /index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME documentroot fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}

 

配置汇总:

1.add_header cache-status $upstream_cache_status在响应头中添加缓存命中的状态。

HIT:缓存命中,直接返回缓存中内容,不回源到后端。

MISS:缓存未命中,回源到后端获取最新的内容。

EXPIRED:缓存命中但过期了,回源到后端获取最新的内容。

UPDATING:缓存已过期但正在被别的Nginx Worker进程更新,配置了proxy_cache_use_stale updating指令时会存在该状态。

STALE:缓存已过期,但因后端服务出现了问题(比如后端服务挂了)返回过期的响应,配置了如proxy_cache_use_stale error timeout指令后会出现该状态。

REVALIDATED:启用proxy_cache_revalidate指令后,当缓存内容过期时,Nginx通过一次if-modified-since的请求头去验证缓存内容是否过期,此时会返回该状态。

BYPASS:proxy_cache_bypass指令有效时,强制回源到后端获取内容,即使已经缓存了。

4.proxy_cache_min_uses

用于控制请求多少次后响应才被缓存。默认“proxy_cache_min_uses1;”,如果缓存热点比较集中、存储有限,则可以通过修改该参数来来减少缓存数量和写磁盘次数。

5.proxy_no_cache

用于控制什么情况下响应不被缓存。比如配置“proxy_no_cache$args_nocache”,如果带的nocache参数值至少有一个不为空或者为0,则响应将不被缓存。

6.proxy_cache_bypass

类似于proxy_no_cache,但是,其控制什么情况不使用缓存的内容,而是直接到后端获取最新的内容。如果命中,则$upstream_cache_status为BYPASS。

7.proxy_cache_use_stale

当对缓存内容的过期时间不敏感,或者后端服务出问题时,即使缓存的内容不新鲜也总比返回错误给用户强(类似于托底),此时可以配置该参数,如“proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504”,即如果出现超时、后端连接出错、500、502、503等错误时,则即使缓存内容已过期也先返回给用户,此时$upstream_cache_status为STALE。还有一个updating表示缓存已过期但正在被别的Nginx Worker进程更新,但先返回了过期内容,此时$upstream_cache_status为UPDATING。

8.proxy_cache_revalidate

当缓存过期后,如果开启了proxy_cache_revalidate,则会发出一次if-modified-since或if-none-match条件请求,如果后端返回304,则此时$upstream_cache_status为REVALIDATED,我们将得到两个好处,节省带宽和减少写磁盘的次数。

9.proxy_cache_lock

当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off),则只有一个请求被发送至后端。其他请求将等待该请求的返回。当第一个请求返回后,其他相同请求将从缓存中获取内容返回。当第一个请求超过了proxy_cache_lock_timeout超时时间(默认为5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的)。启用proxy_cache_lock可以应对Dog-pile effect(当某个缓存失效时,同时有大量相同的请求没命中缓存,而同时请求到后端,从而导致后端压力太大,此时限制一个请求去拿即可)。

proxy_cache_lock_age是1.7.8新添加的,如果在proxy_cache_lock_age指定的时间内(默认为5s),最后一个发送到后端进行新缓存构建的请求还没有完成,则下一个请求将被发送到后端来构建缓存(因为1.7.8版本之后,proxy_cache_lock_timeout超时之后返回的内容是不缓存的,需要下一次请求来构建响应缓存)。

 

缓存清理

有时缓存的内容是错误的,需要手工清理,Nginx企业版提供了purger功能,对于社区版Nginx可以考虑使用ngx_cache_purge(https://github.com/FRiCKLE/ngx_cache_purge)模块进行清理缓存。

location ~ /purge(/.*) {

allow 127.0.0.1;

deny all;

proxy_cache_purge cache$1$is_args$args;

}

 

NGINX SQUID 分流:

bbs运行在缓存上,用户每发布一张帖子,都需要使用purge指令清除该帖子的缓存,如果是squid在最前端,那么每次发布一张帖子,都需要在所有的squid中调用purge指令,这样在机器比较多的时候,purge将成为一个巨大的压力。

所以在这里将Nginx squid架构放在最前端并使用手工url_hash的方式分流,将经常需要purge的帖子页面和列表页面按一个url对应一台squid的策略,分布到各台squid上,并提供了一台或一组backup的squid,个别squid出现异常时将自动使用backup的机器继续提供一段时间的服务直到其正常。在这样的架构下,purge就不再是关键问题,因为一个url只会对应到一台机器上,所以purge的时候,后端app_server找到对应的机器就可以了。

可以看到在前端中还有一台Nginx(purge)的机器,这台机器是专用于purge的,只要发送purge指令和需要清除的url到这台机器,就可以找到相应的服务器并清除缓存了。另外,purge时还需要清理backup机器上的缓存,所以无论前端机器增加到多少,purge指令只会在2台机器上执行,如果backup机器使用到2-3台,purge指令就会在3-4台机器上执行,仍然在可接受范围之内。

Nginx squid架构作为前端,另有的好处:

1/使用Nginx的日志统计点击量非常方便

 

 

 

聊聊:

 

一个很悲剧的事实
对动态网页使用CDN,无论squid还是varnish都不能直接用,都需定制代码。
例如varnish会判断response的header,如果发现里面有set-cookie项,它就认为这个页面不应该被缓存。对于规模庞大/OOP封装严密的网站,普通程序员根本意识不到调用哪一个fucntion会输出set-cookie,这个会导致CDN命中率急剧降低。但你也无力去对每行代码做code review,没有办法,只能去修改varnish代码了,这又引入一个新的维护成本. Squid也有这个问题

purge效率
purge就是CDN删除缓存项的接口,国内的UGC网站,因为严厉的内容检查制度和泛滥的垃圾广告,删帖子删图片特别频繁,某些网站可能高达40%(发100个贴,有40个帖子可能被删除或者修改),所以对purge的效率有要求。
squid和varnish的purge效率都达不到国内这种强度要求,nginx+memcache purge性能要好很多。
在当前的中国,遇到突发事件后,要是不及时删除指定的链接或内容,后果可能会很严重(小到个人被炒,大到公司被关都有可能)
某门户网站曾经发生过,某个链接怎么也删不掉,一慌张把CDN所有缓存都删了重启,导致内网流量瞬间暴涨,各业务线的服务器全线报警

 

..

发表在 web server | 标签为 | nginx proxy_cache已关闭评论

监测Squid日志的五种方法

Squid是Unix、Linux环境下一款优秀的代理服务器软件,本文叙述了Squid代理日志的五种监测方法,五种方法各有重点,可根据需要进行选择使用。

1 使用命令行

访问时间 持续时间 客户IP 采用协议 传输字节 访问方式 服务IP

如果我们仅仅需要查看某一个字段,可以用awk命令,它把一个记录行分割成多个字段,我们使用参数传回需要的字段。命令如下:

# tail -f /var/log/squid/access.log | awk '{print$3 " " $8 " " $7}'

这里选择的是客户IP及取回内容字段,显示如下:

192.168.1.146 - http://jump.qq.com/clienturl_simp_80

192.168.1.149 - http://mm.china.com/zh_cn/images/tit_liangzhuang.gif

192.168.1.161 - http://ly.zzip.com.cn/movie/list.aspx ?

这种方式的优点是实时性强,显示的是当前正在访问的记录的情况。

2 用SARG进行监测

SARG的全称是Squid Analysis Report Generator,即Squid报告分析产生器。利用SARG,可以窗口的方式显示上网用户的浏览记录,包括用户的访问时间,访问站点,传输字节等。SARG可从站点http://sourceforge.net/projects/sarg/ 下载,最新版本是2.0,目前还没有中文版本,这里下载的是源代码包。

1.安装SARG

把下载后的sarg-2.0.1.tar.gz拷贝到/usr/local/目录,进行解压缩并安装。执行如下指令:

#cp sarg-2.0.1.tar.gz /usr/local/

#cd /usr/local/

#tar -zfxv sarg-2.0.1.tar.gz

解压后在当前目录下产生sarg-2.0.1目录,进入到这个目录,执行以下安装命令:

# ./configure

# make

# make install

2.配置SARG

软件安装在/usr/local/sarg/目录下,目录下的配置文件sarg.conf主要包括如下参数:“language English”定义报告显示语言;“title "Squid User Access Reports"”定义报告文件的标题;“output_dir /var/www/html/squid-reports”定义报告文件的输出目录;“user_ip yes”以用户IP为基准进行显示,前提是进行了很好的用户IP控制;“access_log /var/log/squid/access.log”指定Squid日志文件的存放位置;“report_type topsites sites_users users_sites date_time denied auth_failures”显示产生的报告文件里包括什么类型的内容(如表所示)。

3.使用SARG

配置完成之后,在终端窗口用命令sarg生成报告文件,然后就可以在客户端使用浏览器通过访问http://Squid 日志服务器地址/squid-reports/来查看squid日志了。图1所示是查看日志的一个界面。

图1 使用SARG查看日志界面

3 用Webalizer进行监测

Webalizer工作方式不同于SARG,这个软件主要侧重于信息的汇总,如带宽、输入输出量,用于比较在不同的时间段网络的使用情况。

1.安装Webalizer

从站点http://www.mrunix.net/webalizer/download.html 下载,当前稳定版本是 2.01-10,提供RPM包和tar包格式的下载,笔者在这里下载的是webalizer-2.01-10-src.tgz。

进入到下载目录,执行如下命令:

#tar-xvzf webalizer-2.01-10-src.tgz

#cd web webalizer-2.01-10

#./configure

#make

#make install

2.配置Webalizer

Webalizer的配置文件是webalizer.conf,它可以放在安装目录下,也可以放在/etc/目录下,安装后产生可执行命令webalizer,当命令执行时,寻找webalizer.conf配置文件,产生相应的输出。webalizer.conf的配置比较简单,主要是指定squid日志文件的目录位置及产生报告的输出目录,主要参数如下:“LogFile /var/log/squid/access.log”表示squid日志文件目录;“LogType squid”表示Webalizer报告文件的输出类型;“OutputDir /home/webalizer/ ”表示报告文件的输出目录。

3.使用Webalizer

当执行webalizer命令后,在输出目录后输出报告文件,文件是基于时间段的,每一个时间段的报告产生的非常详细,查看文件仍可使用客户端浏览器方式。

4 用Calamaris进行监测

Calamaris是一个用perl语言写成的程序,如果要使用的话,首先系统里要安装perl解释器。它产生Squid日志的详细报告,包括按高峰时间时的使用情况、流进网内流量、流出流量、进出UDP包、进出TCP包、请求的二级或三级域名产生的报告文档。除用于Squid日志产生的日志分析外,它还可用于其他形式的代理服务软件产生的日志,如NetCache、Inktomi Traffic Server、Oops! proxy server、Novell InterNet Caching System等。

安装Calamaris也很简单,首先从站点http://cord.de/tools/squid/calamaris/Welcome.html.en 下载Calamaris V2.59到/usr/local/目录。执行以下命令:

#cd /usr/local/

#tar xvzf calamaris-2.59.tar.gz

# cd calamaris-2.59

解压后的目录包含可执行文件calamaris,无须安装,直接使用即可,比如用以下命令使Calamaris处理squid日志文件,产生html格式的文件,并输出到/var/www/html/calamaris/index.html。然后执行如下命令就可以查看输出报告了。

#/usr/local/calamaris/calamaris -a -F html /var/log/squid/access.log>/var/www/html/calamaris/index.html

对一般的应用来讲,上面的命令产生了最详细的输出报告,我们用命令选项-a表示产生所有类型的报告,用选项-F html表示产生html格式的文档。/var/log/squid/access.log表示squid日志文件的存放位置,/var/www/html/calamaris/index.html表示输出的文件名。当产生报告文件后,在客户端用浏览器可进行浏览。

5 用Squid-Graph进行监测

Squid-Graph同Calamaris一样,也是用Perl写成的,但正如它的名字一样,它用图形化的方法产生squid代理的使用情况,它产生一些综合信息。

可以从站点http://squid-graph.securlogic.com/files/stable/squid-graph-3.1.tar.gz 下载这个软件,这个软件是目前最后一个可获得的版本。这个程序的执行需要使用Perl GD模块,名称一般为GD.pm,是perl的绘图模块,其功能类似于市面上的许多图形程序。利用GD,我们展示如何创建几何图形,以及如何进行图像处理,这个模块可在软件发行版本的CD上找到,也可以从站点http://stein.cshl.org/WWW/software/GD/ 下载。

把下载的软件放到/usr/local/目录,进行解压。执行如下命令:

#cd /usr/local/

# tar xvzf squid-graph-3.1.tar.gz

# mv squid-graph-3.1 squid-graph

# cd squid-graph

# chmod +x /usr/local/squid-graph/bin/*

软件不须安装,直接使用,比如我们用以下的命令可产生TCP访问的累计图形:

#/usr/local/squid-graph/bin/squid-graph -c -n -o=/var/www/html/squid-graph/ --title="Squid server usage of proxy" < /var/log/squid/access.log

上面的这个命令用-c选项产生累计图形,用-n选项指定在命令执行过程中不向屏幕上输出信息,-o选项指定输出文件的目录,-title选项指定自定义的输出文档标题,图2是一个输出示例。

图2 Squid-Graph的显示

其实,squid-graph命令配合Linux下的其他命令如grep可以在squid日志中搜索需要的字符串,然后针对这一匹配项产生需要的图形。如下面的命令就产生了在所有日志行中有字符串“192.168.6.99”的客户端机器的使用squid代理的图形。

#cat /var/log/squid/access.log|grep"192.168.6.99"| /usr/local/squid-graph/bin/squid-graph -c -n / -o=/var/www/html/squid-graph/ --title="192.168.6.99’s usage"

利用这种方式,还可以产生统计访问某一个站点,访问特殊类型的文件如“.MP3”的统计图形

发表在 article | 标签为 | 35条评论

PIF病毒解决方案

最近局域网里面感染了PIF的病毒,十几台电脑无一幸免。它的症状大约是这样的,

1、路由器出现声音报警,提示有ARP攻击;

2、两个局域网中的一个局域网出现掉线的情况;

3、出现掉线的局域网中的大多数电脑系统时间都被改成了2004年

4、360、卡巴等软件全部被关闭。


5、电脑出现360、杀毒软件、注册表编辑器等无法打开,一双击运行就出现上“文件正在使用中”的提示。

6、安全模式无法进入,出现蓝屏重启现象。

7、无法查看隐藏文件,文件选项中“隐藏文件和文件夹”下两个选项同时被选中的情况。

8、各个分区、包括接入的U盘等都出现autorun.inf情况

9、进程里很多3.pif,h.pif,5.pif,无法结束进程

 

网上有提供一些解决方案,方案一:

360安全卫士最新版安装程序,“windows修复专家”,“SREng2”,“冰刃 ICEWORD”

将上述软件存放到光盘或U盘中,待修复系统时使用。

1、修复IFEO映像挟持:

  对付IFEO映像挟持最好的方法就是修改可执行文件的文件名,尝试修改360安全卫士的文件名,双击运行360发现360已经可以打开,但是360打开不多久就被关闭。利用“冰刃”查看进程,发现“冰刀”同样被IFEO映像挟持。修改““冰刃”的可执行文件,“冰刃”可正常运行。在结束“wuauclt.exe”进程后,360等软件已经不会被关闭,利用360的扫描“恶评插件”功能并清除后,即可恢复安全模式的正常运行,也可以清理所有的“IFEO映像挟持”。

修改系统日期为当前正确日期。

二、处理“wuauclt.exe”防止死灰复燃

  “wuauclt.exe”本来是Windows的系统更新程序,但是这次发现的木马程序已经将这个文件变成了
自己。所以这一步要干掉它。

  进入安全模式,利用其它电脑正常的“wuauclt.exe”文件换掉c:\windows\system32以及 c:\windows\system32\dllcache\中的文件,实在找不到正常的文件,
可以直接删除这两个文件,由于目前系统无法查看系统隐藏文件,所以要在命令行的模式下进行清除

  在运行中运行“CMD”进入命令行模式,依次运行下列命令

attrib -s -h -r c:\windows\system32\wuau*.exe

attrib -s -h -r c:\windows\system32\dllcache\wuau*.exe

del c:\windows\system32\wuau*.exe

del c:\windows\system32\dllcache\wuau*.exe

打开SREng,删除蓝色的异常的启动项目。

然后将先前修改的360的可执行文件改成原来的,如果忘记可以在这个时候重装360,并且在保护功能中打开ARP防火墙功能。

重启计算机进入正常模式,然后安装“windows修复专家”,用它对系统进行扫描,清理一切发现的可清除项目,当提示“进行驱动级清理”后,在提示重启计算机时,选择重启。




重启后,“windows修复专家”,会在桌面启动前再次运行并自动扫描,当扫描完成后关闭“windows修复专家”,这时桌面
出现。利用360对IE进行全面修复。

查找并删除硬盘中一切可删除的PIF文件。

到此清理基本成功。

 

 

因为网上提供的方法需要的工具太多了,我根本无法联网,上网下载软件就会被结束浏览器的进程,还不停跳出黄色网站。我只好拔开网线,手动删毒。

我先重装了系统,然后启动系统盘的PE系统,在PE系统里面查找*.pif文件,把这些文件都删除,查找autorun.inf文件,都删除它。重启电脑,装上360再扫描一遍,问题就解决了。

如果真的不想重装系统那也可以用USBcleaner6.0 修复系统安全模式,保护系统时间,进入安全模式再装杀毒软件,杀毒完了,再进PE系统手动删除所有PIF文件,所有恶意的autorun文件。

发表在 article | 标签为 | 66条评论

squid集群配置

在学习CDN方面资料时,所搭建的squid集群环境,供以后学习!
[基本架构]
squid1
                squid      web
squid2
squid1和squid2是姐妹关系,squid1,squid2和squid是父子关系,squid与web也是父子关系.
[IP分配信息]
squid    192.168.5.163
squid1   192.168.5.161
squid2   192.168.5.145
web      192.168.5.162
[内容]将其配置文件Copy下
squid1配置文件
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443
acl CONNECT method CONNECT
acl purge method PURGE
#acl gsrc src 192.168.5.161 192.168.5.162 192.168.5.163
#acl gdst dst 192.168.5.161 192.168.5.162 192.168.5.163
acl Safe_ports port 80
acl Safe_ports port 3130

http_access allow manager localhost
http_access deny manager
http_access allow purge localhost
http_access deny purge
#http_access allow gsrc
#http_access allow gdst
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
#http_access deny all
icp_access allow all
#http_port 80 accel vhost vport
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
cache deny QUERY
visible_hostname slibing1.squid.com
cache_mgr zhengjun.zhu@tiancity.com
access_log /usr/local/squid/var/logs/access.log squid
#refresh_pattern ^ftp:          1440    20%     10080
#refresh_pattern ^gopher:       1440    0%      1440
refresh_pattern -i .html$       10      50%     20
acl apache rep_header Server ^Apache
broken_vary_encoding allow apache
coredump_dir /usr/local/squid/var/cache
cache_mem 64 MB
#negative_ttl 1 second
###################################################
http_port 80 accel vhost vport
icp_port 3130
cache_peer 192.168.5.163 parent 80 0 no-query originserver no-digest name=cache0
cache_peer 192.168.5.161 sibling 80 3130 name=cache1
cache_peer 192.168.5.163 sibling 80 3130 name=cache2
cache_peer 192.168.5.165 sibling 80 3130 name=cache3
cache_peer_domain cache0 [url]www.squid.com[/url]

http_access deny !Safe_ports
negative_ttl 1 second
icp_query_timeout 2000
digest_generation on
log_icp_queries on
icp_hit_stale   on
squid2配置文件
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443
acl CONNECT method CONNECT
acl purge method PURGE
#acl gsrc src 192.168.5.161 192.168.5.162 192.168.5.163
#acl gdst dst 192.168.5.161 192.168.5.162 192.168.5.163
http_access allow manager localhost
http_access deny manager
http_access allow purge localhost
http_access deny purge
#http_access allow gsrc
#http_access allow gdst
#http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
#http_access deny all
icp_access allow all
#http_port 80 accel vhost vport
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
cache deny QUERY
visible_hostname slibing2.squid.com
cache_mgr zhengjun.zhu@tiancity.com
access_log /usr/local/squid/var/logs/access.log squid
#refresh_pattern ^ftp:          1440    20%     10080
#refresh_pattern ^gopher:       1440    0%      1440
refresh_pattern -i .html$       10      50%     20
acl apache rep_header Server ^Apache
broken_vary_encoding allow apache
coredump_dir /usr/local/squid/var/cache
cache_mem 64 MB
#negative_ttl 1 second
###################################################
http_port 80 accel vhost vport
icp_port 3130
cache_peer 192.168.5.163 parent 80 0 no-query originserver no-digest name=cache0
cache_peer 192.168.5.161 sibling 80 3130 name=cache1
cache_peer 192.168.5.163 sibling 80 3130 name=cache2
cache_peer 192.168.5.165 sibling 80 3130 name=cache3
cache_peer_domain cache0 [url]www.squid.com[/url]

acl Safe_ports port 80
acl Safe_ports port 3130
http_access deny !Safe_ports
negative_ttl 1 second
icp_query_timeout 2000
digest_generation on
log_icp_queries on
icp_hit_stale   on
squid配置文件
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443
acl CONNECT method CONNECT
acl purge method PURGE
acl CactiServer src 127.0.0.1 192.168.5.163
acl CactiServer src 192.168.5.161/255.255.255.255
acl SNMP snmp_community passwd
#acl gsrc src 192.168.5.161 192.168.5.162 192.168.5.163
#acl gdst dst 192.168.5.161 192.168.5.162 192.168.5.163
http_access allow manager localhost
http_access deny manager
http_access allow purge localhost
http_access deny purge
#http_access allow gsrc
#http_access allow gdst
#http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
#http_access deny all
snmp_port 3401
snmp_access allow SNMP CactiServer
snmp_access deny all
icp_access allow all
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
cache deny QUERY
visible_hostname parent.squid.com
cache_mgr zhengjun.zhu@tiancity.com
access_log /usr/local/squid/var/logs/access.log squid
#refresh_pattern ^ftp:          1440    20%     10080
#refresh_pattern ^gopher:       1440    0%      1440
refresh_pattern -i .html$       10      50%     20
acl apache rep_header Server ^Apache
broken_vary_encoding allow apache
coredump_dir /usr/local/squid/var/cache
cache_mem 64 MB
#negative_ttl 1 second
###################################################
http_port 80 accel vhost vport
icp_port 3130
cache_peer 192.168.5.162 parent 80 0 no-query originserver no-digest name=cache0
cache_peer 192.168.5.162 sibling 80 3130 name=cache1
cache_peer 192.168.5.163 sibling 80 3130 name=cache2
cache_peer 192.168.5.165 sibling 80 3130 name=cache3
cache_peer_domain cache0 [url]www.squid.com[/url]

acl Safe_ports port 80
acl Safe_ports port 3130
http_access deny !Safe_ports
negative_ttl 1 second
icp_query_timeout 2000
icp_access allow all
digest_generation on
log_icp_queries on
icp_hit_stale   on
web配置
在其加了一个mod_expires模块
ExpiresActive On
ExpiresDefault A600
发表在 article | 标签为 | squid集群配置已关闭评论

.NET 中多线程间资源共享与访问

翻译

vinodramakrishnan著Managing shared resource access in .NET multi-threading

简介

本文详细地描述一个定制的.NET类ThreadLockHelper(该类能在多线程环境下有效地共享资源),同时提供了.NET下多线程中资源共享及同步技术的概述。

文中给出的helper类,将会帮助并简化.NET框架下,高级程序员们对多线程的使用。本文也讲述如何在多线程之间同步资源的访问。

本文将引导你:
使用.NET线程threading模型在访问共享资源时,设计一个更好的加锁机制。设计并实现复杂多线程的解决方案。
我们假设你比较属性.NET开发组件,和基本的线程机制。

内容

概述在多线程中访问共享资源。
设计和实现ThreadLockHelper类。
使用ThreadLockHelper类的示例程序。

总结

在多线程中访问共享资源概述

使用多线程技术,可以使一个.NET程序同时执行多个任务。多线程允许你同时开启多个线程,分别执行不同任务;还能够提高程序的性能和响应时间。

因为多线程能够同时访问资源,所以最好在多线程间进行同步。当一个程序运行在多线程环境下的时候,它需要确保当一个线程挂起的时候,不应该还占用着对象(资源)。线程安全的基本含义是:当多线程同时访问时,对象的成员总是管理着一个有效状态,确保它们不会冲突。

.NET提供了不同的同步机制,以管理多线程的线程安全。

lock

lock是一个关键字,它通过给一个对象加锁,执行语句,解锁,把一段语句标志为临界区。

 

示例代码

lock(obj) { // code to be locked will go here }

Monitor

Monitor:Monitor类是用来同步实例中的方法或静态的方法。这个方法要依赖于一个object,也就是说,它不是在如int或string之类的值上加锁。该临界区通过调用Monitor.Enter()建立,并通过Monitor.Exit()释放。

示例代码:

try
 
{
    Monitor.Enter(obj);
{ 
    // code to be locked will go here

}
finally
{
    Monitor.Exit(obj);
}

Mutex

当位于进程之内或之间的线程需要访问操作系统的资源的时候,需要一个控制机制来限制资源访问的冲突。 System.Threading.Mutex是一个继承于WaitHandle的类,它必须实现一个信号量机制表明排他地占用或释放资源。同一时间,只能有一个线程占用Mutex。在访问资源之前,每个线程都通过发信号,以获得Mutex的控制权。此后,线程还必须等待资源的控制权。当线程完成操作时,通过ReleaseMutex()发出完成信号( lock和Monitor对于unmanaged 资源是不起作用的)。

示例代码:

Mutex objMutex = new
 Mutex(false
, "ThreadLock"
 );
objMutex.WaitOne();
// code to be locked will go here

objMutex.ReleaseMutex();

 

ThreadLockHelper类的设计和实现

ThreadLockHelper类

ThreadLockHelper class is a singleton implementation and only one instance will be taking care of locking threads for a process to be executed.

ThreadLockHelper类需要的命名空间

using
 System;
using
 System.Threading;
/// <summary>

/// 一个静态的用于对managed/unmanaged资源进行加锁的类

/// </summary>

public
 class
 ThreadLockHelper 
{
    static
 ThreadLockHelper mInstance = null;
    Mutex mMutex = null; 
    
    private
 ThreadLockHelper ()
    {
    }
    
    public
 static
 ThreadLockHelper GetInstance()
    {
      if
( mInstance == null )
      {
        mInstance = new
 ThreadLockHelper (); 
        mInstance.mMutex = new
 Mutex(false
, "ThreadLock"
 );
      }
      return
( mInstance );
    }
    
    
    public
 bool
 CreateLock()
    {
      if
 ( mMutex == null )
      {
        mMutex = new
 Mutex(false
, "ThreadLock"
); 
      }
      return
( mMutex.WaitOne() );
    }
    
    public
 void
 ReleaseLock()
    {
        mMutex.ReleaseMutex();
    } 
}

调用示例程序
在进程执行前创建一个ThreadLockHelper锁,在执行后,释放。

public
 class
 Activity
{
    public
 void
 InvokeTask()
    {
        Task objTask = new
 Task(); 
        ThreadLockHelper.GetInstance().CreateLock();
        objTask.DoTask();
        ThreadLockHelper.GetInstance().ReleaseLock();
    }
}

上面的程序中,objTask.DoTask()操作用于访问一个共享的资源(例如:调用一个web服务完成某些功能)

如果你在不同的线程中调用了上面的InvokeTask()方法,示例如下:

Activity objActivity = null;
Thread thdInvokeTask ;
for
(int
 i=1; i < 100 ; i++)
{
    objActivity = new
 Activity(); 
    thdInvokeTask = new
 Thread(new
 ThreadStart(objClsThread.InvokeTask));
    thdInvokeTask.Start(); 
}

在上面的场景中,如果你不采用加锁机制,应用程序就会因线程退出异常(thread abort exception)失败。

你可以在objTask.DoTask()方法中加入Web服务调用,来测试上面的场景。

总结

本文给你一些有效的线程同步管理方法。还提出如何实现一个有效管理共享资源的定制类(ThreadLockHelper)。

程序中的同步锁不应该使用太多,否则可能会影响性能。在需要加的地方加锁才是正确的。

关于原文作者vinodramakrishnan

(MCSD) working as an Architect in a leading software organization having more than 8 years core IT experience in Microsoft Technologies.
Click here(http://www.codeproject.com/script/profile/whos_who.asp?vt=arts&id=1801947
) to view vinodramakrishnan's online profile.
 

发表在 article | 标签为 | .NET 中多线程间资源共享与访问已关闭评论

Nginx 常见应用技术指南[Nginx Tips] 第二版

原文:http://www.linuxtone.org/html/85/t-1685.html

http://nginx.net/

作者:NetSeek  http://www.linuxtone.org
(IT运维专家网|集群架构|性能调优)
欢迎转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明.
首发时间: 2008-11-25     更新时间:2009-1-14

目 录
一、        Nginx 基础知识
二、        Nginx 安装及调试
三、        Nginx Rewrite
四、        Nginx Redirect
五、        Nginx 目录自动加斜线:
六、        Nginx Location
七、        Nginx expires
八、        Nginx 防盗链
九、        Nginx 访问控制
十、        Nginx日志处理
十一、     Nginx Cache
十二、     Nginx负载均衡
十三、       Nginx简单优化      
十四、        如何构建高性能的LEMP环境
十五、        Nginx服务监控
十六、        常见问题与错误处理.
十七、        相关资源下载

【前言】:
编写此技术指南在于推广普及NGINX在国内的使用,更方便的帮助大家了解和掌握NGINX的一些使用技巧。本指南很多技巧来自于网络和工作中或网络上朋友们问我的问题.在此对网络上愿意分享的朋友们表示感谢和致意!欢迎大家和我一起丰富本技术指南提出更好的建议!请朋友们关注: http://www.linuxtone.org
技术分享社区! 互想学习共同进步!

一、 Nginx 基础知识
1、简介
   Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。Igor 将源代码以类BSD许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。
更多的请见官方wiki: http://wiki.codemongers.com/

2、 Nginx的优点
nginx做为HTTP服务器,有以下几项基本特性:
1)        处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.
2)        无缓存的反向代理加速,简单的负载均衡和容错.
3)        FastCGI,简单的负载均衡和容错.
4)        模块化的结构。包括gzipping, byte ranges, chunked responses, 以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI,则这项处理可以并行运行,而不需要相互等待。
5)        支持SSL 和 TLS SNI.

Nginx专为性能优化而开发,性能是其最重要的考量, 实现上非常注重效率 。它支持内核Poll模型,能经受高负载的考验, 有报告表明能支持高达 50,000 个并发连接数。
Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上是毫无用处的。就稳定性而言, nginx比lighthttpd更胜一筹。
Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。
Nginx采用master-slave模型, 能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。
Nginx代码质量非常高,代码很规范, 手法成熟, 模块扩展也很容易。特别值得一提的是强大的Upstream与Filter链。 Upstream为诸如reverse proxy, 与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以把前一个filter的输出做为当前filter的输入,这有点像Unix的管线。这意味着,一个模块可以开始压缩从后端服务器发送过来的请求,且可以在模块接收完后端服务器的整个请求之前把压缩流转向客户端。
Nginx采用了一些os提供的最新特性如对sendfile (Linux 2.2+),accept-filter (FreeBSD 4.1+),TCP_DEFER_ACCEPT (Linux 2.4+) 的支持,从而大大提高了性能

二、 Nginx 安装及调试
1、Pcre 安装

CODE:

./configure
  make && make install
  cd ../

2.        nginx 编译安装

CODE:

./configure --user=www --group=www --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-openssl=/usr/local/openssl
make && make install

更详细的模块定制与安装请参照官方wiki.

3、Nginx 配置文件测试:

CODE:

# /usr/local/nginx/sbin/nginx -t  //Debug 配置文件的关键命令需要重点撑握.

2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf was tested successfully

3、Nginx 启动:

CODE:

# /usr/local/nginx/sbin/nginx
4、Nginx 配置文件修改重新加载:

CODE:

# kill -HUP `cat /usr/local/nginx/logs/nginx.pid
`
三、Nginx Rewrite

1.  Nginx Rewrite 基本标记(flags)
last - 基本上都用这个Flag。
※相当于Apache里的[L]标记,表示完成rewrite,不再匹配后面的规则
break - 中止Rewirte,不再继续匹配
redirect - 返回临时重定向的HTTP状态302
permanent - 返回永久重定向的HTTP状态301
      ※原有的url支持正则  重写的url不支持正则

2.  正则表达式匹配,其中:
    * ~         为区分大小写匹配
    * ~*       为不区分大小写匹配
    * !~和!~*   分别为区分大小写不匹配及不区分大小写不匹配

3. 文件及目录匹配,其中:
   * -f和!-f用来判断是否存在文件
    * -d和!-d用来判断是否存在目录
    * -e和!-e用来判断是否存在文件或目录
    * -x和!-x用来判断文件是否可执行

3.  Nginx 的一些可用的全局变量,可用做条件判断:

CODE:

$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri

四、 Nginx Redirect
将所有linuxtone.org与netseek.linuxtone.org域名全部自跳转到http://www.linuxtone.org

CODE:

server
{
listen 80;
server_name linuxtone.org netseek.linuxtone.org;
index index.html index.php;
root /data/www/wwwroot;
if ($host !~ "^www\.linxtone\.org$") {
rewrite ^(.*) http://www.linuxtone.org$1 redirect;
}
........................
}

五、 Nginx 目录自动加斜线:

CODE:

if (-d $request_filename){
           rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
     }

六  Nginx Location

1.基本语法:[和上面rewrite正则匹配语法基本一致]
location [=|~|~*|^~] /uri/ { … }
    * ~  为区分大小写匹配
    * ~* 为不区分大小写匹配
    * !~和!~*分别为区分大小写不匹配及不区分大小写不匹配

示例1:
location = / {
# matches the query / only.
# 只匹配 / 查询。
}
匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配

示例2:
location ^~ /images/ {
# matches any query beginning with /images/ and halts searching,
# so regular expressions will not be checked.
# 匹配任何已 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。

示例3:
location ~* \.(gif|jpg|jpeg)$ {
# matches any request ending in gif, jpg, or jpeg. However, all
# requests to the /images/ directory will be handled by
}
# 匹配任何已 gif、jpg 或 jpeg 结尾的请求。

七、 Nginx expires

1.根据文件类型expires

CODE:

# Add expires header for static content
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
    if (-f $request_filename) {
       root /data/www/wwwroot/bbs;
       expires      1d;
       break;
    }
}

2、根据判断某个目录

CODE:

# serve static files
location ~ ^/(images|javascript|js|css|flash|media|static)/  {
root    /data/www/wwwroot/down;
        expires 30d;
  }

八、  Nginx 防盗链

1.        针对不同的文件类型

CODE:

#Preventing hot linking of images and other file types
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {
        valid_referers none blocked server_names *.linuxtone.org linuxtone.org http://localhost baidu.com;
if ($invalid_referer) {
      rewrite   ^/   ;
     # return   403;
      }
}

2.        针对不同的目录

CODE:

location /img/ {
    root /data/www/wwwroot/bbs/img/;
    valid_referers none blocked server_names *.linuxtone.org http://localhost baidu.com;
    if ($invalid_referer) {
                   rewrite  ^/  ;
                   #return   403;
    }
}

3.        同实现防盗链和expires的方法

CODE:

#Preventing hot linking of images and other file types
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {
        valid_referers none blocked server_names *.linuxtone.org linuxtone.org http://localhost ;
if ($invalid_referer) {
      rewrite   ^/   ;
                     }
     access_log off;
     root /data/www/wwwroot/bbs;
expires 1d;
     break;
}

九、 Nginx 访问控制

1.        Nginx 身份证验证

CODE:

#cd /usr/local/nginx/conf
#mkdir htpasswd
/usr/local/apache2/bin/htpasswd -c /usr/local/nginx/conf/htpasswd/tongji linuxtone
#添加用户名为linuxtone
New password:   (此处输入你的密码)
Re-type new password:   (再次输入你的密码)
Adding password for user
http://count.linuxtone.org/tongji/data/index.html(目录存在/data/www/wwwroot/tongji/data/目录下)
将下段配置放到虚拟主机目录,当访问http://count.linuxtone/tongji/即提示要密验证:
location ~ ^/(tongji)/  {
                root    /data/www/wwwroot/count;
                        auth_basic              "LT-COUNT-TongJi";
                        auth_basic_user_file  /usr/local/nginx/conf/htpasswd/tongji;
                }

2.        Nginx 禁止访问某类型的文件.
如,Nginx下禁止访问*.txt文件,配置方法如下.

CODE:

location ~* \.(txt|doc)$ {
   if (-f $request_filename) {
   root /data/www/wwwroot/linuxtone/test;
   #rewrite …..可以重定向到某个URL
   break;
   }
}

方法2:

CODE:

location ~* \.(txt|doc)${
        root /data/www/wwwroot/linuxtone/test;
        deny all;
}

实例:
禁止访问某个目录

CODE:

location ~ ^/(WEB-INF)/ {
            deny all;
}  

3.        使用ngx_http_access_module限制ip访问

CODE:

location / {
    deny    192.168.1.1;
    allow   192.168.1.0/24;
    allow   10.1.1.0/16;
    deny    all;
}

详细参见wiki: http://wiki.codemongers.com/NginxHttpAccessModule#allow

4.        Nginx 下载限制并发和速率

CODE:

limit_zone   linuxtone  $binary_remote_addr  10m;
server
       {
               listen       80;
               server_name  down.linuxotne.org;
               index index.html index.htm index.php;
               root   /data/www/wwwroot/down;
               #Zone limit
               location / {
                   limit_conn   linuxtone  1;
                   limit_rate  20k;
               }
..........
       }

只允许客房端一个线程,每个线程20k.
【注】limit_zone   linuxtone  $binary_remote_addr  10m; 这个可以定义在主的

5.        Nginx 实现Apache一样目录列表

CODE:

location  /  {
    autoindex  on;
}

6.        上文件大小限制
主配置文件里加入如下,具体大小根据你自己的业务做调整。
client_max_body_size 10m;                                                         

十、        Nginx 日志处理

1.Nginx 日志切割
#contab -e
59 23 * * * /usr/local/sbin/logcron.sh /dev/null 2>&1
[root@count ~]# cat /usr/local/sbin/logcron.sh

CODE:

#!/bin/bash
log_dir="/data/logs"
time=`date +%Y%m%d`  
/bin/mv  ${log_dir}/access_linuxtone.org.log ${log_dir}/access_count.linuxtone.org.$time.log
kill -USR1 `cat  /var/run/nginx.pid`

更多的日志分析与处理就关注(同时欢迎你参加讨论):http://bbs.linuxtone.org/forum-8-1.html

2.利用AWSTATS分析NGINX日志
  设置好Nginx日志格式,仍后利用awstats进行分析.
请参考: http://bbs.linuxtone.org/thread-56-1-1.html

3.        Nginx 如何不记录部分日志
日志太多,每天好几个G,少记录一些,下面的配置写到server{}段中就可以了
location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$
{
     access_log off;
}

十一、Nginx Cache服务配置

如果需要将文件缓存到本地,则需要增加如下几个子参数:

CODE:

proxy_store on;
proxy_store_access user:rw group:rw all:rw;
proxy_temp_path 缓存目录;

其中,
proxy_store on用来启用缓存到本地的功能,
proxy_temp_path用来指定缓存在哪个目录下,如:proxy_temp_path html;

在经过上一步配置之后,虽然文件被缓存到了本地磁盘上,但每次请求仍会向远端拉取文件,为了避免去远端拉取文件,必须修改

CODE:

proxy_pass:
if ( !-e $request_filename) {
    proxy_pass  http://mysvr;
}

即改成有条件地去执行proxy_pass,这个条件就是当请求的文件在本地的proxy_temp_path指定的目录下不存在时,再向后端拉取。

   
更多更高级的应用可以研究ncache,详细请参照http://bbs.linuxtone.org
里ncache相关的贴子.

十二、Nginx 负载均衡
1. Nginx 负载均衡基础知识
nginx的upstream目前支持4种方式的分配
1)、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
2)、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
3)、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash(第三方)

2.        Nginx 负载均衡实例1

CODE:

upstream bbs.linuxtone.org {#定义负载均衡设备的Ip及设备状态
    server 127.0.0.1:9090 down;
    server 127.0.0.1:8080 weight=2;
    server 127.0.0.1:6060;
    server 127.0.0.1:7070 backup;
}

在需要使用负载均衡的server中增加
proxy_pass http://bbs.linuxtone.org/
;

每个设备的状态设置为:
a)        down 表示单前的server暂时不参与负载
b)        weight 默认为1.weight越大,负载的权重就越大。
c)        max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
d)        fail_timeout:max_fails次失败后,暂停的时间。
e)        backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

nginx支持同时设置多组的负载均衡,用来给不用的server来使用。

client_body_in_file_only 设置为On 可以讲client post过来的数据记录到文件中用来做debug
client_body_temp_path 设置记录文件的目录 可以设置最多3层目录
location 对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡

3.        Nginx 负载均衡实例 2
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效,也可以用作提高Squid缓存命中率.

简单的负载均等实例:
#vi nginx.conf  //nginx主配置文件核心配置

CODE:

……….
#loadblance my.linuxtone.org
       upstream  my.linuxtone.org  {
       ip_hash;
       server   127.0.0.1:8080;
       server   192.168.169.136:8080;
       server   219.101.75.138:8080;
       server   192.168.169.117;
       server   192.168.169.118;
       server   192.168.169.119;
     }
…………..
include          vhosts/linuxtone_lb.conf;
………
# vi proxy.conf
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 50m;
client_body_buffer_size 256k;
proxy_connect_timeout 30;
proxy_send_timeout 30;
proxy_read_timeout 60;

proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
proxy_max_temp_file_size 128m;
proxy_store on;
proxy_store_access   user:rw  group:rw  all:r;
#nginx cache               
#client_body_temp_path  /data/nginx_cache/client_body 1 2;
proxy_temp_path /data/nginx_cache/proxy_temp 1 2;

#vi  linuxtone_lb.conf

CODE:

server
    {
        listen  80;
        server_name my.linuxtone.org;
        index index.php;
        root /data/www/wwwroot/mylinuxtone;
        if (-f $request_filename) {
            break;
           }
        if (-f $request_filename/index.php) {
          rewrite (.*) $1/index.php break;
        }

        error_page 403 http://my.linuxtone.org/member.php?m=user&a=login;
        location / {
           if ( !-e $request_filename) {
               proxy_pass http://my.linuxtone.org;
               break;
           }
           include /usr/local/nginx/conf/proxy.conf;
        }
}

十三、Nginx简单优化

1.        减小nginx编译后的文件大小 (Reduce file size of nginx)
默认的nginx编译选项里居然是用debug模式(-g)的(debug模式会插入很多跟踪和ASSERT之类),编译以后一个nginx有好几兆。去掉nginx的debug模式编译,编译以后只有几百K
在 auto/cc/gcc,最后几行有:
# debug

CODE:

CFLAGS=”$CFLAGS -g”
注释掉或删掉这几行,重新编译即可。

2.        修改Nginx的header伪装服务器
1)        修改nginx.h

CODE:

#vi nginx-0.7.30/src/core/nginx.h
#define NGINX_VERSION      "1.8"
#define NGINX_VER          "LTWS/" NGINX_VERSION

#define NGINX_VAR          "NGINX"
#define NGX_OLDPID_EXT     ".oldbin"

2) 修改nginx_http_header_filter_module
#vi nginx-0.7.30/src/http/ngx_http_header_filter_module.c
将如下

CODE:

static char ngx_http_server_string[] = "Server: nginx" CRLF;
修改为

CODE:

static char ngx_http_server_string[] = "Server: LTWS" CRLF;
a)        修改nginx_http_header_filter_module
#vi nginx-0.7.30/src/http/ngx_http_special_response.c
将如下:

CODE:

static u_char ngx_http_error_full_tail[] =
"<hr><center>" NGINX_VER "</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

CODE:

static u_char ngx_http_error_tail[] =
"<hr><center>nginx</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

修改为:

CODE:

static u_char ngx_http_error_full_tail[] =
"<center> "NGINX_VER" </center>" CRLF
"<hr><center>http://www.linuxtone.org</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

static u_char ngx_http_error_tail[] =
"<hr><center>LTWS</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

修改后重新编译一下环境,
404错误的时候显示效果图(如果没有指定错误页的话):
 


404.png

利用curl命令查看服务器header
 


curl.png

3.为特定的CPU指定CPU类型编译优化.
默认nginx使用的GCC编译参数是-O
需要更加优化可以使用以下两个参数
--with-cc-opt='-O3' \
--with-cpu-opt=opteron \
使得编译针对特定CPU以及增加GCC的优化.
此方法仅对性能有所改善并不会有很大的性能提升,供朋友们参考.
CPUD类型确定: # cat /proc/cpuinfo | grep "model name"
编译优化参数参考:http://en.gentoo-wiki.com/wiki/Safe_Cflags

4.Tcmalloc优化Nginx 性能

CODE:

# wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-alpha.tar.gz
# tar zxvf libunwind-0.99-alpha.tar.gz
# cd libunwind-0.99-alpha/
# CFLAGS=-fPIC ./configure
# make CFLAGS=-fPIC
# make CFLAGS=-fPIC install
# wget http://google-perftools.googlecode.com/files/google-perftools-0.98.tar.gz
# tar zxvf google-perftools-0.98.tar.gz
# cd google-perftools-0.98/
# ./configure
# make && make install
# echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
# ldconfig
# lsof -n | grep tcmalloc

编译nginx 加载google_perftools_module:
./configure --with-google_perftools_module
在主配置文件加入nginx.conf 添加:
google_perftools_profiles /path/to/profile;

5.内核参数优化
# vi /etc/sysctl.conf   #在末尾增加以下内容:

CODE:

net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000

#使配置立即生效
/sbin/sysctl -p

十四、如何构建高性的LEMP
请参见: http://www.linuxtone.org/lemp/lemp.pdf

1、提供完整的配置脚本下载:http://www.linuxtone.org/lemp/scripts.tar.gz

2、提供NGINX常见配置范例含(虚拟主机,防盗链,Rewrite,访问控制,负载均衡
Discuz相关程序静态化及等等),你只要稍稍修改即可线上应用。 3、将原版的xcache替换成EA,并提供相关简单调优脚本及配置文件。
更多的及更新资料请关注: http://www.linuxtone.org

十五、Nginx监控
1、        RRDTOOL+Perl脚本画图监控
先安装好rrdtool ,关于rrdtool本文不作介绍,具体安装请参照linuxtone监控版块.
#cd /usr/local/sbnin
#wget http://blog.kovyrin.net/files/mrtg/rrd_nginx.pl.txt

#mv rrd_nginx.pl.txt rrd_nginx.pl
#chmod a+x rrd_nginx.pl

#vi rrd_nginx.pl   //配置脚本文件设置好路径
#!/usr/bin/perl
use RRDs;
use LWP::UserAgent;

# define location of rrdtool databases
my $rrd = '/data/www/wwwroot/nginx/rrd';
# define location of images
my $img = '/data/www/wwwroot/nginx/html';
# define your nginx stats URL
my $URL = "http://219.232.244.13/nginx_status";
…………
【注】根据自己具体的状况修改相应的路径.
#crontab –e //加入如下
* * * * * /usr/local/sbin/rrd_nginx.pl
重启crond后,通过配置nginx虚拟主机指到/data/www/wwwroot/nginx/html目录,通过crond自动执行perl脚本会生成很多图片.
http://xxx/connections-day.png即可看到服务器状态图。

2、        官方Nginx-rrd 监控服务(多虚拟主机)(推荐)
网址:http://www.nginx.eu/nginx-rrd.html

此解决方案其实是基于上述监控方案的一个改进和增强,同样先安装好rrdtool这个画图工具和相应的perl模块再做如下操作:
# yum install perl-HTML*
先建立好生成的库存和图片存放录

CODE:

#mkdir -p /data/www/wwwroot/nginx/{rrd,html}

#cd /usr/local/sbin
#wget http://www.nginx.eu/nginx-rrd/nginx-rrd-0.1.4.tgz
#tar zxvf nginx-rrd-0.1.4.tgz
#cd nginx-rrd-0.1.4
#cd etc/
#cp nginx-rrd.conf /etc
#cd etc/cron.d
#cp nginx-rrd.cron /etc/cron.d

#cd /usr/local/src/nginx-rrd-0.1.4/html
# cp index.php /data/www/wwwroot/nginx/html/

#cd /usr/local/src/nginx-rrd-0.1.4/usr/sbin
#cp * /usr/sbin/

#vi /etc/nginx-rrd.conf

CODE:

#####################################################
#
# dir where rrd databases are stored
RRD_DIR="/data/www/wwwroot/nginx/rrd";
# dir where png images are presented
WWW_DIR="/data/www/wwwroot/nginx/html";
# process nice level
NICE_LEVEL="-19";
# bin dir
BIN_DIR="/usr/sbin";
# servers to test
# server_utl;server_name
SERVERS_URL="http://219.32.205.13/nginx_status;219.32.205.13  http://www.linuxtone.org/nginx_status;www.linuxtone.org""

//根据你的具体情况做调整.
SEVERS_URL 格式 http://domain1/nginx_status;domain1 http://domain2/nginx_status;domain2
这种格式监控多虚拟主机连接状态:
重点启crond服务,仍后通过http://219.32.205.13/nginx/html/
即可访问。配置过程很简单!

3、        CACTI模板监控Nginx
利用Nginx_status状态来画图实现CACTI监控
nginx编译时允许http_stub_status_module

# vi /usr/local/nginx/conf/nginx.conf

CODE:

location /nginx_status {
stub_status on;
access_log off;
allow 192.168.1.37;
deny all;
}

CODE:

# kill -HUP `cat /usr/local/nginx/logs/nginx.pid`

# wget http://forums.cacti.net/download.php?id=12676
# tar xvfz cacti-nginx.tar.gz
# cp cacti-nginx/get_nginx_socket_status.pl /data/cacti/scripts/
# cp cacti-nginx/get_nginx_clients_status.pl /data/cacti/scripts/
# chmod 755 /data/cacti/scripts/get_nginx*

检测插件

CODE:

# /data/cacti/scripts/get_nginx_clients_status.pl http://192.168.1.37/nginx_status
在cacti管理面板导入
cacti_graph_template_nginx_clients_stat.xml
cacti_graph_template_nginx_sockets_stat.xml

十六、常见问题与错误处理
1、400 bad request错误的原因和解决办法
配置nginx.conf相关设置如下.
client_header_buffer_size 16k;
large_client_header_buffers 4 64k;
根据具体情况调整,一般适当调整值就可以。

2、Nginx 502 Bad Gateway错误
proxy_next_upstream error timeout invalid_header http_500 http_503;
或者尝试设置:
large_client_header_buffers 4 32k;

3、Nginx出现的413 Request Entity Too Large错误
这个错误一般在上传文件的时候会出现,
编辑Nginx主配置文件Nginx.conf,找到http{}段,添加
client_max_body_size 10m; //设置多大根据自己的需求作调整.
如果运行php的话这个大小client_max_body_size要和php.ini中的如下值的最大值一致或者稍大,这样就不会因为提交数据大小不一致出现的错误。
post_max_size = 10M
upload_max_filesize = 2M

4、解决504 Gateway Time-out(nginx)
遇到这个问题是在升级discuz论坛的时候遇到的
一般看来, 这种情况可能是由于nginx默认的fastcgi进程响应的缓冲区太小造成的, 这将导致fastcgi进程被挂起, 如果你的fastcgi服务对这个挂起处理的不好, 那么最后就极有可能导致504 Gateway Time-out
现在的网站, 尤其某些论坛有大量的回复和很多内容的, 一个页面甚至有几百K。
默认的fastcgi进程响应的缓冲区是8K, 我们可以设置大点
在nginx.conf里, 加入: fastcgi_buffers 8 128k
这表示设置fastcgi缓冲区为8×128k
当然如果您在进行某一项即时的操作, 可能需要nginx的超时参数调大点,例如设置成60秒:send_timeout 60;
只是调整了这两个参数, 结果就是没有再显示那个超时, 可以说效果不错, 但是也可能是由于其他的原因, 目前关于nginx的资料不是很多, 很多事情都需要长期的经验累计才有结果, 期待您的发现哈!

5、如何使用Nginx Proxy
朋友一台服务器运行tomcat 为8080端口,IP:192.168.1.2:8080,另一台机器IP:192.168.1.8. 朋友想通过访问http://192.168.1.8
即可访问tomcat服务.配置如下:
在192.168.1.8的nginx.conf上配置如下:

CODE:

server {
listen 80;
server_name java.linuxtone.org
location / {
proxy_pass http://192.168.1.2:8080;
include /usr/local/nginx/conf/proxy.conf;
}
}

6、如何关闭Nginx的LOG
access_log /dev/null; error_log /dev/null;

十七、相关资源下载

1.nginx配置示例及脚本下载:
# wget http://www.linuxtone.org/lemp/scripts.tar.gz
#此脚本范例定期更新.
--------------------------------------------------------------------------------------------------------------

Nginx作为一个后起之秀,他的迷人之处已经让很多人都投入了他的怀抱。配置简单,实现原理简单。做一个负载平衡的再好不过了。

其原理:

简单介绍一下他的安装及配置过程

官方网站
http://wiki.codemongers.com/Main

一、依赖的程序

1. gzip module requires zlib library
2. rewrite module requires pcre library
3. ssl support requires openssl library

二、安装
./configure
make
make install

默认安装的路径是/usr/local/nginx

更多的安装配置
./configure --prefix=/usr/local/nginx
--with-openssl=/usr/include (启用ssl)
--with-pcre=/usr/include/pcre/ (启用正规表达式)
--with-http_stub_status_module (安装可以查看nginx状态的程序)
--with-http_memcached_module (启用memcache缓存)
--with-http_rewrite_module (启用支持url重写)

三、启动及重启
启动:nginx
重启:kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
测试配置文件:nginx -t

简单吧,安装,启动都比较方便。

四、配置文件
http://wiki.codemongers.com/NginxFullExample

#运行用户

user  nobody nobody;

#启动进程

worker_processes  5;

#全局错误日志及PID文件


error_log  logs/error.log notice;

pid        logs/nginx.pid;

#工作模式及连接数上限

events {

  #工作模式有:select(标准模式),poll
(标准模式),
kqueue(高效模式,适用FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 and MacOS X),

  #epoll(高效模式,本例用的。适用Linux 2.6+,SuSE 8.2,),/dev/poll(高效模式,适用Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+)

  use epoll;

  worker_connections      1024;

}

#设定http服务器,利用它的反向代理功能提供负载均衡支持

http {

  #设定mime类型

  include      conf/mime.types;

  default_type  application/octet-stream;

  #设定日志格式

  log_format main        '$remote_addr - $remote_user [$time_local] '

                         '"$request" $status $bytes_sent '

                         '"$http_referer" "$http_user_agent" '

                         '"$gzip_ratio"';
  log_format download    '$remote_addr - $remote_user [$time_local] '

                         '"$request" $status $bytes_sent '

                         '"$http_referer" "$http_user_agent" '

                         '"$http_range" "$sent_http_content_range"';

  #设定请求缓冲

  client_header_buffer_size    10k;

  large_client_header_buffers  4 4k;

  

  #开启gzip模块,要求安装gzip 在运行./config时要指定

  gzip on;

  gzip_min_length  1100;

  gzip_buffers    4 8k;

  gzip_types      text/plain;

  output_buffers  1 32k;

  postpone_output  1460;

  

  #设定访问日志

  access_log  logs/access.log  main;

  client_header_timeout  3m;

  client_body_timeout    3m;

  send_timeout          3m;

  sendfile                on;

  tcp_nopush              on;

  tcp_nodelay            on;

  keepalive_timeout  65;

  

  #设定负载均衡的服务器列表

  upstream backserver {

  #weigth参数表示权值,权值越高被分配到的几率越大

  #本例是指在同一台服务器,多台服务器改变ip即可

  server 127.0.0.1:8081 weight=5;

  server 127.0.0.1:8082;

  server 127.0.0.1:8083;

  }
  #设定虚拟主机,默认为监听80端口,改成其他端口会出现问题

  server {

    listen         80;

    server_name    test.com

 www.test.com

;

    charset utf8;

    #设定本虚拟主机的访问日志

    access_log  logs/test.com.log  main;

    #如果访问 /images/*, /js/*, /css/* 资源,则直接取本地文件,不用转发。但如果文件较多效果不是太好。

    location ~ ^/(images|js|css)/  {

        root    /usr/local/testweb;

        expires 30m;

    }

    

    #对 "/" 启用负载均衡

    location / {

       proxy_pass      http://backserver

;

       proxy_redirect          off;

       proxy_set_header        Host $host;

       proxy_set_header        X-Real-IP $remote_addr;

       proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

       client_max_body_size    10m;

       client_body_buffer_size 128k;

       proxy_connect_timeout  90;

       proxy_send_timeout      90;

       proxy_read_timeout      90;

       proxy_buffer_size      4k;

       proxy_buffers          4 32k;

       proxy_busy_buffers_size 64k;

       proxy_temp_file_write_size 64k;

    }

    #设定查看Nginx状态的地址,在运行./config 要指定,默认是不安装的。

    location /NginxStatus {

       stub_status            on;

       access_log              on;

       auth_basic              "NginxStatus";

       #是否要通过用户名和密码访问,测试时可以不加上。conf/htpasswd 文件的内容用 apache
 提供的 htpasswd 工具来产生即可       

       #auth_basic_user_file  conf/htpasswd;

    }

}

 

发表在 web server | 标签为 | 30条评论

MyISAM InnoDB 存储引擎的比较和事务的概念

MyISAM InnoDB 存储引擎的比较和事务的概念

一、两种引擎的应用方式和区别:
MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的 顺序访问方法) 的缩写,它是存储记录和文件的标准方法.与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具. MyISAM表格可以被压缩,而且它们支持全文搜索.但它不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚,不具有原子性。如果执行大量的SELECT,MyISAM是更好的选择。

InnoDB:这种类型是事务安全的.它与BDB类型具有相同的特性,它还支持外键.InnoDB表格速度很快.具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它.如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表,对于支持事务的InnoDB类型的表,影响速度的主要原因是AUTOCOMMIT默认设置是打开的,而且程序没有显式调用BEGIN 开始事务,导致每插入一条都自动Commit,严重影响了速度。可以在执行sql前调用begin,多条sql形成一个事物(即使autocommit打开也可以),将大大提高性能。

二、事务的概念:

  事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元。事务通常由高级数据库操纵语言或编程语言书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句来界定。事务由事务开始和事务结束之间执行的全体操作组成。

三、事务的四大特性:

(1) 原子性
  事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。这种特性称为原子性。 

(2) 一致性
    事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。一致性和事务的原子性是密不可分的。

(3) 分离性
  分离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。

(4)持久性
  持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。即一旦一个事务提交,DBMS保证它对数据库中数据的改变应该是永久性的,耐得住任何系统故障。持久性通过数据库备份和恢复来保证。

四、为什么要使用事务:

我们用一个简单的例子来说明这个问题,比如我到银行去存钱,于是有这么几个步骤:
1、把钱交给工作人员;2、工作人员填单;3、将单子给我签字;4、工作人员确认并输入电脑。
  在这个事务进行的过程中,要是我把钱交给工作人员之后,进行到步骤3我签玩字,银行工作人员突发心脏病挂掉了,那,我的钱还没有被输入电脑,但我却交了钱又签字确认了,这时候我岂不是要亏死了?我肯定会要求银行回退这次事务,把钱还给我,要么由银行其他人员帮我输入电脑,完成本次事务。

    当然,这个是在有人工操作的时候进行的,我们可以要求银行做到交易的完整性。但是如果我们用自动存款机存钱的时候,机器在处理到我确认存款但还没有将记录真正提交到数据库的时候,突然因为断电或其他未知故障而突然停止,这时我该怎么办?

   于是,在数据库里产生了这么一个术语:事务(Transaction),也就是要么成功,要么失败,并恢复原状。

五、在MySQL中体验事务的过程:

1. 4.0以上mysqld都支持事务,包括非max版本。3.23的需要max版本mysqld才能支持事务。可以用show engines 来查看mysql支持的引擎:

mysql> show engines;
+------------+----------+----------------------------------------------------------------+--------------+-----+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+------------+----------+----------------------------------------------------------------+--------------+-----+------------+
| ndbcluster | DISABLED | Clustered, fault-tolerant tables | YES | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| FEDERATED | YES | Federated MySQL storage engine | YES | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| InnoDB | YES | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| MyISAM | DEFAULT | Default engine as of MySQL 3.23 with great performance | NO | NO | NO |
+------------+----------+----------------------------------------------------------------+--------------+-----+------------+
 

2. 创建表时如果不指定type则默认为myisam,不支持事务。
存储引擎是针对表对象来说的,可以用 show create table tablename 命令看表的类型。

mysql> show create table aa;
+-------+-------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------+
| aa | CREATE TABLE `aa` (
  `a` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+-------+-------------------------------------------------------------------------------------------+
 

3、 对不支持事务的表做start/commit操作没有任何效果,在执行commit前已经提交,但在支持事务的表里则必须 commit后才能生效:

use test;
drop table if exists aa;
create table aa (a varchar(10)) type=myisam;
drop table if exists bb;
create table bb (a varchar(10)) type=innodb;

insert into aa values('a');
insert into bb values('a');
select * from aa;
select * from bb;

验证:虽然还没有进行commit操作,但是这时两个表都能看到一条记录,根据事务的定义必须使用类似于 BEGAN END 的语句块来执行一个事务,如果程序没有显式调用BEGIN 开始事务,在Innodb中每插入一条记录都会自动Commit。

use test;
begin;
insert into aa values('aaaa');
insert into bb values('aaaa');
select * from aa;
select * from bb;

验证:在begin的语句块中执行事务操作,虽然还没有进行commit操作,但是aa表已经能看到增加了一条新的记录,但bb表还没有.

commit;

验证:在begin执行的当前窗口后执行commit命令后,再次查看bb表,新的记录也添加进去了。

 

 

注意:commit必须和begin对应起来,中间封装一个事务,如果关掉执行了begin但尚未执行commit的窗口,在其他窗口执行commit操作,这时数据库认为这个事务在执行的某个过程中失败,所以整个事务都会失败!

 

 

六、Mysql表引擎的切换:

1. 可以执行以下命令来切换非事务表到事务(数据不会丢失),innodb表比myisam表更安全:
   alter table tablename type=innodb;

2. innodb表不能用repair table命令和myisamchk -r table_name
但可以用check table,以及mysqlcheck [OPTIONS] database [tables]

3. 启动mysql数据库的命令行中添加了以下参数可以使新发布的mysql数据表都默认为使用事务(只影响到create语句。)
--default-table-type=InnoDB

4. 临时改变默认表类型可以用:
set table_type=InnoDB;
show variables like 'table_type';
show engines;

------------------------------------------------------------------------------------------------------------------------------------------------

Mysql的transaction实现 收藏
 transaction在数据库编程中是一个重要的概念,这样做可以控制对数据库操作的事务提交。
但是要想在程序中实现事务,要求数据库本身支持事务。
现在的关系型数据库,我们日常使用的mysql,oracle等等都支持事务,有的是安装后直接就支持,有的需要做一些设置。
这篇文章是针对mysql的,讲述从数据库安装,设置,一直到sql语句,甚至到java程序中,如何实现transaction。
1.安装
要想在mysql的表中支持transaction,必须要求是innodb表。普通表使用的autocommit模式,会自动提交每一条sql语句,不能算是transaction吧。
安装时要指定mysql支持innodb,./configure --with-innodb。

2.配置
安装后,可以对innodb做一些配置,在my.cnf或my.ini中的[mysqld]段。
#存储目录,如果不指定默认为安装的data目录,为空时以innodb_data_file_path指定路径为准
innodb_data_home_dir =
#数据文件名及大小,默认为ibdata1,10m大小。autoextend可以自增,max:2000M文件最大2g,因为有的硬盘有2g文件大小限制。
innodb_data_file_path = ibdata1:2000M;ibdata2:2000M:autoextend:max:2000M
# 设置缓冲池大小
set-variable = innodb_buffer_pool_size=70M
set-variable = innodb_additional_mem_pool_size=10M
#设置日志文件路径,默认在date目录下,名称为ib_logfile...
innodb_log_group_home_dir =
#设置日志文件数目,默认为3
set-variable = innodb_log_files_in_group=3
# 设置日志文件大小
set-variable = innodb_log_file_size=10M
# 设置日志缓冲大小
set-variable = innodb_log_buffer_size=8M
# 任何事务提交前写入日志,方便故障诊断,请设为1。如果丢失最近的几个事务影响不大的话,设置为0(默认值)。
innodb_flush_log_at_trx_commit=1
#设置超时时间
set-variable = innodb_lock_wait_timeout=50

注意:innodb不会自动生成目录,上面所有指定目录要手工生成。默认不用。

完整的配置参数如下表(下表引自http://man.chinaunix.net/database/mysql/inonodb_zh/2.htm#InnoDB_start
):

  innodb_data_home_dir
 这是InnoDB表的目录共用设置。如果没有在 my.cnf 进行设置,InnoDB 将使用MySQL的 datadir 目录为缺省目录。如果设定一个空字串,可以在 innodb_data_file_path 中设定绝对路径。
 
innodb_data_file_path
 单独指定数据文件的路径与大小。数据文件的完整路径由 innodb_data_home_dir 与这里所设定值的组合。 文件大小以 MB 单位指定。因此在文件大小指定后必有“M”。 InnoDB 也支持缩写“G”, 1G = 1024M。从 3.23.44 开始,在那些支持大文件的操作系统上可以设置数据文件大小大于 4 GB。而在另一些操作系统上数据文件必须小于 2 GB。数据文件大小总和至少要达到 10 MB。在 MySQL-3.23 中这个参数必须在 my.cnf 中明确指定。在 MySQL-4.0.2 以及更新版本中则不需如此,系统会默认在 MySQL 的 datadir 目录下创建一个 16 MB 自扩充(auto-extending)的数据文件 ibdata1。你同样可以使用一个 原生磁盘分区(RAW raw disk partitions(raw devices)) 作为数据文件, 如何在 my.cnf 中详细指定它们请查看第 12.1 节。
 
innodb_mirrored_log_groups
 为了保护数据而设置的日志文件组的拷贝数目,默认设置为 1。在 my.cnf 中以数字格式设置。
 
innodb_log_group_home_dir
 InnoDB 日志文件的路径。必须与 innodb_log_arch_dir 设置相同值。 如果没有明确指定将默认在 MySQL 的 datadir 目录下建立两个 5 MB 大小的 ib_logfile... 文件。
 
innodb_log_files_in_group
 日志组中的日志文件数目。InnoDB 以环型方式(circular fashion)写入文件。数值 3 被推荐使用。在 my.cnf 中以数字格式设置。
 
innodb_log_file_size
 日志组中的每个日志文件的大小(单位 MB)。如果 n 是日志组中日志文件的数目,那么理想的数值为 1M 至下面设置的缓冲池(buffer pool)大小的 1/n。较大的值,可以减少刷新缓冲池的次数,从而减少磁盘 I/O。但是大的日志文件意味着在崩溃时需要更长的时间来恢复数据。 日志文件总和必须小于 2 GB,3.23.55 和 4.0.9 以上为小于 4 GB。在 my.cnf 中以数字格式设置。
 
innodb_log_buffer_size
 InnoDB 将日志写入日志磁盘文件前的缓冲大小。理想值为 1M 至 8M。大的日志缓冲允许事务运行时不需要将日志保存入磁盘而只到事务被提交(commit)。 因此,如果有大的事务处理,设置大的日志缓冲可以减少磁盘I/O。 在 my.cnf 中以数字格式设置。
 
innodb_flush_log_at_trx_commit
 通常设置为 1,意味着在事务提交前日志已被写入磁盘, 事务可以运行更长以及服务崩溃后的修复能力。如果你愿意减弱这个安全,或你运行的是比较小的事务处理,可以将它设置为 0 ,以减少写日志文件的磁盘 I/O。这个选项默认设置为 0。
 
innodb_log_arch_dir
 The directory where fully written log files would be archived if we used log archiving. 这里设置的参数必须与 innodb_log_group_home_dir 相同。 从 4.0.6 开始,可以忽略这个参数。
 
innodb_log_archive
 这个值通常设为 0。 既然从备份中恢复(recovery)适合于 MySQL 使用它自己的 log files,因而通常不再需要 archive InnoDB log files。这个选项默认设置为 0。
 
innodb_buffer_pool_size
 InnoDB 用来高速缓冲数据和索引内存缓冲大小。 更大的设置可以使访问数据时减少磁盘 I/O。在一个专用的数据库服务器上可以将它设置为物理内存的 80 %。 不要将它设置太大,因为物理内存的使用竞争可能会影响操作系统的页面调用。在 my.cnf 中以数字格式设置。
 
innodb_additional_mem_pool_size
 InnoDB 用来存储数据字典(data dictionary)信息和其它内部数据结构(internal data structures)的存储器组合(memory pool)大小。理想的值为 2M,如果有更多的表你就需要在这里重新分配。如果 InnoDB 用尽这个池中的所有内存,它将从操作系统中分配内存,并将错误信息写入 MySQL 的错误日志中。在 my.cnf 中以数字格式设置。
 
innodb_file_io_threads
 InnoDB 中的文件 I/O 线程。 通常设置为 4,但是在 Windows 下可以设定一个更大的值以提高磁盘 I/O。在 my.cnf 中以数字格式设置。
 
innodb_lock_wait_timeout
 在回滚(rooled back)之前,InnoDB 事务将等待超时的时间(单位 秒)。InnoDB 会自动检查自身在锁定表与事务回滚时的事务死锁。如果使用 LOCK TABLES 命令,或在同一个事务中使用其它事务安全型表处理器(transaction safe table handlers than InnoDB),那么可能会发生一个 InnoDB 无法注意到的死锁。在这种情况下超时将用来解决这个问题。这个参数的默认值为 50 秒。在 my.cnf 中以数字格式设置。
 
innodb_flush_method
 这个参数仅仅与 Unix 相关。这个参数默认值为 fdatasync。 另一个设置项为 O_DSYNC。这仅仅影响日志文件的转储,在 Unix 下以 fsync 转储数据。InnoDB 版本从 3.23.40b 开始,在 Unix 下指定 fdatasync 为使用 fsync 方式、指定 O_DSYNC 为使用 O_SYNC 方式。由于这在某些 Unix 环境下还有些问题所以在 'data' versions 并没有被使用。
 
innodb_force_recovery
 警告:此参数只能在你希望从一个被损坏的数据库中转储(dump)数据的紧急情况下使用! 可能设置的值范围为 1 - 6。查看下面的章节 'Forcing recovery' 以了解这个参数的具体含义。参数设置大于 0 的值代表着 InnoDB 防止用户修改数据的安全度。从 3.23.44 开始,这个参数可用。在 my.cnf 中以数字格式设置。
 
innodb_fast_shutdown
 InnoDB 缺少在关闭之前清空插入缓冲。这个操作可能需要几分钟,在极端的情况下可以需要几个小时。如果这个参数据设置为 1 ,InnoDB 将跳过这个过程而直接关闭。从 3.23.44 和 4.0.1 开始,此参数可用。从 3.23.50 开始,此参数的默认值为 1。
 
innodb_thread_concurrency
 InnoDB 会试图将 InnoDB 服务的使用的操作系统进程小于或等于这里所设定的数值。此参数默认值为 8。如果计算机系统性能较低或 innodb_monitor 显示有很多线程等侍信号,应该将这个值设小一点。如果你的计算机系统有很我的处理器与磁盘系统,则可以将这个值设高一点以充分利用你的系统资源。建议设值为处理器数目+ 磁盘数目。 从 3.23.44 和 4.0.1 开始,此参数可用。在 my.cnf 中以数字格式设置。
 

innodb还需要使用二进制日志文件:

log-bin指定二进制文件名称,不指定默认生成。
log-bin-index 可以指定索引文件。
使用 binlog-do-db可以指定记录的数据库。
使用 binlog-ignore-db可以指定不记录的数据库。
注意的是: binlog-do-db 和binlog-ignore-db 一次只指定一个数据库,指定多个数据库需要多个语句。而且,MySQL会将所有的数据库名称改成小写, 在指定数据库时必须全部使用小写名字,否则不会起作用。

3.添加表
CREATE TABLE user (id INT NOT NULL AUTO_INCREMENT,PRIMARY KEY,fname VARCHAR(15),sname VARCHAR(20),sex VARCHAR(6),age VARCHAR(3)) TYPE=INNODB;
记得后面的TYPE=INNODB。

4.sql语句的transaction实现
两种方式:
如果SET AUTOCOMMIT=0;也就是关闭了自动提交,那么任何commit或rallback语句都可以触发事务提交。
比如:
 mysql> SET AUTOCOMMIT=0;
 Query OK, 0 rows affected (0.00 sec)
 
 mysql> INSERT INTO user(fname,sname) VALUES ('Max','Ma');
 Query OK, 1 row affected (0.00 sec)

 mysql> INSERT INTO user(fname,sname) VALUES ('Sky','Sun');
 Query OK, 1 row affected (0.00 sec)
 
 mysql> COMMIT;
 Query OK, 0 rows affected (0.00 sec)
这样事务就算提交了。
如果SET AUTOCOMMIT=1;也就是开启了自动提交(默认值),那么必须要以begin或者START TRANSACTION声明事务的开始,然后再以commit或rallback语句都可以触发事务提交。
比如:
 mysql> SET AUTOCOMMIT=1;
 Query OK, 0 rows affected (0.00 sec)

 mysql> BEGIN;
 Query OK, 0 rows affected (0.00 sec)
 
 mysql> INSERT INTO user(fname,sname) VALUES ('Max','Ma');
 Query OK, 1 row affected (0.00 sec)

 mysql> INSERT INTO user(fname,sname) VALUES ('Sky','Sun');
 Query OK, 1 row affected (0.00 sec)
 
 mysql> COMMIT;
 Query OK, 0 rows affected (0.00 sec)

像其他关系型数据库一样,也可以使用存储过程(procedure)来封装事务。

5.java程序开发中的实现。
涉及到程序开发实现方法就多了。
一.自己写方法把mysql的底层transaction命令封装。我感觉程序开发中应该尽量避免和底层数据库的过多交互,我没有实现它。
有人实现了,下面是他实现的一个例子网址:http://dlog.cn/html/diary/showlog.vm?sid=7&log_id=2516

二.java的jdbc开发包包含了操作transaction的方法,在java.sql.connection接口里。
使用他的好处是可以和多种类型数据库交互。
三.hibernate等ORM框架工具。
hibernate中也封状了对transaction的操作,在org.hibernate.Session类中,使用beginTransaction()方法开启transaction;使用getTransaction().commit()提交transaction;使用getTransaction().rollback()方法回滚transaciton。
四.这是我常用的一种方法,把hibernate的session的方法封装或者实现jdbc的connection的接口。

 

发表在 article | 标签为 , | MyISAM InnoDB 存储引擎的比较和事务的概念已关闭评论

dotnet 自定义应用程序配置文件

配置文件概述:

  应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的。它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序。配置文件的根节点是configuration。我们经常访问的是appSettings,它是由.Net预定义配置节。我们经常使用的配置文件的架构是象下面的形式。先大概有个印象,通过后面的实例会有一个比较清楚的认识。下面的“配置节”可以理解为进行配置一个XML的节点。

  常见配置文件模式:
 

<
configuration
>


<
configSections
>
    
//
配置节声明区域,包含配置节和命名空间声明


                
<
section
>
              
//
配置节声明


             
<
sectionGroup
>
       
//
定义配置节组


                  
<
section
>
       
//
配置节组中的配置节声明


        
<
appSettings
>
 
//
预定义配置节


        
<
Custom element 
for
 configuration section
>
  
//
配置节设置区域

  只有appSettings节的配置文件及访问方法

  下面是一个最常见的应用程序配置文件的例子,只有appSettings节。
 

<?
xml version="1.0" encoding="utf-8"
?>


<
configuration
>


<
appSettings
>


<
add 
key
="connectionstring"
 value
="User ID=sa;Data Source=.;Password=;Initial Catalog=test;Provider=SQLOLEDB.1;"
 
/>


<
add 
key
="TemplatePATH"
 value
="Template"
 
/>


</
appSettings
>


</
configuration
>

  下面来看看这样的配置文件如何方法。

  string _connectionString=ConfigurationSettings.AppSettings["connectionstring"];

  使用ConfigurationSettings类的静态属性AppSettings就可以直接方法配置文件中的配置信息。这个属性的类型是NameValueCollection。
  自定义配置文件

  自定义配置节

  一个用户自定义的配置节,在配置文件中分为两部分:一是在<configSections></ configSections>配置节中声明配置节(上面配置文件模式中的“<section>”),另外是在<configSections></ configSections >之后设置配置节(上面配置文件模式中的“<Custom element for configuration section>”),有点类似一个变量先声明,后使用一样。声明一个配置文件的语句如下:
 

<
section 
name
=" "
 type
=" "
/>

  <section>:声明新配置节,即可创建新配置节。

  name:自定义配置节的名称。

  type:自定义配置节的类型,主要包括System.Configuration.SingleTagSectionHandler、   System.Configuration.DictionarySectionHandler、 System.Configuration.NameValueSectionHandler。

  不同的type不但设置配置节的方式不一样,最后访问配置文件的操作上也有差异。下面我们就举一个配置文件的例子,让它包含这三个不同的type。
 

<?
xml version="1.0" encoding="utf-8" 
?>


<
configuration
>


<
configSections
>


<
section 
name
="Test1"
 type
="System.Configuration.SingleTagSectionHandler"
/>


<
section 
name
="Test2"
 type
="System.Configuration.DictionarySectionHandler"
/>


<
section 
name
="Test3"
 type
="System.Configuration.NameValueSectionHandler"
 
/>


</
configSections
>


<
Test1 
setting1
="Hello"
 setting2
="World"
/>


<
Test2
>


<
add 
key
="Hello"
 value
="World"
 
/>


</
Test2
>


<
Test3
>


<
add 
key
="Hello"
 value
="World"
 
/>


</
Test3
>


</
configuration
>

  我们对上面的自定义配置节进行说明。在声明部分使用<section name="Test1" type="System.Configuration.SingleTagSectionHandler"/>声明了一个配置节它的名字叫Test1,类型为SingleTagSectionHandler。在设置配置节部分使用 <Test1 setting1="Hello" setting2="World"/>设置了一个配置节,它的第一个设置的值是Hello,第二个值是World,当然还可以有更多。其它的两个配置节和这个类似。

  下面我们看在程序中如何访问这些自定义的配置节。我们用过ConfigurationSettings类的静态方法GetConfig来获取自定义配置节的信息。

  public static object GetConfig(string sectionName);

  下面是访问这三个配置节的代码:
 

 
//
访问配置节Test1


            IDictionary IDTest1 
=
 (IDictionary)ConfigurationSettings.GetConfig(
"
Test1
"
);

string
 str 
=
 (
string
)IDTest1[
"
setting1
"
] 
+
"
 
"
+
(
string
)IDTest1[
"
setting2
"
];
MessageBox.Show(str);        
//
输出Hello World

//
访问配置节Test1的方法2


            
string
[] values1
=
new
 
string
[IDTest1.Count];
IDTest1.Values.CopyTo(values1,
0
);
MessageBox.Show(values1[
0
]
+
"
 
"
+
values1[
1
]);    
//
输出Hello World

//
访问配置节Test2


            IDictionary IDTest2 
=
 (IDictionary)ConfigurationSettings.GetConfig(
"
Test2
"
);

string
[] keys
=
new
 
string
[IDTest2.Keys.Count];

string
[] values
=
new
 
string
[IDTest2.Keys.Count];
IDTest2.Keys.CopyTo(keys,
0
);
IDTest2.Values.CopyTo(values,
0
);
MessageBox.Show(keys[
0
]
+
"
 
"
+
values[
0
]);

//
访问配置节Test3


            NameValueCollection nc
=
(NameValueCollection)ConfigurationSettings.GetConfig(
"
Test3
"
);
MessageBox.Show(nc.AllKeys[
0
].ToString()
+
"
 
"
+
nc[
"
Hello
"
]);    
//
输出Hello World

  自定义配置节组

  配置节组是使用<sectionGroup>元素,将类似的配置节分到同一个组中。配置节组声明部分将创建配置节的包含元素,在<configSections>元素中声明配置节组,并将属于该组的节置于<sectionGroup>元素中。下面是一个包含配置节组的配置文件的例子:
 

<?
xml version="1.0" encoding="utf-8" 
?>


<
configuration
>


<
configSections
>


<
sectionGroup 
name
="TestGroup"
>


<
section 
name
="Test"
 type
="System.Configuration.NameValueSectionHandler"
/>


</
sectionGroup
>


</
configSections
>


<
TestGroup
>


<
Test
>


<
add 
key
="Hello"
 value
="World"
/>


</
Test
>


</
TestGroup
>


</
configuration
>

 

发表在 article | 标签为 | dotnet 自定义应用程序配置文件已关闭评论

Mysql的distinct语句和group by,order by

最近,在做一个项目的时候,发现得出的数据于预料的相差很多,仔细的研究了一下,发现问题出在 distinct语句和groupy by,order by
首先,distinct语句,获得非重复的(唯一)行记.
grouy by是分组,order by 是排序。

直接看我的例子。

假定我有一个表f_job,有字段:

select job_id, com_id,job_time from f_job order by job_time desc limit 10; T e:webwebphpfhrtee.txt
+--------+--------+---------------------+
| job_id | com_id | job_time |
+--------+--------+---------------------+
| 5060 | 2205 | 2006-09-29 16:30:11 |
| 4707 | 19084 | 2006-09-29 16:27:55 |
| 4708 | 19084 | 2006-09-29 16:27:55 |
| 4709 | 19084 | 2006-09-29 16:27:55 |
| 4710 | 19084 | 2006-09-29 16:27:55 |
| 4711 | 19084 | 2006-09-29 16:27:55 |
| 4859 | 19084 | 2006-09-29 16:27:55 |
| 4918 | 19084 | 2006-09-29 16:27:55 |
| 5059 | 2205 | 2006-09-29 16:27:22 |
| 4078 | 2715 | 2006-09-29 16:18:36 |
+--------+--------+---------------------+
10 rows in set (0.03 sec)

还有其他字段,不可能影响结果.此处不列出。

job_id是primary key。 com_id是外键,我需要按照时间来排序。所以必须使用order by!

你看到了com_id在得出的结果中不唯一,对,我需要的结果就是提取com_id唯一的最近10条com_id的记录,而已。

我就以以前的MSSQL的经验写如下的语句执行:
mysql> select distinct( com_id) from f_job order by job_time desc limit 10; T e:webwebphpfhrtee.txt
+--------+
| com_id |
+--------+
| 19084 |
| 2197 |
| 19917 |
| 19580 |
| 19520 |
| 19664 |
| 19397 |
| 19900 |
| 1176 |
| 19449 |
+--------+

对,这次得出的结果是唯一,但是,这不对呀,很明显,把com_id记录号码是2005的记录给没了,这结果肯定错。马上分析一下所有的的结果,发现忽略的com_id并没有消失,只是被排到后面去了。

我按照时间排序,应该出现的结果第一个就是2205呀,为什么能排到后面?从两条可疑记录看出了结果:

原记录:

| 5058 | 19580 | 2006-09-29 15:23:58 |
| 5057 | 19917 | 2006-09-29 15:14:16 |
| 4973 | 19580 | 2006-09-29 15:13:49 |
| 5011 | 19580 | 2006-09-29 15:13:49 |

distinct后的次序:

| 19917 |
| 19580 |

这说明,对于不是在一起的隔行记录,如果恰巧隔一行,还可以被order by 比较出来,否则比较出来的不再真实,这是因为,被缓存的上次的order by 的临时值在客观上不再有用!还有一种情况,如果记录连着,也可以被比较出来。

先是明白了MySql的弱智了。

马上又执行了一下操作,结果如下:
mysql> select distinct(com_id),job_time from f_job order by job_time desc limit 10;
+--------+---------------------+
| com_id | job_time |
+--------+---------------------+
| 2205 | 2006-09-29 16:30:11 |
| 19084 | 2006-09-29 16:27:55 |
| 2205 | 2006-09-29 16:27:22 |
| 2715 | 2006-09-29 16:18:36 |
| 2197 | 2006-09-29 16:03:16 |
| 19580 | 2006-09-29 15:23:58 |
| 19917 | 2006-09-29 15:14:16 |
| 19580 | 2006-09-29 15:13:49 |
| 19520 | 2006-09-29 10:29:41 |
| 19900 | 2006-09-29 10:16:48 |
+--------+---------------------+
10 rows in set (0.10 sec)

先和这个比较一下:
mysql> select com_id,job_time from f_job order by job_time desc limit 10; T e:webwebphpfhrtee.txt
+--------+---------------------+
| com_id | job_time |
+--------+---------------------+
| 2205 | 2006-09-29 16:30:11 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 19084 | 2006-09-29 16:27:55 |
| 2205 | 2006-09-29 16:27:22 |
| 2715 | 2006-09-29 16:18:36 |
+--------+---------------------+
10 rows in set (0.06 sec)

发现,distinct恰巧和前面第一次测试的结果相反处理我们的信息,他把隔行的看作不同的结果输出,这就导致了2205的记录又出现了。

然后我就用了group by语句,应该可以吧,结果也让我。。。:
mysql> select com_id from f_job group by com_id order by job_time desc limit 10;
+--------+
| com_id |
+--------+
| 19084 |
| 2197 |
| 19917 |
| 19580 |
| 19520 |
| 19664 |
| 19397 |
| 19900 |
| 1176 |
| 19449 |
+--------+
10 rows in set (0.03 sec)

这和distinct的结果一样,这倒不出乎意料,然后我又加入分组job_time,看看:
mysql> select com_id from f_job group by com_id,job_time order by job_time desc limit 10;
+--------+
| com_id |
+--------+
| 2205 |
| 19084 |
| 2205 |
| 2715 |
| 2197 |
| 19580 |
| 19917 |
| 19580 |
| 19520 |
| 19900 |
+--------+
10 rows in set (0.03 sec)

这结果差一点点了,然后我再distinct(com_id)一下,应该可以了吧!看看:
mysql> select distinct(com_id) from f_job group by com_id,job_time order by job_time desc limit 10; T e:webwebphpfhrtee.txt
+--------+
| com_id |
+--------+
| 19084 |
| 2197 |
| 19917 |
| 19580 |
| 19520 |
| 19664 |
| 19397 |
| 19900 |
| 1176 |
| 19449 |
+--------+
10 rows in set (0.04 sec)

汗,这和没加group by 的一点区别都没,怎么这样弱呀!没办法,这怎么办,犹豫中。。。

上面的问题彻底的说明了这样一个事实:distinct只能返回它的目标字段,而无法返回其它字段。。。

汗,这和没加group by 的一点区别都没,怎么这样弱呀!没办法,这怎么办,犹豫中。。。

------------------------------------
想起了一个很能骚的一个人--phzzy,这jh,qq说了句话,果然在,他玩php,马上求助,经过1个多小时的艰苦YY,终于这鸟人先大爷我一步给出语句:
select (`com_id`),max(`job_time`) from `f_job` GROUP BY `com_id` order by max(`job_time`) limit 10;

mdgb,终于明白了,刚拿到这语句就明白了。

我tmd知道这是2次排序,md,group by是一次,然后无论怎么样,都不可能2次排序,因为第二次必须借助内部的集聚函数。。。。。。我怎么没想到max,气死我了

发表在 article | 标签为 | Mysql的distinct语句和group by,order by已关闭评论

squid之重定向redirect使用/启用Linux的内存盘/squid重启建目

在squid.conf中添加
url_rewrite_program /etc/squid/redirect.pl ##重定向perl程序
redirect_rewrites_host_header off ##禁止squid做host更新
redirect_children 20 ##启用20个进程

再看这个redirect.pl
#!/usr/bin/perl
$|=1;
        while (<>) {
                @X = split;
                $url = $X[0];
                if ($url =~ /^http:\/\/www\.baidu\.com/) {
                        print “302:https:\/\/www\.google\.com\n”;
                }
                elsif ($url =~ /^http:\/\/opvps\.com/) {
                        print “302:http:\/\/www\.opvps\.com\n”;
                }
                elsif ($url =~ /^http:\/\/gmail\.com/) {
                        print “302:https:\/\/gmail\.google\.com\n”;
                }
                else {
                        print “$url\n”;
                }
            }

程序实现如下功能:
将http://www.baidu.com
转向http://www.google.com

http://opvps.com
及www变成http://www.opvps.com

http://gmail.com
变成https://gmail.google.com

重定向acl匹配:

正常情况下,squid将每个请求发送往重定向器。可以使用redirector_access规则来有选择的发送某些请求。语法与http_access相同:
redirector_access allow|deny [!]ACLname
例如:
acl opvps src 192.168.1.5
acl All src 0/0

redirector_access deny opvps
redirector_access allow All
在该情形里,对匹配opvps(来源于192.168.0.5的主机)的请求,Squid跳过重定向器。

 

 

-----------------------------------------------------------------------

启用Linux的内存盘

大家都知道,读写放在内存里面文件的速度远远快于放在硬盘,放在内存中基本上不存在IO读写等待的问题。当然放在内存上,机器一当重启,内存中的文件就会丢失了,适合于存放一些Cache 如squid的 cache目录

大多数的Linux发行版本中,内存盘默认使用的是/dev/shm 大小一般等同于内存的大小

当然我也可以重设这个盘的大小,使用
mount -o remount,size=3G /dev/shm
这样/dev/shm就成为3G了

其实我们可以直接把文件放到/dev/shm下使用的

下面,我将squid 的cache 目录挂在内存盘中使用
mount -t tmpfs -o size=3G,mode=0755 tmpfs /usr/local/squid/var/cache
在/etc/fstab中加入一行,实行每次启动自动挂载内存盘
tmpfs /usr/local/squid/var/cache  tmpfs size=3G,mode=0755 0 0
当然,squid的cache的权限需要更改,每次启动需要更改目录权限及重建cache目录,需要执行如下指令
chown -R nobody:nobody /usr/local/squid/var/cache #这里的squid是使用nobody用户的
/usr/local/squid/sbin/squid -z ##重建cache

这样linux的内存盘就用启来了

-----------------------------------------------------

新到服务器Dell1900,2G内存,正好用来做squid代理服务器,用内存盘做ramdisk,以减少I/O瓶颈,FreeBSD 6.2的OS,先vi /etc/fstab,加入'md /ramdisk mfs rw,noatime,-s512M 0 0',但是这样的话,每次机器重启由于没有cache目录结构了,导致squid没法启动,需要手动squid -z,于是修改/usr/local/etc/rc.d/squid启动脚本如下,注意蓝色部分是添加的自动创建cache目录。

squid_checkrunning() {
        ${command} ${squid_flags} -k check 2>/dev/null
}

squid_stop() {
        echo "Stopping ${name}."
        ${command} ${squid_flags} -k shutdown
        run_rc_command poll
}

. /etc/rc.subr

name=squid
rcvar=${name}_enable

command=/usr/local/sbin/squid
extra_commands=reload
reload_cmd="${command} ${squid_flags} -k reconfigure"
stop_precmd="squid_checkrunning"
stop_cmd="squid_stop"

load_rc_config ${name}

squid_chdir=${squid_chdir:-/usr/local/squid/logs}
squid_enable=${squid_enable:-"NO"}
squid_flags=${squid_flags-"-D"}
squid_user=${squid_user:-squid}
default_config=/usr/local/etc/squid/squid.conf

required_dirs=${squid_chdir}

# squid(8) will not start if ${default_config} is not present so try
# to catch that beforehand via ${required_files} rather than make
# squid(8) crash.
# If you remove the default configuration file make sure to add
# '-f /path/to/your/squid.conf' to squid_flags

if [ -z "${squid_flags}" ]; then
        required_files=${default_config}
fi

cache_dir="/ramdisk/00"
if [ ! -d $cache_dir ]; then
  /usr/local/sbin/squid -z
fi

run_rc_command "$1"
发表在 article | 标签为 | squid之重定向redirect使用/启用Linux的内存盘/squid重启建目已关闭评论

isp.apnic.list/获取电信,网通,铁通APNIC权威IP数据集

从apnic获得ISP IP列表的脚本

朋友让我看一个abel在CU上提出从apnic获得ISP IP列表的脚本
。仔细看了一遍发现abel的方法很复杂很强大,好些命令看不明白,所以想自己按照abel的思想写一个更简单易懂shell脚本。正好前些天学习了sed,练习机会来了,花了两个多小时完成这个任务。脚本如下:

#!/bin/sh
FILE=ip_apnic
ISPIP=ISP.ip
rm -f $FILE
rm -f *.ip
wget http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest
-O $FILE
#remove all useless lines
sed -i -e '/\(apnic\)|\(CN\)|\(ipv4\)|\(.\+\)|\(.\+\)|\(.\+\)|\(.\+\)/!d;' $FILE
#get ip networks and the number of hosts in this network from field 4 and field 5
sed -i -e 's/\(apnic\)|\(CN\)|\(ipv4\)|\(.\+\)|\(.\+\)|\(.\+\)|\(.\+\)/\4 \5/g;' $FILE

while read ip cnt
do
        pow=32
        #cnt2=$cnt
        #get netmask from the number of hosts in the network
        while [ $cnt -gt 1 ]; do
                pow=$(($pow-1))
                cnt=$(($cnt/2))
        done
        #get whois information, remove all useless lines, extract the netname from the rest line.
        NETNAME=`whois -h whois.apnic.net $ip | sed -e '/netname/!d;/netname/q' | sed -e 's/netname:[[:blank:]]\+\(.*\)/\1/g'`
        echo $ip/$pow $NETNAME >> $ISPIP
        echo $ip/$pow $NETNAME
done < $FILE

#all networks are categorized by their netname like these "sed ..."
sed -n -e '/CNC\|wangtong/p' $ISPIP >> CNCGROUP.ip
sed -n -e '/CHINANET\|CHINATELECOM/p' $ISPIP >> CHINANET.ip
done

abel写好几个case语句匹配NETNAME,由于ISP的NETNAME实在太多,我就不写case了,直接在最后的sed命令中硬编码NETNAME。如果要做的更好,可以先定义一个ISP NETNAME的数组,然后做一个for循环。与abel的脚本相比,上面的脚本使用的命令更少,程序结构更简单,基本上是靠sed命令解决问题。如果说abel使用乘法计算2*5=10的话,那我就是用比较笨的加法计算2*5=5 + 5 = 10。

 

---------------------------------------------------------------------------------------------------------------------------------------------

程序代码

<?php
         $iplist=file_get_contents("ftp://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest
");
         $ipsplit=split("[\n]+",$iplist);
         foreach($ipsplit as $val){
                 if(preg_match("/apnic\|CN\|ipv4\|/",$val)){
                 list($nic,$CN,$ver,$ip,$mask)=preg_split("/\|/",$val);
                 $iparray['set'][]=array("ip"=>$ip,"mask"=>$mask);
                 }
         }
        
         foreach($iparray['set'] as $val){
                 echo $val['ip']."\t".(32-log($val['mask'],2))."\n";
                 $flag=GetWhois($val['ip']);
                 switch($flag){
                         case "CHINANET":
                                 //$fpc=fopen("CHINANET.lst","a+");
                                 //fwrite($fpc,$val['ip']."/".(32-log($val['mask'],2))."\n");
                                 $CHINANET[]=$val['ip']."/".(32-log($val['mask'],2));
                                 break;
                         case "CNC":
                                 //$fpc=fopen("CNC.lst","a+");
                                 //fwrite($fpc,$val['ip']."/".(32-log($val['mask'],2))."\n");
                                 $CNC[]=$val['ip']."/".(32-log($val['mask'],2));
                                 break;
                                 break;
                         case "CRTC":
                                 //$fpc=fopen("CRTC.lst","a+");
                                 //fwrite($fpc,$val['ip']."/".(32-log($val['mask'],2))."\n");
                                 $CRTC[]=$val['ip']."/".(32-log($val['mask'],2));
                                 break;

                         default:        
                                 //$fpc=fopen("OTHERS.lst","a+");
                                 //fwrite($fpc,$val['ip']."/".(32-log($val['mask'],2))."\n");
                                 $OTHERS[]=$val['ip']."/".(32-log($val['mask'],2));
                                 break;
                 }
                
                
                        
         }
        
         //去掉重复数据
                 $CHINANET = array_unique($CHINANET);
                 $CNC = array_unique($CNC);
                 $CRTC = array_unique($CRTC);
                 $OTHERS = array_unique($OTHERS);
                
                 //生成IP集表 CHINANET
                 $MaxCount = count($CHINANET);
                 $fpc_lst=fopen("CHINANET.lst","a+");
                 $fpc_routes_rsc=fopen("CHINANET_routes.rsc","a+");
                 $fpc_address_rsc=fopen("CHINANET_address.rsc","a+");
                 fwrite($fpc_routes_rsc,"/ ip route rule\n");
                 fwrite($fpc_address_rsc,"/ ip firewall address-list\n");
                
                 for ($iCount=0;$iCount< $MaxCount;$iCount++){
                         fwrite($fpc_lst,$CHINANET[$iCount]."\n");
                         fwrite($fpc_routes_rsc,"add   dst-address=".$CHINANET[$iCount]." action=lookup table=Route_ChinaNet disabled=no\n");
                         fwrite($fpc_address_rsc,"add list=ChinaNet address=".$CHINANET[$iCount]." disabled=no\n");
                 }
                
                 fclose($fpc_address_rsc);
                 fclose($fpc_routes_rsc);
                 fclose($fpc_lst);
                
                 //生成IP集表 CNC
                 $MaxCount = count($CNC);
                 $fpc_lst=fopen("CNC.lst","a+");
                 $fpc_routes_rsc=fopen("CNC_routes.rsc","a+");
                 $fpc_address_rsc=fopen("CNC_address.rsc","a+");
                 fwrite($fpc_routes_rsc,"/ ip route rule\n");
                 fwrite($fpc_address_rsc,"/ ip firewall address-list\n");
                
                 for ($iCount=0;$iCount< $MaxCount;$iCount++){
                         fwrite($fpc_lst,$CNC[$iCount]."\n");
                         fwrite($fpc_routes_rsc,"add   dst-address=".$CNC[$iCount]." action=lookup table=Route_CNC disabled=no\n");
                         fwrite($fpc_address_rsc,"add list=CNC address=".$CNC[$iCount]." disabled=no\n");
                 }
                
                 fclose($fpc_address_rsc);
                 fclose($fpc_routes_rsc);
                 fclose($fpc_lst);
                
                
                 //生成IP集表 CRTC
                 $MaxCount = count($CRTC);
                 $fpc_lst=fopen("CRTC.lst","a+");
                 $fpc_routes_rsc=fopen("CRTC_routes.rsc","a+");
                 $fpc_address_rsc=fopen("CRTC_address.rsc","a+");
                 fwrite($fpc_routes_rsc,"/ ip route rule\n");
                 fwrite($fpc_address_rsc,"/ ip firewall address-list\n");
                
                 for ($iCount=0;$iCount< $MaxCount;$iCount++){
                         fwrite($fpc_lst,$CRTC[$iCount]."\n");
                         fwrite($fpc_routes_rsc,"add   dst-address=".$CRTC[$iCount]." action=lookup table=Route_CRTC disabled=no\n");
                         fwrite($fpc_address_rsc,"add list=CRTC address=".$CRTC[$iCount]." disabled=no\n");
                 }
                
                 fclose($fpc_address_rsc);
                 fclose($fpc_routes_rsc);
                 fclose($fpc_lst);
                
                 //生成IP集表 OTHERS
                 $MaxCount = count($OTHERS);
                 $fpc_lst=fopen("OTHERS.lst","a+");
                 $fpc_routes_rsc=fopen("OTHERS_routes.rsc","a+");
                 $fpc_address_rsc=fopen("OTHERS_address.rsc","a+");
                 fwrite($fpc_routes_rsc,"/ ip route rule\n");
                 fwrite($fpc_address_rsc,"/ ip firewall address-list\n");
                
                 for ($iCount=0;$iCount< $MaxCount;$iCount++){
                         fwrite($fpc_lst,$OTHERS[$iCount]."\n");
                         fwrite($fpc_routes_rsc,"add   dst-address=".$OTHERS[$iCount]." action=lookup table=Route_OTHERS disabled=no\n");
                         fwrite($fpc_address_rsc,"add list=ChinaNet address=".$OTHERS[$iCount]." disabled=no\n");
                 }
                
                 fclose($fpc_address_rsc);
                 fclose($fpc_routes_rsc);
                 fclose($fpc_lst);        

         function GetWhois($IP){
                 $rootwhois = 'whois.apnic.net';
                 $buffer1 = ReadSocket($rootwhois,$IP);
                 $flag="";
                 $buffer_result=nl2br($buffer1);
                 if(preg_match("/CHINANET/",$buffer_result)){
                         $flag="CHINANET";
                         return $flag;
                 }
                 if(preg_match("/CNC/",$buffer_result)){
                         $flag="CNC";
                         return $flag;
                 }
                 if(preg_match("/CRTC/",$buffer_result)){
                         $flag="CRTC";
                         return $flag;
                 }
                 if(!preg_match("/CHINANET|CRTC|CNC/",$buffer_result)){
                         $flag="OTHERS";
                         return $flag;
                 }
         }
function ReadSocket($whois,$ip)
{
   $buffer = '';
   if (!$sock = fsockopen( $whois, 43, $errNum, $errStr, 20))
{
         echo "Sorry,Can't fsockopen it";
   }
   else
   {
     fputs($sock,"$ip\n");
     //$buffer = fread($sock, 8192);
     while(!feof($sock))         $buffer.=fgets($sock, 8192);
     fclose($sock);
   }
   return $buffer;
}
?>

 
--------------------------------------------------------------------------------
附:获取IP地址范围方法:
1、 利用shell程序获取IP地址段

#!/bin/sh

FILE=/root/study/apnic/ip_apnic

rm -f $FILE

wget http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest
-O $FILE

grep 'apnic|CN|ipv4|' $FILE | cut -f 4,5 -d'|'|sed -e 's/|/ /g' | while read ip cnt

do

echo $ip:$cnt

mask=$(cat << EOF | bc | tail -1

pow=32;

define log2(x) {

if (x<=1) return (pow);

pow--;

return(log2(x/2));

}

log2($cnt)

EOF)

echo $ip/$mask>> cn.net

NETNAME=`whois $ip@whois.apnic.net | sed -e '/./{H;$!d;}' -e 'x;/netnum/!d' |grep ^netname | sed -e 's/.*: \(.*\)/\1/g' | sed -e 's/-.*//g'`

case $NETNAME in

CNC)

echo $ip/$mask >> CNCGROUP

;;

CHINANET|CNCGROUP)

echo $ip/$mask >> $NETNAME

;;

CHINANET|CNCGROUP)

echo $ip/$mask >> $NETNAME

;;

CHINATELECOM)

echo $ip/$mask >> CHINANET

;;

*)

echo $ip/$mask >> OTHER

;;

esac

done
 

发表在 article | 标签为 | isp.apnic.list/获取电信,网通,铁通APNIC权威IP数据集已关闭评论

使用BIND来搭建简单的主辅DNS服务器

下载:http://www.isc.org/software/bind/980-p2/download/bind980-p2zip

一.安装BIND

在系统中使用rpm –qa |grep bind查看有没有安装BIND包。如果没有安装,则将系统盘挂载,使用rpm –ivh *bind* 安装。
 
或: yum install bind bind-chroot bind-utils 
 
二.启动BIND
service named start
chkconfig --level 35 named on
 
三.试验拓扑
试验拓扑如下图,使用bob.com域:
 
四.配置Master DNS
1. 编辑DNS的主配置文件named.conf
vi /etc/named.conf
options {
             directory "/var/named";
};
zone "." IN {
             type hint;
             file "named.ca";
};
zone "localhost" IN {
              type master;
             file "localhost.zone";
             allow-update { none; };
};
zone "0.0.127.in-addr.arpa" IN {
              type master;
             file "named.local";
             allow-update { none; };
};
zone "bob.com" IN {
             type master;
             file "bob.com.dns";
             allow-update { none; };
             allow-transfer { 192.168.120.241; };
};
zone "120.168.192.in-addr.arpa" IN {
             type master;
             file "bob.com.rev";
             allow-update { none; };
             allow-transfer { 192.168.120.241; };
};
include "/etc/rndc.key"
 
2. 编辑区域数据文件
vi /var/named/chroot/var/named/bob.com.dns
$TTL 86400
$ORIGIN bob.com.
@    IN   SOA   bob.com.   root.bob.com. (
                                                    2 ;              serial
                                                    120 ;          refresh
                                                    14400 ;      retry
                                                    3600000 ; expiry
                                                    86400 ) ;    minimum
                      IN   NS     bob.com.
master          IN   A      192.168.120.240
slave             IN    A       192.168.120.241
www            IN    A      192.168.120.250
 
vi /var/named/chroot/var/named/bob.com.rev
$TTL 86400
@   IN    SOA bob.com. root.bob.com. (
                                                    2 ;               Serial
                                                    120 ;         Refresh
                                                    14400 ;      Retry
                                                    3600000 ; Expire
                                                    86400 ) ;    Minimum
                     IN NS      bob.com.
240                IN PTR     master.bob.com.
241               IN PTR     slave.bob.com.
250               IN PTR    [url]www.bob.com[/url] .
 
chown named.named /var/named/chroot/var/named/bob.com.*
 
3. 测试
在Master DNS上使用host命令查看信息:
[root@master /]# host [url]www.bob.com[/url]
[url]www.bob.com[/url] has address 192.168.120.250
[root@master /]# host master.bob.com
master.bob.com has address 192.168.120.240
[root@master /]# host slave.bob.com
slave.bob.com has address 192.168.120.241
 
在Master DNS上使用nslookup命令查看信息:
[root@master /]# nslookup
Server: 192.168.120.240
Address: 192.168.120.240#53
Address: 192.168.120.250
> master.bob.com
Server: 192.168.120.240
Address: 192.168.120.240#53
Name: master.bob.com
Address: 192.168.120.240
> 192.168.120.250
Server: 192.168.120.240
Address: 192.168.120.240#53
250.120.168.192.in-addr.arpa name= [url]www.bob.com[/url] .
 
在用户pc上将DNS指向192.168.120.240,然后访问 [url]www.bob.com[/url]
 
4. 查看日志
[root@master /]#service named start
[root@master /]#cat /var/log/messages |grep named
Sep 8 18:24:35 master named[15322]: starting BIND 9.2.4 -u named -t /var/named/chroot
Sep 8 18:24:35 master named[15322]: using 1 CPU
Sep 8 18:24:35 master named[15322]: loading configuration from '/etc/named.conf'
Sep 8 18:24:35 master named[15322]: listening on IPv4 interface lo, 127.0.0.1#53
Sep 8 18:24:35 master named[15322]: listening on IPv4 interface eth0, 192.168.120.240#53
Sep 8 18:24:35 master named[15322]: command channel listening on 127.0.0.1#953
Sep 8 18:24:35 master named[15322]: command channel listening on ::1#953
Sep 8 18:24:35 master named[15322]: zone 0.0.127.in-addr.arpa/IN: loaded serial 1997022700
Sep 8 18:24:35 master named[15322]: zone 120.168.192.in-addr.arpa/IN: loaded serial 2
Sep 8 18:24:35 master named[15322]: zone bob.com/IN: loaded serial 2
Sep 8 18:24:35 master named[15322]: zone localhost/IN: loaded serial 42
Sep 8 18:24:35 master named[15322]: named startup succeeded
Sep 8 18:24:35 master named[15322]: running
 
5. 注意事项
A.修改区域数据文件在每次存盘时要注意增加Serial值,主要用来让辅助服务器同步主服务器的区域数据文件。
B.使用绝对域名时千万别忘了后面要带"."。
C.主配置文件named.conf的";"不能少。
 
五.配置Slave DNS
1. 编辑DNS的主配置文件named.conf
vi /etc/named.conf
options {
              directory "/var/named";
};
zone "." IN {
              type hint;
              file "named.ca";
};
zone "localhost" IN {
               type master;
              file "localhost.zone";
              allow-update { none; };
};
zone "0.0.127.in-addr.arpa" IN {
              type master;
              file "named.local";
              allow-update { none; };
};
zone "bob.com" IN {
              type slave;
              file "slaves/bob.com.dns";
              masters { 192.168.120.240; };
};
zone "120.168.192.in-addr.arpa" IN {
              type slave;
              file "slaves/bob.com.rev";
              masters { 192.168.120.240; };
};
include "/etc/rndc.key"
 
2. 修改从主DNS复制过来的区域文件存放目录的权限
cd /var/named/chroot/var/named/slaves
chmod 775 /var/named/chroot/var/named/slaves
chown named.named /var/named/chroot/var/named/slaves
 
3. 测试
在Slave DNS上查看区域数据文件有没有从主DNS复制过来
[root@slave /]#ll /var/named/chroot/var/named/slaves
-rw------- 1 named named 406 Jun 13 23:50 bob.com.dns
-rw------- 1 named named 410 Jun 13 19:10 bob.com.rev
 
在Slave DNS上使用host命令查看信息
[root@slave /]# host [url]www.bob.com[/url]
[url]www.bob.com[/url] has address 192.168.120.250
[root@slave /]# host master.bob.com
master.bob.com has address 192.168.120.240
[root@slave /]# host slave.bob.com
slave.bob.com has address 192.168.120.241
 
在slave DNS上使用nslookup命令查看信息
[root@slave /]# nslookup
Server: 192.168.120.241
Address: 192.168.120.241#53
Address: 192.168.120.250
> master.bob.com
Server: 192.168.120.241
Address: 192.168.120.241#53
Name: master.bob.com
Address: 192.168.120.240
> 192.168.120.250
Server: 192.168.120.241
Address: 192.168.120.241#53
250.120.168.192.in-addr.arpa name= [url]www.bob.com[/url] .
 
在用户pc上将DNS指向192.168.120.241,然后访问 [url]www.bob.com[/url]
 
4. 查看日志
[root@slaves /]#services named start
[root@slaves /]# cat /var/log/messages |grep named
Jun 14 00:04:48 slave named[10083]: starting BIND 9.2.4 -u named -t /var/named/chroot
Jun 14 00:04:48 slave named[10083]: using 1 CPU
Jun 14 00:04:48 slave named[10083]: loading configuration from '/etc/named.conf'
Jun 14 00:04:48 slave named[10083]: listening on IPv4 interface lo, 127.0.0.1#53
Jun 14 00:04:48 slave named[10083]: listening on IPv4 interface eth0, 192.168.120.241#53
Jun 14 00:04:48 slave named[10083]: command channel listening on 127.0.0.1#953
Jun 14 00:04:48 slave named[10083]: command channel listening on ::1#953
Jun 14 00:04:49 slave named[10083]: zone 0.0.127.in-addr.arpa/IN: loaded serial 1997022700
Jun 14 00:04:49 slave named[10083]: zone localhost/IN: loaded serial 42
Jun 14 00:04:49 slave named[10083]: named startup succeeded
Jun 14 00:04:49 slave named[10083]: running
Jun 14 00:04:49 slave named[10083]: zone 120.168.192.in-addr.arpa/IN: transferred serial 2
Jun 14 00:04:49 slave named[10083]: transfer of '120.168.192.in-addr.arpa/IN' from 192.168.120.240#53: end of transfer
Jun 14 00:04:49 slave named[10083]: zone bob.com/IN: transferred serial 2
Jun 14 00:04:49 slave named[10083]: transfer of 'bob.com/IN' from 192.168.120.240#53: end of transfer
 
5. 注意事项
A.从主DNS复制过来的区域文件存放目录的权限。
B.主配置文件named.conf的";"不能少。
发表在 article | 标签为 | 使用BIND来搭建简单的主辅DNS服务器已关闭评论

bind配置文件语法

acl:定义IP地址表的名字,用于访问控制等

语法:
acl acl-name {
    address_match_list;
}controls:宣告一个用于rndc工具控制通道

语法:
controls {
   [ inet ( ip_addr | * ) [ port ip_port ] allow {  address_match_list  }
                keys { key_list }; ]
   [ inet ...; ]
   [ unix path perm number owner number group number keys { key_list }; ]
   [ unix ...; ]
};
include:包含一个文件

语法:
include filename;key:定义key信息用于验证和TSIG验证

语法:
key key_id {
    algorithm string;
    secret string;
};logging:定义bing服务的日志, channel -> categroy.

语法:
logging {
   [ channel channel_name {
     ( file path name
         [ versions ( number | unlimited ) ]
         [ size size spec ]
       | syslog syslog_facility
       | stderr
       | null );
     [ severity (critical | error | warning | notice |
                 info | debug [ level ] | dynamic ); ]
     [ print-category yes or no; ]
     [ print-severity yes or no; ]
     [ print-time yes or no; ]
   }; ]
   [ category category_name {
     channel_name ; [ channel_name ; ... ]
   }; ]
   ...
};

category 参数:
    default: 默认分类,没有分类的日志都使用这个分类的配置.
    general: 没有分类的日志都记录在此分类中.
    database: 服务器内部使用存储zone和缓存数据.
    security: 允许/拒绝的请求.
    config: 配置文件分析和处理.
    resolver: DNS解析,被dns缓存服务器进行递归查询.
    xfer-in: 接收区域传输.
    xfer-out: 发送区域传输.
    notify: NOTIFY协议.
    client: 客户端请求进程.
    unmatched: 未匹配的查询?
    network: 网络操作.
    update: 动态更新.
    update-security: 允许/拒绝更新请求.
    queries: 客户端队列日志.
    dispatch: 数据包传送日志.
    dnssec: DNSSEC和TSIG协议处理.
    lame-servers: 远端的配置错误的服务器发送的请求.
    delegation-only: NXDOMAIN的结果将被强制定义到delegation-only区域lwres:定义named为一个轻量级的解析进程

语法:
lwres {
    [ listen-on { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    [ view view_name; ]
    [ search { domain_name ; [ domain_name ; ... ] }; ]
    [ ndots number; ]
};masters:定义主域服务器列表

语法:
masters name [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] };options:设定全局配置选项和默认值

语法:
options {
    [ version version_string; ]
    [ hostname hostname_string; ]
    [ server-id server_id_string; ]
    [ directory path_name; ]
    [ key-directory path_name; ]
    [ named-xfer path_name; ]
    [ tkey-domain domainname; ]
    [ tkey-dhkey key_name key_tag; ]
    [ cache-file path_name; ]
    [ dump-file path_name; ]
    [ memstatistics-file path_name; ]
    [ pid-file path_name; ]
    [ statistics-file path_name; ]
    [ zone-statistics yes_or_no; ]
    [ auth-nxdomain yes_or_no; ]
    [ deallocate-on-exit yes_or_no; ]
    [ dialup dialup_option; ]
    [ fake-iquery yes_or_no; ]
    [ fetch-glue yes_or_no; ]
    [ flush-zones-on-shutdown yes_or_no; ]
    [ has-old-clients yes_or_no; ]
    [ host-statistics yes_or_no; ]
    [ host-statistics-max number; ]
    [ minimal-responses yes_or_no; ]
    [ multiple-cnames yes_or_no; ]
    [ notify yes_or_no | explicit | master-only; ]
    [ recursion yes_or_no; ]
    [ rfc2308-type1 yes_or_no; ]
    [ use-id-pool yes_or_no; ]
    [ maintain-ixfr-base yes_or_no; ]
    [ dnssec-enable yes_or_no; ]
    [ dnssec-validation yes_or_no; ]
    [ dnssec-lookaside domain trust-anchor domain; ]
    [ dnssec-must-be-secure domain yes_or_no; ]
    [ dnssec-accept-expired yes_or_no; ]
    [ forward ( only | first ); ]
    [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ]
    [ dual-stack-servers [port ip_port] {
        ( domain_name [port ip_port] |
          ip_addr [port ip_port] ) ;
        ... }; ]
    [ check-names ( master | slave | response )
        ( warn | fail | ignore ); ]
    [ check-mx ( warn | fail | ignore ); ]
    [ check-wildcard yes_or_no; ]
    [ check-integrity yes_or_no; ]
    [ check-mx-cname ( warn | fail | ignore ); ]
    [ check-srv-cname ( warn | fail | ignore ); ]
    [ check-sibling yes_or_no; ]
    [ allow-notify { address_match_list }; ]
    [ allow-query { address_match_list }; ]
    [ allow-query-cache { address_match_list }; ]
    [ allow-transfer { address_match_list }; ]
    [ allow-recursion { address_match_list }; ]
    [ allow-update { address_match_list }; ]
    [ allow-update-forwarding { address_match_list }; ]
    [ update-check-ksk yes_or_no; ]
    [ allow-v6-synthesis { address_match_list }; ]
    [ blackhole { address_match_list }; ]
    [ avoid-v4-udp-ports { port_list }; ]
    [ avoid-v6-udp-ports { port_list }; ]
    [ listen-on [ port ip_port ] { address_match_list }; ]
    [ listen-on-v6 [ port ip_port ] { address_match_list }; ]
    [ query-source ( ( ip4_addr | * )
        [ port ( ip_port | * ) ] |
        [ address ( ip4_addr | * ) ]
        [ port ( ip_port | * ) ] ) ; ]
    [ query-source-v6 ( ( ip6_addr | * )
        [ port ( ip_port | * ) ] |
        [ address ( ip6_addr | * ) ]
        [ port ( ip_port | * ) ] ) ; ]
    [ max-transfer-time-in number; ]
    [ max-transfer-time-out number; ]
    [ max-transfer-idle-in number; ]
    [ max-transfer-idle-out number; ]
    [ tcp-clients number; ]
    [ recursive-clients number; ]
    [ serial-query-rate number; ]
    [ serial-queries number; ]
    [ tcp-listen-queue number; ]
    [ transfer-format ( one-answer | many-answers ); ]
    [ transfers-in  number; ]
    [ transfers-out number; ]
    [ transfers-per-ns number; ]
    [ transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ use-alt-transfer-source yes_or_no; ]
    [ notify-source (ip4_addr | *) [port ip_port] ; ]
    [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    [ max-ixfr-log-size number; ]
    [ max-journal-size size_spec; ]
    [ coresize size_spec ; ]
    [ datasize size_spec ; ]
    [ files size_spec ; ]
    [ stacksize size_spec ; ]
    [ cleaning-interval number; ]
    [ heartbeat-interval number; ]
    [ interface-interval number; ]
    [ statistics-interval number; ]
    [ topology { address_match_list }];
    [ sortlist { address_match_list }];
    [ rrset-order { order_spec ; [ order_spec ; ... ] ] };
    [ lame-ttl number; ]
    [ max-ncache-ttl number; ]
    [ max-cache-ttl number; ]
    [ sig-validity-interval number ; ]
    [ min-roots number; ]
    [ use-ixfr yes_or_no ; ]
    [ provide-ixfr yes_or_no; ]
    [ request-ixfr yes_or_no; ]
    [ treat-cr-as-space yes_or_no ; ]
    [ min-refresh-time number ; ]
    [ max-refresh-time number ; ]
    [ min-retry-time number ; ]
    [ max-retry-time number ; ]
    [ port ip_port; ]
    [ additional-from-auth yes_or_no ; ]
    [ additional-from-cache yes_or_no ; ]
    [ random-device path_name ; ]
    [ max-cache-size size_spec ; ]
    [ match-mapped-addresses yes_or_no; ]
    [ preferred-glue ( A | AAAA | NONE ); ]
    [ edns-udp-size number; ]
    [ max-udp-size number; ]
    [ root-delegation-only [ exclude { namelist } ] ; ]
    [ querylog yes_or_no ; ]
    [ disable-algorithms domain { algorithm; [ algorithm; ] }; ]
    [ acache-enable yes_or_no ; ]
    [ acache-cleaning-interval number; ]
    [ max-acache-size size_spec ; ]
    [ clients-per-query number ; ]
    [ max-clients-per-query number ; ]
    [ masterfile-format (text|raw) ; ]
    [ empty-server name ; ]
    [ empty-contact name ; ]
    [ empty-zones-enable yes_or_no ; ]
    [ disable-empty-zone zone_name ; ]
    [ zero-no-soa-ttl yes_or_no ; ]
    [ zero-no-soa-ttl-cache yes_or_no ; ]
};

参数(Options):
directory: 服务器的工作目录.
key-directory: 保存密钥的目录.
named-xfer: 已经废弃,bind 8中定义named-xfer命令的路径.
tkey-domain: ...
tkey-dhkey: dhkey用于服务器生成dh模式的客户端共享的tkey,服务器必须加载公钥和私钥从工作目录的文件中.
cache-file: 仅为测试,没用.
dump-file: 当执行rndc dumpdb时服务器dump文件的路径.
memstatistics-file: 默认为named.memestats,当退出的服务的时候将服务器的统计信息写到文件中.
pid-file: 服务器记录进程ID的文件路径.
statictics-file: 执行rndc stats将服务器的统计信息写入文件,默认为named.stats
port: 服务器用于DNS协议的UDP/TCP端口号,默认为53.
random-device: entropy(平均信息量?)主要用于DNSSEC操作,像tkey传输,签署域的动态更新,默认为/dev/random,这个选项主要用于当服务器启动的时候初始化配置,reload将忽略这个选项.
preferred-glue: 优先胶? 优先相应的type list
root-delegation-only: 在根区域打开delegation-only的强制解析,并对exclude列表中的根域排除强制解析.
disable-algorithms: 对域禁用特定的DNSSEC算法,可以用多个,
dnssec-lookaside: 当设置dnssec-lookaside,它为验证器提供另外一个能在网络区域的顶层验证DNSKEY的方法.
dnssec-must-be-secure: 指定验证等级,如果选yes,named只接收安全的回应,如果选no,一般的dnssec验证将允许接收不安全的回应.

Boolean 参数:
auth-nxdomain: 如果选yes,AA字节一直设置为NXDOMAIN的回复,即使服务器不是真正可信赖的.默认为no,这是个从bind8后的改变,如果使用老的DNS软件,需要设置为yes.
deallocate-on-exit: 用于bind8在退出的时候进行内存泄露检测,bind9忽略此项,始终做检查.
dialup: 默认为no,是通过拨号网络的方式进行域传输,通常在每个heartbeat-interval执行,通常会抑制一些网络维护流量,一般的notify设置不受影响.
dialup mode normal refresh heart-beat refresh heart-beat notify no (default) yes no no yes no yes yes notify yes no yes refresh no yes no passive no no no notify-passive no no yes

fake-iquery: BIND8中模仿已经淘汰的IQUERY查询,BIND9中从不进行IQUERY模拟.
fetch-glue: 选项已经废弃.
flush-zone-on-shutdown: 当服务收到退出的信号,清除或者不清除未进行的域的写操作.默认为no
has-old-client: 这个选项在BIND8中执行有错误,BIND9忽略.
host-statistics: BIND8中保持name服务器相互作用的信息,BIND9无用.
maintain-ixfr-base: 已经废弃.
minimal-responses: 如果启用,产生响应的服务器只增加记录到权限和附加数据片中.此项能改善服务器性能.
multiple-cname: 这个选项在BIND8中允许域名有多个违反标准的CNAME记录,从BIND9.2开始严格执行CNAME规则在主域文件和动态更新中.
notify: 默认为yes,当服务器的一个域授权发生改变,将发送DNS NOTIFY信息给域NS记录的服务器列表,和一些列在also-notify选项中的服务器.如果选master-only,信息只发给主域,如果是explicit,通知只发给also-notify的列表,no不发通知.
recuision: 如果为yes,一个DNS的递归查询请求,服务器将必须做所有的尝试去应答查询,如果关闭递归并且服务器不知道答案,它将回复一个参考应答.默认为yes.
rfc2308-type1: BIND9已经不支持.
use-id-pool: 已经废弃.
zone-statistics: 如果为yes,服务器将收集所有区域的统计数据,除非从域的配置中关闭.)这些信息将进入rndc stats,会被dump到statistics-file.
use-ixfr: 已经废弃.
provide-ixfr: 用于主域服务器,设置为yes将进行增量传输,no将不进行增量传输,全局默认为yes.
request-ixfr: 用于从域服务器,设置为yes将向主域服务器发送增量传输的请求,no将不进行增量传输,全局默认为yes,
treat-cs-as-space: 用于BIND8使服务器对待\r字符像对待空格或者tab,使DOS,NT下的区域文件容易加载到UNIX系统中.BIND9忽略此项.
additional-from-auth,additional-from-cache: 这个选项控制权威服务器回答查询的时候的附加数据,或者当跟随CNAME和DNAME链.
match-mapped-address: ipv4映射到ipv6的地址
ixfr-from-differences: 当启用,主服务器加载一个新版本的区域或者从服务器接收到一个新版本的使用非增量传输,将进行比较新的版本和先前的版本,两个版本不同的部分记录到区域的日志,改变的将传送给从服务器作为域的增量传输.
multi-master: 通常被用于一个区域有多个地址不同的主服务器,如果启用,将不记录主服务器序号小于当前序号的服务.默认为no.
dnssec-enable: 是否支持DNSSEC开关,默认为yes
dnssec-validation: 是否进行DNSSEC确认开关,默认为no
dnssec-accept-expired: 接受验证DNSSEC签名过期的信号,默认为no
querylog: 确定querylog在服务启动时候启动,如果querylog没有指定,将使用日志分类中的queries定义的参数.
check-names: 用于约束主区域文件中的字符集和从网络收到的DNS应答.
check-mx: 检测MX记录指向的IP地址,默认为warn,其他的参数为,fail和ignore.
check-wildcard: 默认yes,检测如果为非域末端的通配符则发警告.
check-integrity: 检测主区域的完整性.默认为yes,这个检测MX和SRV记录指向的地址是否存在.
check-mx-cname: 如果设置check-integrity,那么fail,warn,ignore MX记录指向CNAME的检测,默认为warn.
check-srv-cname: 如果设置check-integrity,那么fail,warn,ignore SRV记录指向CNAME的检测,默认为warn.
check-sibling: 当执行完完整性检测,进行 兄弟? 胶? 检测,默认为yes
zero-no-soa-ttl: 当返回拒绝响应的SOA查询,在授权节中设置SOA记录的TTL值为0,默认为yes.
zero-no-soa-ttl-cache: 缓存一个拒绝响应的SOA记录的TTL设置为0,默认为no
update-check-ksk: 默认yes.当刷新RRSIGs跟随一个UPDATE请求到一个安全的区域,检测DNSSEC RR上的KSK标记来用于刷新RRSIG,此项被忽略如果非DNSSEC RRs有或者没有KSK,默认是yes

转发(Forward):
forward: 这个选项仅在转发列表不为空的情况下有作用.如果为first,将先转发再本地查询,如果为only,将只进行转发查询.
forwarders: 指定转发的IP地址表,默认地址表为空.

Dual-stack Servers:
dual-stack-servers: 指定机器的主机名或者地址进行ipv4或者ipv6传输,如果使用主机名,服务器必须能解析名字只用于传输,如果服务器是对称的,那么daul-stack-servers没有效果,除非用于传输被在命令行中关闭.

权限控制(Access Control):
allow-notify: 指定哪个服务器可以通知这个服务器,从域,当主域发生变化时.当allow-notify用于在zone中指定,将覆盖全局的选项.对从域服务器没有用.默认只有主域可以发送通知信息.
allow-query: 指定哪个服务器可以进行普通DNS查询,如果在zone中指定,将覆盖全局参数,默认允许来自全部主机的查询.
allow-query-cache: 指定哪个主机可以被允许从缓存中得到答案.
allow-recursion: 指定哪个主机可以通过服务器进行递归查询.
allow-update: 指定哪个主机可以对主域进行动态更新操作.
allow-update-forwarding: 指定哪个主机可以对从域发送动态更新,并由从域转发到主域,默认为{ none; }.
allow-v6-synthesis: 此参数目的是为了从AAAA到A6的地址平滑转变,从"nibble labels"到二进制标签.
allow-transfer: 指定那些主机可以从服务器上接收区域传输,未指定将允许传说到所有的主机.
black-hole: 指定地址列表内的地址不接受解析从或者使用一个解析查询,这些地址发出的查询不会被相应,默认为none.

接口(Interface):
listen-on port 1234 { 5.6.7.8; }; 指定在地址5.6.7.8上面的1234端口提供服务,默认为53.
listen-on-v6: 在ipv6地址上监听.

查询地址(Query Address):
query-sources address * port *;
query-sources-v6 address * port *;
如果服务器不知道答案,将查询其他的name服务器, query-source指定地址和端口用户这些查询.

区域传输(Zone Transfer):
also-notify: 定义一个向在全局的地址列表的服务器发送通知信息当刷新或者加载区域的时候.
max-transfer-time-in: 当区域传入运行的时间大于设定的分钟将被中断,默认为120 minutes,最大值为28天,40320 minutes.
max-transfer-idle-in: 当区域传入运行处于传输等待的状态,大于设定的时间将被中断,默认为60 minutes,最大值为28天.
max-transfer-time-out: 当区域传出运行的时间大于设定的时间,将被中断,默认为120 minutes,最大为28天.
max-transfer-idle-out: 当区域传出运行处于传输等待的状态,大于设定时间将被中断,默认为60 minutes,最大为28天.
serial-query-rate: 从服务器定期去主服务器查询区域的serial数字是否发生改变.默认为20秒.
serial-queries: BIND9忽略此参数,使用serial-query-rate代替.
transfer-format: 区域的传输可以使用两种不同的格式,one-answers和many-answers,one-answers传输每个记录使用一个DNS信息,many-answers近可能把资源记录打成一个包,默认为many-answers
transfer-in: 设定当前同时传入的区域的最大数目,默认为10个.区域的请求超过限制将被拒绝.
transfer-out: 设定当前同时传出的区域的最大数目,默认为10个,区域的传出请求超过限制将被决绝.
transfer-per-ns: 设定同时进行传输的区域从给定的name服务,默认为2.
transfer-source: 指定通过哪个IPV4的源地址进行域的传送.
transfer-source-v6: 指定通过哪个IPV6的源地址进行域的传送.
alt-transfer-source: 指定,如果transfer-source发生故障,通过哪个IPV4的源地址进行域的传松.
alt-transfer-source-v6: 同上.
use-alt-transfer-source: 指定是否通过alt-transfer-source进行域的传松,默认为yes,兼容BIND8.
notify-source: 指定哪个本地地址,以及本地端口被用来作为发送通知信息的源.此项受限于allow-notify.
notify-source-v6: 同notify-source.

Bad UDP Port Lists:
使用avoid-v4-udp-ports和avoid-v6-udp-ports来指定列表中的IPV4和ipv6端口不能被用于系统指定的源端口.

Operating System Resource Limits:
coresize: 用于core dump的限制.
datasize: 可以使用的最大的数据内存.
files: 最大打开文件数,默认unlimited.
stacksize: 最大使用的内存栈.

Server Resource Limits:
max-ixfr-log-size: BIND8兼容,相当于BIND9的max-journal-size.
max-journal-size: 设定每个日志文件的最大大小.默认unlimited
host-statistics-max: BIND9无效.
recursive-clients: 设定最大并发进行递归查询的数量,默认为1000.
tcp-clients: 服务器接受的最大并发tcp连接数,默认为100.
max-cache-size: 服务器缓存最大使用的内存,字节.默认为unlimited,意味着记录只有在TTL过期后才被清除出缓存.
tcp-listen-queue: 监听最深队列,默认和最小值为3.

Periodic Task Intervals:
cleaning-interval: 服务器清理过期的资源记录在每个设定的时间间隔.默认为60分钟,最大设定为28天,如果设定为0将不进行清理.
heartbeat-interval: 当被标记为dialup的区域过了设定的时间间隔,将进行区域维护任务,默认为60分钟,合理的设置是1天,最大设置为28天,如果设置为0,将不进行区域维护任务.
interface-interval: 服务器将在设定的时间间隔扫描网络接口,默认为60分钟,最大为28天,设定为0只有在配置文件重新加载的时候才进行扫描.
statistics-interval: 服务器的统计信息将在设定的期间内被记录,默认为60分钟,最大28天,设置为0将不记录.

Topology:
topology { localhost; localnets; }; BIND9无效.

Sortlist:
sortlist {
           { localhost; localnets; };
           { localnets; };
};

RRset Ordering:
rrset-order {
   class IN type A name "host.example.com" order random;
   order cyclic;
};节(Tuning):
lame-ttl: 设定缓存一个lame服务器的时间,0关闭,默认600秒,最大为1800秒.
max-ncache-ttl: 为了减少网络流量和提升性能,服务器记录不正确的回答得时间,默认为10800秒,不能超过7天.
max-cache-ttl: 设定服务器存储普通应答的最大缓存时间,默认为7天.
min-roots: BIND9无效.
sig-validity-interval: 设定DNSSEC自动生成动态更新的过期时间.默认为30天,最长10年.
min-refresh-time,max-refresh-time,min-retry-time,max-retry-time: 这些选项控制服务器的运转,当刷新一个区域或者重试失败的传输.
edns-udp-size: 这个参数设定发出的EDNS UDP包的大小,有效地值是512-4096之间,默认为4096bytes.
max-udp-size: 设定最大的EDNS信息的大小,有效地值是512-4096之间,默认为4096bytes.
masterfile-format: 指定区域文件的格式,默认为text.
clients-per-query,max-clients-per-query: 设定初始和最大数量服务器接受的客户端并发的递归查询,

服务器内建信息:
version: 版本
hostname: 主机名
server-id: 服务器ID

内建空域:
empty-server: 指定哪个服务器名将出现在返回的空域中的SOA记录,如果没指定,将使用区域的名字.
empty-contact: 指定哪个联系信息将出现在返回的空域的SOA记录中.如果没指定,将使用".".
empty-zones-enable: 打开或者关闭空的区域,默认为开启.
disable-empty-zone: 关闭单独的空地区域,默认关闭,此参数可指定多次.

额外的Cache参数:
acache-enable: 是否打开额外的cache参数.
acache-cleaning-interval: 服务器将删除过期的缓存进入,基于LRU based algorithm,每个设定的间隔时间,默认为60分钟,设置成0则不清除.
max-acache-size: 设定acache使用的最大的内存大小.servers:对特定的服务器设置参数

语法:
server ip_addr[/prefixlen] {
    [ bogus yes_or_no ; ]
    [ provide-ixfr yes_or_no ; ]
    [ request-ixfr yes_or_no ; ]
    [ edns yes_or_no ; ]
    [ edns-udp-size number ; ]
    [ max-udp-size number ; ]
    [ transfers number ; ]
    [ transfer-format ( one-answer | many-answers ) ; ]]
    [ keys { string ; [ string ; [...]] } ; ]
    [ transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ notify-source (ip4_addr | *) [port ip_port] ; ]
    [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ query-source [ address ( ip_addr | * ) ] [ port ( ip_port | * ) ]; ]
    [ query-source-v6 [ address ( ip_addr | * ) ] [ port ( ip_port | * ) ]; ]
};trusted_keys:设置可信任的DNSSEC key

语法:
trusted-keys {
    string number number number string ;
    [ string number number number string ; [...]]
};view:定义一个视图

view view_name
      [class] {
      match-clients { address_match_list };
      match-destinations { address_match_list };
      match-recursive-only yes_or_no ;
      [ view_option; ...]
      [ zone_statement; ...]
};zone:定义一个区域

zone zone_name [class] {
    type master;
    [ allow-query { address_match_list }; ]
    [ allow-transfer { address_match_list }; ]
    [ allow-update { address_match_list }; ]
    [ update-policy { update_policy_rule [...] }; ]
    [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    [ check-names (warn|fail|ignore) ; ]
    [ check-mx (warn|fail|ignore) ; ]
    [ check-wildcard yes_or_no; ]
    [ check-integrity yes_or_no ; ]
    [ dialup dialup_option ; ]
    [ file string ; ]
    [ masterfile-format (text|raw) ; ]
    [ journal string ; ]
    [ forward (only|first) ; ]
    [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ]
    [ ixfr-base string ; ]
    [ ixfr-tmp-file string ; ]
    [ maintain-ixfr-base yes_or_no ; ]
    [ max-ixfr-log-size number ; ]
    [ max-transfer-idle-out number ; ]
    [ max-transfer-time-out number ; ]
    [ notify yes_or_no | explicit | master-only ; ]
    [ pubkey number number number string ; ]
    [ notify-source (ip4_addr | *) [port ip_port] ; ]
    [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ zone-statistics yes_or_no ; ]
    [ sig-validity-interval number ; ]
    [ database string ; ]
    [ min-refresh-time number ; ]
    [ max-refresh-time number ; ]
    [ min-retry-time number ; ]
    [ max-retry-time number ; ]
    [ key-directory path_name; ]
    [ zero-no-soa-ttl yes_or_no ; ]
};

zone zone_name [class] {
    type slave;
    [ allow-notify { address_match_list }; ]
    [ allow-query { address_match_list }; ]
    [ allow-transfer { address_match_list }; ]
    [ allow-update-forwarding { address_match_list }; ]
    [ update-check-ksk yes_or_no; ]
    [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    [ check-names (warn|fail|ignore) ; ]
    [ dialup dialup_option ; ]
    [ file string ; ]
    [ masterfile-format (text|raw) ; ]
    [ journal string ; ]
    [ forward (only|first) ; ]
    [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ]
    [ ixfr-base string ; ]
    [ ixfr-tmp-file string ; ]
    [ maintain-ixfr-base yes_or_no ; ]
    [ masters [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] }; ]
    [ max-ixfr-log-size number ; ]
    [ max-transfer-idle-in number ; ]
    [ max-transfer-idle-out number ; ]
    [ max-transfer-time-in number ; ]
    [ max-transfer-time-out number ; ]
    [ notify yes_or_no | explicit | master-only ; ]
    [ pubkey number number number string ; ]
    [ transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ use-alt-transfer-source yes_or_no; ]
    [ notify-source (ip4_addr | *) [port ip_port] ; ]
    [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ zone-statistics yes_or_no ; ]
    [ database string ; ]
    [ min-refresh-time number ; ]
    [ max-refresh-time number ; ]
    [ min-retry-time number ; ]
    [ max-retry-time number ; ]
    [ multi-master yes_or_no ; ]
    [ zero-no-soa-ttl yes_or_no ; ]
};

zone zone_name [class] {
    type hint;
    file string ;
    [ delegation-only yes_or_no ; ]
    [ check-names (warn|fail|ignore) ; // Not Implemented. ]
};

zone zone_name [class] {
    type stub;
    [ allow-query { address_match_list }; ]
    [ check-names (warn|fail|ignore) ; ]
    [ dialup dialup_option ; ]
    [ delegation-only yes_or_no ; ]
    [ file string ; ]
    [ masterfile-format (text|raw) ; ]
    [ forward (only|first) ; ]
    [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ]
    [ masters [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] }; ]
    [ max-transfer-idle-in number ; ]
    [ max-transfer-time-in number ; ]
    [ pubkey number number number string ; ]
    [ transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ]
    [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    [ use-alt-transfer-source yes_or_no; ]
    [ zone-statistics yes_or_no ; ]
    [ database string ; ]
    [ min-refresh-time number ; ]
    [ max-refresh-time number ; ]
    [ min-retry-time number ; ]
    [ max-retry-time number ; ]
    [ multi-master yes_or_no ; ]
};

zone zone_name [class] {
    type forward;
    [ forward (only|first) ; ]
    [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ]
    [ delegation-only yes_or_no ; ]
};

zone zone_name [class] {
    type delegation-only;
};

区域Type:
master: 主域服务
slave: 从域服务
stub: 只复制主域的NS记录,属于BIND特有功能.
hint: 设定初始化设置根域服务器所用的参数.
forward: 域转发设置
delegation-only: 设定返回为NXDOMAIN?

发表在 article | 标签为 , | bind配置文件语法已关闭评论

linux开机启动脚本的顺序

如果

服务
器重启之后需要手工开启许多服务、工作及以后的维护相对比较繁琐、特地总结了下
linux

开机
自动启动
脚本
所涉及的
知识
和方法、如下:
1、相关
基础
知识点
  1)redhat的启动方式和执行次序是:
     加载内核
     执行init程序
     /etc/rc.d/rc.sysinit # 由init执行的第一个脚本
     /etc/rc.d/rc $runlevel # $runlevel为缺省的运行模式
     /etc/rc.d/rc.local     #相应级别服务启动之后、在执行该
文件
(其实也可以把需要执行的
命令
写到该文件中)
     /sbin/mingetty # 等待用户登录
    
     在redhat中,/etc/rc.d/rc.sysinit主要做在各个运行模式中相同的初始化工作,包括:
     调入keymap以及
系统
字体
     启动swapping
     设置主机名
     设置nis域名
     检查(fsck)并mount文件系统
     打开quota
     装载声卡模块
     设置系统时钟
     等等。
     /etc/rc.d/rc则根据其参数指定的运行模式(运行级别,你在inittab文件中可以
设置
)来执行相应目录下的脚本。凡是以kxx开头的
     ,都以stop为参数来调用;凡是以sxx开头的,都以start为参数来调用。调用的
顺序
按xx
     从小到大来执行。(其中xx是数字、表示的是启动顺序)例如,假设缺省的运行模式是3,/etc/rc.d/rc就会按上述方式调用
     /etc/rc.d/rc3.d/下的脚本。
     值得一提的是,redhat中的运行模式2、3、5都把/etc/rc.d/rc.local做为初始化脚本中
     的最后一个,所以用户可以自己在这个文件中添加一些需要在其他初始化工作之后,登录之前执行的命令。
    
     init在等待/etc/rc.d/rc执行完毕之后(因为在/etc/inittab中/etc/rc.d/rc的
     action是wait),将在指定的各个虚拟终端上运行/sbin/mingetty,等待用户的登录。
     至此,linux的启动结束。
   2)init运行级别及指令
   一、什么是init:
  init是linux系统操作中不可缺少的程序之一。
  所谓的init进程,它是一个由内核启动的用户级进程。
  内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和
数据
结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。
  内核会在过去曾使用过init的几个地方查找它,它的正确位置(对linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。
  二、运行级别
  那么,到底什么是运行级呢?
  简单的说,运行级就是
操作系统
当前正在运行的
功能
级别。这个级别从1到6 ,具有不同的功能。
  不同的运行级定义如下
  # 0 - 停机(千万不能把initdefault 设置为0 )
  # 1 - 单用户模式                                     # s   init s = init 1
  # 2 - 多用户,没有 nfs
  # 3 - 完全多用户模式(标准的运行级)
  # 4 - 没有用到
  # 5 - x11 多用户图形模式(xwindow)
  # 6 - 重新启动 (千万不要把initdefault 设置为6 )
 
 这些级别在/etc/inittab 文件里指定。这个文件是init 程序寻找的主要文件,最先运行的服务是放在/etc/rc.d
目录下的文件。在大多数的linux 发行版本中,启动脚本都是位于 /etc/rc.d/init.d中的。这些脚本被用ln 命令连接到
/etc/rc.d/rcn.d 目录。(这里的n 就是运行级0-6)
    3):chkconfig 命令(redhat 操作系统下)
    不像dos 或者
windows
,linux
可以有多种运行级。常见的就是多用户的2,3,4,5 ,很多人知道 5 是运行 x-windows 的级别,而 0 就   
是关机了。运行级的改变可以通过 init 命令来切换。例如,假设你要维护系统进入单用户状态,那么,可以使用 init 1 来切换。在   
 linux 的运行级的切换过程中,系统会自动寻找对应运行级的目录/etc/rc[0-6].d下的k 和 s
开头的文件,按后面的数字顺序,执行这      些脚本。对这些脚本的维护,是很繁琐的一件事情,linux 提供了chkconfig
命令用来更新和查询不同运行级上的系统服务。
    语法为:
   
    chkconfig --list [name]
    chkconfig --add name
    chkconfig --del name
    chkconfig [--level levels] name
    chkconfig [--level levels] name
   
    chkconfig 有五项功能:添加服务,删除服务,列表服务,改变启动信息以及检查特定服务的启动状态。
   
    chkconfig 没有参数运行时,显示用法。如果加上服务名,那么就检查这个服务是否在当前运行级启动。如果是,返回 true,否则返回      false。 --level 选项可以指定要查看的运行级而不一定是当前运行级。
   
    如果在服务名后面指定了on,off 或者 reset,那么 chkconfig 会改变指定服务的启动信息。on 和 off 分别指服务在改变运行级时的      启动和停止。reset 指初始化服务信息,无论有问题的初始化脚本指定了什么。
   
    对于 on 和 off 开关,系统默认只对运行级 3,4, 5有效,但是 reset 可以对所有运行级有效。指定 --level 选项时,可以
选择
特       定的运行级。
   
    需要说明的是,对于每个运行级,只能有一个启动脚本或者停止脚本。当切换运行级时,init 不会重新启动已经启动的服务,也不会再      次去停止已经停止的服务。
   
    选项介绍:
   
    --level levels
    指定运行级,由数字 0 到 7 构成的字符串,如:
   
    --level 35 表示指定运行级3 和5。
    要在运行级别3、4、5中停运 nfs 服务,使用下面的命令:chkconfig --level 345 nfs off
   
    --add name
    这个选项增加一项新的服务,chkconfig 确保每个运行级有一项 启动(s) 或者 杀死(k) 入口。如有缺少,则会从缺省的init 脚本自动      建立。
   
    --del name
    用来删除服务,并把相关符号连接从 /etc/rc[0-6].d 删除。
   
    --list name
    列表,如果指定了name 那么只是显示指定的服务名,否则,列出全部服务在不同运行级的状态。
   
    运行级文件
   
    每个被chkconfig
管理
的服务需要在对应的init.d 下的脚本加上两行或者更多行的注释。
    第一行告诉 chkconfig 缺省启动的运行级以及启动和停止的优先级。如果某服务缺省不在任何运行级启动,那么使用 - 代替运行级。
    第二行对服务进行描述,可以用 跨行注释。
   
    例如,random.init 包含三行:
    # chkconfig: 2345 20 80
    # description: saves and restores system entropy pool for
    # higher quality random number generation.
    表明 random 脚本应该在运行级 2, 3, 4, 5 启动,启动优先权为20,停止优先权为 80。
   
    好了,介绍就到这里了,去看看自己目录下的/etc/rc.d/init.d 下的脚本吧。 
   
    设置自启动服务:chkconfig --level 345 nfs on
   
2.
实例
介绍:

1、在linux下安装了apache 服务(通过下载二进制文件经济编译安装、而非rpm包)、apache 服务启动命令:         
/server/apache/bin/apachectl start    。让apache服务运行在运行级别3下面。  命令如下:
 
  1)touch /etc/rc.d/init.d/apache
     vi /etc/rc.d/init.d/apache
     chown -r root /etc/rc.d/init.d/apache
     chmod 700 /etc/rc.d/init.d/apache

   ln -s /etc/rc.d/init.d/apache /etc/rc.d/rc3.d/s60apache   #s
是start的简写、代表启动、k是kill的简写、代表关闭。60数字        代表启动的顺序。(对于iptv系统而言、许多服务都是建立在
数据库
启动的前提下才能够正常启动的、可以通过该数字就行调整脚本的       启动顺序))
    
     apache的内容:
     #!/bin/bash
     #start httpd service
     /server/apache/bin/apachectl start
    
     至此 apache服务就可以在运行级别3下 随机自动启动了。(可以结合chkconfig 对启动服务进行相应的调整)
 

-----------------------------------------------------------------------------------------------------------------------------------

在Redhat Redflag centos fc linux系统里面脚本的启动

先后:
第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端
rc.sysinit
rc.d(里面的脚本)
rc.local
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/etc/bashrc
/root/.bashrc
/root/.bash_profile

在Suse Linux (sles server or Desktop 10)

第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端 /etc/init.d/boot 里面包括:
. /etc/rc.status
./etc/sysconfig/boot
./etc/init.d/boot.d下面的脚本
./etc/init.d/boot.local
rc X.d(里面的脚本)
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/root/.bashrc
/root/.profile
先后:
第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端
rc.sysinit
rc.d(里面的脚本)
rc.local
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/etc/bashrc
/root/.bashrc
/root/.bash_profile

在Suse Linux (sles server or Desktop 10)

第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端 /etc/init.d/boot 里面包括:
. /etc/rc.status
./etc/sysconfig/boot
./etc/init.d/boot.d下面的脚本
./etc/init.d/boot.local
rc X.d(里面的脚本)
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/root/.bashrc
/root/.profile
先后:
第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端
rc.sysinit
rc.d(里面的脚本)
rc.local
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/etc/bashrc
/root/.bashrc
/root/.bash_profile

在Suse Linux (sles server or Desktop 10)

第一步:通过/boot/vm进行启动 vmlinuz
第二步:init /etc/inittab
第三步:启动相应的脚本,并且打开终端 /etc/init.d/boot 里面包括:
. /etc/rc.status
./etc/sysconfig/boot
./etc/init.d/boot.d下面的脚本
./etc/init.d/boot.local
rc X.d(里面的脚本)
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的
/etc/profile.d/file
/etc/profile
/root/.bashrc
/root/.profile

发表在 article | 标签为 | 25条评论

监控 SQL Server 的运行状况/使用DMV和DMF分析数据库性能

监控 SQL Server 的运行状况

URL: http://technet.microsoft.com/zh-cn/library/bb838723(office.12).aspx

Microsoft SQL Server 2005 提供了一些工具来监控数据库。方法之一是动态管理视图。动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的运行状况、诊断问题和优化性能。

常规服务器动态管理对象包括:

  • dm_db_*:数据库和数据库对象

  • dm_exec_*:执行用户代码和关联的连接

  • dm_os_*:内存、锁定和时间安排

  • dm_tran_*:事务和隔离

  • dm_io_*:网络和磁盘的输入/输出

此部分介绍为监控 SQL Server 运行状况而针对这些动态管理视图和函数运行的一些常用查询。

示例查询

您可以运行以下查询来获取所有 DMV 和 DMF 名称:

SELECT * FROM sys.system_objects
WHERE name LIKE 'dm_%'
ORDER BY name

监控 CPU 瓶颈

CPU 瓶颈通常由以下原因引起:查询计划并非最优、配置不当、设计因素不良或硬件资源不足。下面的常用查询可帮助您确定导致 CPU 瓶颈的原因。

下面的查询使您能够深入了解当前缓存的哪些批处理或过程占用了大部分 CPU 资源。

SELECT TOP 50 
      SUM(qs.total_worker_time) AS total_cpu_time, 
      SUM(qs.execution_count) AS total_execution_count,
      COUNT(*) AS  number_of_statements, 
      qs.sql_handle 
FROM sys.dm_exec_query_stats AS qs
GROUP BY qs.sql_handle
ORDER BY SUM(qs.total_worker_time) DESC

下面的查询显示缓存计划所占用的 CPU 总使用率(带 SQL 文本)。

SELECT 
      total_cpu_time, 
      total_execution_count,
      number_of_statements,
      s2.text
      --(SELECT SUBSTRING(s2.text, statement_start_offset / 2, ((CASE WHEN statement_end_offset = -1 THEN (LEN(CONVERT(NVARCHAR(MAX), s2.text)) * 2) ELSE statement_end_offset END) - statement_start_offset) / 2) ) AS query_text
FROM 
      (SELECT TOP 50 
            SUM(qs.total_worker_time) AS total_cpu_time, 
            SUM(qs.execution_count) AS total_execution_count,
            COUNT(*) AS  number_of_statements, 
            qs.sql_handle --,
            --MIN(statement_start_offset) AS statement_start_offset, 
            --MAX(statement_end_offset) AS statement_end_offset
      FROM 
            sys.dm_exec_query_stats AS qs
      GROUP BY qs.sql_handle
      ORDER BY SUM(qs.total_worker_time) DESC) AS stats
      CROSS APPLY sys.dm_exec_sql_text(stats.sql_handle) AS s2 

下面的查询显示 CPU 平均占用率最高的前 50 个 SQL 语句。

SELECT TOP 50
total_worker_time/execution_count AS [Avg CPU Time],
(SELECT SUBSTRING(text,statement_start_offset/2,(CASE WHEN statement_end_offset = -1 then LEN(CONVERT(nvarchar(max), text)) * 2 ELSE statement_end_offset end -statement_start_offset)/2) FROM sys.dm_exec_sql_text(sql_handle)) AS query_text, *
FROM sys.dm_exec_query_stats 
ORDER BY [Avg CPU Time] DESC

下面显示用于找出过多编译/重新编译的 DMV 查询。

select * from sys.dm_exec_query_optimizer_info
where 
      counter = 'optimizations'
      or counter = 'elapsed time'

下面的示例查询显示已重新编译的前 25 个存储过程。plan_generation_num 指示该查询已重新编译的次数。

select top 25
      sql_text.text,
      sql_handle,
      plan_generation_num,
      execution_count,
      dbid,
      objectid 
from sys.dm_exec_query_stats a
      cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where plan_generation_num > 1
order by plan_generation_num desc

效率较低的查询计划可能增大 CPU 占用率。

下面的查询显示哪个查询占用了最多的 CPU 累计使用率。

SELECT 
    highest_cpu_queries.plan_handle, 
    highest_cpu_queries.total_worker_time,
    q.dbid,
    q.objectid,
    q.number,
    q.encrypted,
    q.[text]
from 
    (select top 50 
        qs.plan_handle, 
        qs.total_worker_time
    from 
        sys.dm_exec_query_stats qs
    order by qs.total_worker_time desc) as highest_cpu_queries
    cross apply sys.dm_exec_sql_text(plan_handle) as q
order by highest_cpu_queries.total_worker_time desc

下面的查询显示一些可能占用大量 CPU 使用率的运算符(例如 ‘%Hash Match%’、‘%Sort%’)以找出可疑对象。

select *
from 
      sys.dm_exec_cached_plans
      cross apply sys.dm_exec_query_plan(plan_handle)
where 
      cast(query_plan as nvarchar(max)) like '%Sort%'
      or cast(query_plan as nvarchar(max)) like '%Hash Match%'

如果已检测到效率低下并导致 CPU 占用率较高的查询计划,请对该查询中涉及的表运行 UPDATE STATISTICS 以查看该问题是否仍然存在。然后,收集相关数据并将此问题报告给 PerformancePoint 规划支持人员。

如果您的系统存在过多的编译和重新编译,可能会导致系统出现与 CPU 相关的性能问题。

您可以运行下面的 DMV 查询来找出过多的编译/重新编译。

select * from sys.dm_exec_query_optimizer_info
where 
counter = 'optimizations'
or counter = 'elapsed time'

下面的示例查询显示已重新编译的前 25 个存储过程。plan_generation_num 指示该查询已重新编译的次数。

select top 25
sql_text.text,
sql_handle,
plan_generation_num,
execution_count,
dbid,
objectid 
from sys.dm_exec_query_stats a
cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where plan_generation_num > 1
order by plan_generation_num desc

如果已检测到过多的编译或重新编译,请尽可能多地收集相关数据并将其报告给规划支持人员。

内存瓶颈

开始内存压力检测和调查之前,请确保已启用 SQL Server 中的高级选项。请先对 master 数据库运行以下查询以启用此选项。

sp_configure 'show advanced options'
go
sp_configure 'show advanced options', 1
go
reconfigure
go

首先运行以下查询以检查内存相关配置选项。

sp_configure 'awe_enabled'
go
sp_configure 'min server memory'
go
sp_configure 'max server memory'
go
sp_configure 'min memory per query'
go
sp_configure 'query wait'
go

运行下面的 DMV 查询以查看 CPU、计划程序内存和缓冲池信息。

select 
cpu_count,
hyperthread_ratio,
scheduler_count,
physical_memory_in_bytes / 1024 / 1024 as physical_memory_mb,
virtual_memory_in_bytes / 1024 / 1024 as virtual_memory_mb,
bpool_committed * 8 / 1024 as bpool_committed_mb,
bpool_commit_target * 8 / 1024 as bpool_target_mb,
bpool_visible * 8 / 1024 as bpool_visible_mb
from sys.dm_os_sys_info

I/O 瓶颈

检查闩锁等待统计信息以确定 I/O 瓶颈。运行下面的 DMV 查询以查找 I/O 闩锁等待统计信息。

select wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms, wait_time_ms / waiting_tasks_count
from sys.dm_os_wait_stats  
where wait_type like 'PAGEIOLATCH%'  and waiting_tasks_count > 0
order by wait_type

如果 waiting_task_countswait_time_ms 与正常情况相比有显著变化,则可以确定存在 I/O 问题。获取 SQL Server 平稳运行时性能计数器和主要 DMV 查询输出的基线非常重要。

这些 wait_types 可以指示您的 I/O 子系统是否遇到瓶颈。

使用以下 DMV 查询来查找当前挂起的 I/O 请求。请定期执行此查询以检查 I/O 子系统的运行状况,并隔离 I/O 瓶颈中涉及的物理磁盘。

select 
    database_id, 
    file_id, 
    io_stall,
    io_pending_ms_ticks,
    scheduler_address 
from  sys.dm_io_virtual_file_stats(NULL, NULL)t1,
        sys.dm_io_pending_io_requests as t2
where t1.file_handle = t2.io_handle

在正常情况下,该查询通常不返回任何内容。如果此查询返回一些行,则需要进一步调查。

您还可以执行下面的 DMV 查询以查找 I/O 相关查询。

select top 5 (total_logical_reads/execution_count) as avg_logical_reads,
                   (total_logical_writes/execution_count) as avg_logical_writes,
           (total_physical_reads/execution_count) as avg_physical_reads,
           Execution_count, statement_start_offset, p.query_plan, q.text
from sys.dm_exec_query_stats
      cross apply sys.dm_exec_query_plan(plan_handle) p
      cross apply sys.dm_exec_sql_text(plan_handle) as q
order by (total_logical_reads + total_logical_writes)/execution_count Desc

下面的 DMV 查询可用于查找哪些批处理/请求生成的 I/O 最多。如下所示的 DMV 查询可用于查找可生成最多 I/O 的前五个请求。调整这些查询将提高系统性能。

select top 5 
    (total_logical_reads/execution_count) as avg_logical_reads,
    (total_logical_writes/execution_count) as avg_logical_writes,
    (total_physical_reads/execution_count) as avg_phys_reads,
     Execution_count, 
    statement_start_offset as stmt_start_offset, 
    sql_handle, 
    plan_handle
from sys.dm_exec_query_stats  
order by  (total_logical_reads + total_logical_writes) Desc

阻塞

运行下面的查询可确定阻塞的会话。

select blocking_session_id, wait_duration_ms, session_id from 
sys.dm_os_waiting_tasks
where blocking_session_id is not null

使用此调用可找出 blocking_session_id 所返回的 SQL。例如,如果 blocking_session_id 是 87,则运行此查询可获得相应的 SQL。

dbcc INPUTBUFFER(87)

下面的查询显示 SQL 等待分析和前 10 个等待的资源。

select top 10 *
from sys.dm_os_wait_stats
--where wait_type not in ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR')
order by wait_time_ms desc

若要找出哪个 spid 正在阻塞另一个 spid,可在数据库中创建以下存储过程,然后执行该存储过程。此存储过程会报告此阻塞情况。键入 sp_who 可找出 @spid;@spid 是可选参数。

create proc dbo.sp_block (@spid bigint=NULL)
as
select 
    t1.resource_type,
    'database'=db_name(resource_database_id),
    'blk object' = t1.resource_associated_entity_id,
    t1.request_mode,
    t1.request_session_id,
    t2.blocking_session_id    
from 
    sys.dm_tran_locks as t1, 
    sys.dm_os_waiting_tasks as t2
where 
    t1.lock_owner_address = t2.resource_address and
    t1.request_session_id = isnull(@spid,t1.request_session_id)

以下是使用此存储过程的示例。

exec sp_block
exec sp_block @spid = 7

发表在 article | 标签为 , | 监控 SQL Server 的运行状况/使用DMV和DMF分析数据库性能已关闭评论