%e4%bf%ae%e6%94%b9squid%e7%9a%84%e6%97%a5%e5%bf%97%e6%a0%bc%e5%bc%8f%e8%ae%a9awstats%e5%88%86%e6%9e%90

为了让awstats分析squid的日志,我们要修改一下它的日志格式.我们先看看squid的默认格式和解释吧.

logformat squid  %ts.%03tu %6tr %>a %Ss/%03Hs %<st %rm %ru %un %Sh/%<A %mt

解释如下:
Seconds since epoch; subsecond time (milliseconds);  Response time (milliseconds); Client source IP address;  Squid request status (TCP_MISS etc); HTTP status code; Reply size including HTTP headers;  Request method (GET/POST etc) ; Request URL;  User name;  Squid hierarchy status (DEFAULT_PARENT etc);  Client FQDN;  MIME content type

下面看看要怎么样修改,awstats才能认识和分析squid的日志

squid: /etc/squid/squid.conf
代码:

logformat combined %>a %ui %un [%tl] “%rm %ru HTTP/%rv” %Hs %<st “%{Referer}>h” “%{User-Agent}>h” %Ss:%Sh %{host}>h
access_log /var/log/squid/access.log combined

awstats: /etc/awstats/awstats.conf.local
代码:

LogFormat = “%host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot %other %virtualname”
LogFile=”/var/log/squid/access.log”

关键点: squid 的日志需要加上虚拟主机名: %{host}>h awstats的读取参数指出 %virtualname 还有一种方法,我觉得也是比较理想的,直接修改apache的日志格式:

原:
#LogFormat “%h %l %u %t \”%r\” %>s %b \”%{Referer}i\” \”%{User-Agent}i\”" combined

修改为:
LogFormat “%{X-Forwarded-For}i %l %u %t \”%r\” %>s %b \”%{Referer}i\” \”%{User-Agent}i\”"combined

这样也可以将apache的日志转为正常的日志。

07月 2nd, 2008awstats安装和配置

1.下载&&安装

http://awstats.sourceforge.net/
tar .. && cd …. && perl awstats_configure.pl
#然后根据提示操作,可以不要这步,直接根据自带的模版定义
#cp  ../cgi-bin/awstats.model.conf /etc/awstats/common.conf

2.按照一下样例设置配置文件:

#cd /etc/awstats
#vi awstats.www.zhangjianfeng.com.conf
Include “common.conf”
LogFile=”/home/apache/logs/access_log.%YYYY-24%MM-24%DD-24″  %YYYY-24%MM-24%DD-24>>>

是指用24小时前的年月日日志文件名,如access_log.20061206
SiteDomain=”www.zhangjianfeng.com
HostAliases=”zhangjianfeng.com”
DefaultFile=”index.html”
DirData=”/home/cgi-bin/awstats/data/”

3.更新数据

perl awstats.pl -config=mysite -update

4.配置apache

# Directives to allow use of AWStats as a CGI
Alias /awstatsclasses “/app/awstats-6.5/wwwroot/classes/”
Alias /awstatscss “/app/awstats-6.5/wwwroot/css/”
Alias /awstatsicons “/app/awstats-6.5/wwwroot/icon/”
ScriptAlias /awstats/ “/app/awstats-6.5/wwwroot/cgi-bin/”
<Directory “/app/awstats-6.5/wwwroot”>
Options None
AllowOverride None
Order allow,deny
Allow from all
</Directory>

5.对要分析的虚拟主机, 将CustomLog logs/access_xxx_log >>>

<<<common中的common改成combined

6. 重启apache,如果虚拟主机或目录配置好了,

http://server/awstats/awstats.pl?config=mysite

7.添加定时分析指令

crontab -e
* */1 * * * (cd /path/to/apache/cgi-bin/; ./awstats.pl >>>

<<<-update -config=blog.zhangjianfeng.com)

8.直接分析gunzip压过的log
查了一下,如果是gz格式的压缩包,可以在配置文件中参考如下格式修改:
LogFile=”gzip -d </日志的绝对路径/wwwlog%YYYY-24%MM-24%DD-24.log.gz |”

附: 其它说明

#就是不统计指定IP的访问量
SkipHosts=”x.x.x.x.”

#数据源日志格式和按天的截断规则
对于Apache:日志格式好设置:设置成combined格式即可,

日志截断麻烦一点:需要安装cronolog工具,
将日志设置成按天截断:
CustomLog “|/usr/local/sbin/cronolog >>>

<<</path/to/apache/logs/access_log.%Y%m%d” combined 比如:logs/access_log.20061126
日志是压缩格式,

可以使用gzip -d < /home/apache/logs/access_log.%YYYY-24%MM-24%DD-24.gz |

动态解压缩统计。

#多站点日志统计
AWStats自带了一个批处理工具:tools/awstats_updateall.pl,

可以批量地遍历一个目录下

所有地配置文件并运行统 计。针对多个站点,很多配置选项是重复的,

如果每个配置文件都

修改维护起来会很麻烦,所以我们可 以配置一个通用配置,比如:common.conf
然后其他站点的配置设置可以通过后面的选项覆盖和缺省不一致的配置。
awstats.www.zhangjianfeng.com.conf
Include “common.conf”
LogFile “/path/to/access_log”
SiteName “www.zhangjianfeng.com
HostAliases=”zhangjianfeng.com”

#统计指标说明
参观者:按来访者不重复的IP统计,一个IP代表一个参观者;
参观次数:一个参观者可能1天之内参观多次(比如:上午一次,下午一次),

所以按一定时间内(比如:1个小时),不重复的IP数统计,参观者 的访问次数;
网页数:不包括图片,CSS, JavaScript文件等的纯页面访问总数,

但如果一个页面使用了多个帧,

每个帧都算一个页面请求;
文件数:来自浏览器客户端的文件请求总数,包括图片,CSS,JavaScript等,

用户请求一个页面是,

如果页面中包含图片等,所以对服 务器会发出多次文件请求,文件数一般远远大于文件数;
字节:传给客户端的数据总流量;
来自REFERER中的数据:日志中的参考(REFERER)字段,

记录了访问相应网页之前地址,

因此如果用户是通过搜索引擎的搜索结果点击 进入网站的,

日志中就会有用户在相应搜索

引擎的查询地址,这个地址中就可以通过解析将用户查询使用的关键词提取出来:

##plugin

安装GeoIP
需要
GeoIP C Library
Geo::IP Perl Module (faster, but requires C library)
Geo::IP::PurePerl Module (slower, but does not require C library)
C Library和Perl Module是一组,必须先编译安装C的,再编译安装perl,

或者直接装PurePerl Module,我就是这种方式

安装GeoIP C Library
# wget http://www.maxmind.com/download>>>

<<</geoip/api/c/GeoIP-1.3.8.tar.gz
# tar zxvf GeoIP-1.3.8.tar.gz
# cd GeoIP-1.3.8
# ./configure; make; make install

安装 Geo::IP Perl Module
# wget http://www.maxmind.com/>>>

<<<download/geoip/api/perl/Geo-IP-1.25.tar.gz
# tar zxvf Geo-IP-1.25.tar.gz
# cd Geo-IP-1.25
# perl Makefile.PL
# make
# make test (在AS4下通不过,放弃,改装PurePerl Module)
# make install

以上两步也可以这样安装
# perl -MCPAN -e shell
cpan> install Geo::IP

安装Geo::IP::PurePerl Module
# wget http://www.maxmind.com/download/>>

<<geoip/api/pureperl/Geo-IP-PurePerl-1.14.tar.gz

# tar zxvf Geo-IP-PurePerl-1.14.tar.gz
# cd Geo-IP-PurePerl-1.14
# perl Makefile.PL
# make
# make test
# make install
也可以这样安装
# perl -MCPAN -e shell
cpan> install Geo::IP::PurePerl
修改/usr/local/etc/awstats/awstats.www.test.com.conf,

取消下面这行的注释,启用此插件
LoadPlugin=”geoip GEOIP_STANDARD”

更新GeoIP库
# cd /usr/local/share/GeoIP/
# wget http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz
# gunzip GeoIP.dat.gz
定时更新GeoIP库
0 0 * * * root /usr/local/bin/geoipupdate -v

安装XWhois
# perl -MCPAN -e shell
cpan> install Net::XWhois
修改/usr/local/etc/awstats/awstats.www.test.com.conf,

取消下面这行的注释,启用此插件
LoadPlugin=”hostinfo”

安装decodeutfkeys
# perl -MCPAN -e shell
cpan> install URI::Escape
修改/usr/local/etc/awstats/awstats.www.test.com.conf,

取消下面这行的注释,启用此插件
LoadPlugin=”decodeutfkeys”

更新日志
/usr/local/awstats/wwwroot/cgi-bin/awstats.pl

-config=www.zhangjianfeng.com-update -lang=c

apache-rewrite%e4%be%8b%e5%ad%90%e9%9b%86%e5%90%88

虚拟主机世界近期更换了域名,新域名为 www.wbhw.com, 更加简短好记。这时需要将原来的域名 webhosting-world.com, 以及论坛所在地址 webhosting-world.com/forums/ 定向到新的域名,以便用户可以找到,并且使原来的论坛 URL 继续有效而不出现 404 未找到,比如原来的 http://www. webhosting-world.com/forums/-f60.html, 让它在新的域名下继续有效,点击后转发到 http://bbs.wbhw.com/-f60.html, 这就需要用 apache 的 Mod_rewrite 功能来实现。

在< virtualhost> 中添加下面的重定向规则:

RewriteEngine On
# Redirect webhosting-world.com/forums to bbs.wbhw.com
RewriteCond %{REQUEST_URI} ^/forums/
RewriteRule /forums/(.*) http://bbs.wbhw.com/$1 [R=permanent,L]

# Redirect webhosting-world.com to wbhw.com
RewriteCond %{REQUEST_URI} !^/forums/
RewriteRule /(.*) http://www.wbhw.com/$1 [R=permanent,L]

添加了上面的规则以后, 里的全部内容如下:

< virtualhost *:80>
ServerAlias webhosting-world.com
ServerAdmin admin@webhosting-world.com
DocumentRoot /path/to/webhosting-world/root
ServerName www.webhosting-world.com
RewriteEngine On
# Redirect webhosting-world.com/forums to bbs.wbhw.com
RewriteCond %{REQUEST_URI} ^/forums/
RewriteRule /forums/(.*) http://bbs.wbhw.com/$1 [R=permanent,L]

# Redirect webhosting-world.com to wbhw.com
RewriteCond %{REQUEST_URI} !^/forums/
RewriteRule /(.*) http://www.wbhw.com/$1 [R=permanent,L]
< /virtualhost>

 

 

URL重定向例子一:
1.http://www.zzz.com/xxx.php-> http://www.zzz.com/xxx/
2.http://yyy.zzz.com-> http://www.zzz.com/user.php?username=yyy 的功能

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.zzz.com
RewriteCond %{REQUEST_URI} !^user\.php$
RewriteCond %{REQUEST_URI} \.php$
RewriteRule (.*)\.php$ http://www.zzz.com/$1/ [R]RewriteCond %{HTTP_HOST} !^www.zzz.com
RewriteRule ^(.+) %{HTTP_HOST} [C]
RewriteRule ^([^\.]+)\.zzz\.com http://www.zzz.com/user.php?username=$1

 

 

例子二:
/type.php?typeid=* –> /type*.html
/type.php?typeid=*&page=* –> /type*page*.html

RewriteRule ^/type([0-9]+).html$ /type.php?typeid=$1 [PT]
RewriteRule ^/type([0-9]+)page([0-9]+).html$ /type.php?typeid=$1&page=$2 [PT]

%e5%a6%82%e4%bd%95%e7%bc%96%e5%86%99%e5%85%bc%e5%ae%b9%e5%90%84%e4%b8%bb%e6%b5%81%e9%82%ae%e7%ae%b1%e7%9a%84html%e9%82%ae%e4%bb%b6

1、全局规则之一,不要写<style>标签、不要写class,所有CSS都用style属性,什么元素需要什么样式就用style写内联的CSS。
2、全局规则之二,少用图片,邮箱不会过滤你的img标签,但是系统往往会默认不载入陌生来信的图片,如果用了很多图片的邮件,在片没有载入的情况下,丑陋无比甚至看不清内容,没耐心的用户直接就删除了。图片上务必加上alt。
3、不要在style里面写float、position这些style,因为会被过滤。那么如何实现左右布局或者更复杂的布局呢?用table。
4、 style内容里面background可以设置color,但是img会被过滤,就是说不能通过CSS来设置背景图片了。但是有一个很有意思的元素属 性,也叫background,里面可以定义一个图片路径,这是个不错的替代方案,虽然这样功能有限,比如无法定位背景图片了,有总比没有好。例如要给一 个单元格加一个背景,必须这样写:
5、div模式的邮箱不支持flash,iframe模式的有待验证。

网上一直流传eAccelerator不支持php5.1 我还是决定试一下,结果发现Class中的protected变量出错。
然后又在Google上搜索,发现很多人提出这个问题,最后在eAccelerator.net看到作者已经解决了这个问题,只是没有放进eAccelerator0.95的发行版:
http://eaccelerator.net/

svn checkout http://dev.eaccelerator.net/eaccelerator/trunk

也可以直接下载这个安装包(可以从官方网站上面下载)

./configure –enable-eaccelerator –with-eaccelerator-shared-memory –with-eaccelerator-sessions –with-eaccelerator-content-caching –with-eaccelerator-disassembler -with-php-config=/usr/local/php/bin/php-config

make
make install

首先到http://www.Imagemagick.org去下载有关软件包来安装和配置
1.安装Imagemagick(6.3.9-10): 
  ./configure –prefix=/usr/local/ImageMagick –enable-shared –enable-lzw LDFLAGS=”-L/usr/lib” CPPFLAGS=”-I/usr/include”
2.安装Imagemagick2.1.0-rc(PHP客户端工具为例):
./configure –with-php-config=/usr/local/php/bin/php-config –with-imagick=/usr/local/ImageMagick

3.安装附加软件magickwand1.7.0(PHP为例):
./configure –with-php-config=/usr/local/php/bin/php-config –with-magickwand=/usr/local/ImageMagick

以上安装测试在linux AS4上调试成功.WEB环境是:Apache2.0.55+Php5
大家要以在PHP4版上可以进行调试一下.PHP4这个环境我没有试过.请大家也要以尝试一下.
关于其他Imagemagick客户端软件有java、perl、python、C++等等有兴趣可以调试一下。

MySQL 4.1开始,对多语言的支持有了很大变化 (这导致了问题的出现)。尽管大部分的地方 (包括个人使用和主机提供商),MySQL 3、4.0 仍然占主导地位;但 MySQL 4.1 乃至5.0是 MySQL 官方推荐的数据库,已经有主机提供商开始提供并将会越来越多;因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集,成功的蒙蔽了许多 PHP 程序的开发者和用户,掩盖了在中文等语言环境下会出现的问题。
MySQL 4.1开始把多国语言字符集分的更加详细,所以导致数据库迁移,或则dz论坛升级到4.0后(dz4.0开始使用gbk或utf-8编码)出现乱码问题。
MySQL 4.1的字符集支持(Character Set Support)有两个方面:字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次: 服务器(server),数据库(database),数据表(table)和连接(connection)。
查看系统的字符集和排序方式的设定可以通过下面的两条命令:
QUOTE:
mysql> SHOW VARIABLES LIKE ‘character_set_%’;
+————————–+—————————-+
| Variable_name | Value |
+————————–+—————————-+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+————————–+—————————-+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE ‘collation_%’;
+———————-+——————-+
| Variable_name | Value |
+———————-+——————-+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+———————-+——————-+
3 rows in set (0.00 sec)
MySQL 4.1 对于字符集的指定可以细化到一台机器上安装的 MySQL,其中的一个数据库,其中的一张表,其中的一栏,应该用什么字符集。但是,传统的 Web 程序在创建数据库和数据表时并没有使用那么复杂的配置,它们用的是默认的配置,那么,默认的配置从何而来呢?
编译 MySQL 时,指定了一个默认的字符集,这个字符集是 latin1;
安装 MySQL 时,可以在配置文件 (my.ini) 中指定一个默认的的字符集,如果没指定,这个值继承自编译时指定的;
启动 mysqld 时,可以在命令行参数中指定一个默认的的字符集,如果没指定,这个值继承自配置文件中的;
此时 character_set_server 被设定为这个默认的字符集;
当创建一个新的数据库时,除非明确指定,这个数据库的字符集被缺省设定为 character_set_server;
当选定了一个数据库时,character_set_database 被设定为这个数据库默认的字符集;
在这个数据库里创建一张表时,表默认的字符集被设定为 character_set_database,也就是这个数据库默认的字符集;
当在表内设置一栏时,除非明确指定,否则此栏缺省的字符集就是表默认的字符集;
这个字符集就是数据库中实际存储数据采用的字符集,mysqldump 出来的内容就是这个字符集下的;
当我们按照原来的方式通过PHP存取MySQL数据库时,就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询,你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。
想要进行“正确”的存储和得到“正确”的结果,最方便的是在所有query开始之前执行一下:
SET NAMES ‘gbk’;
其中gbk是数据库字符集。
它相当于下面的三句指令:
SET character_set_client = gbk;
SET character_set_results = gbk;
SET character_set_connection = gbk;
4.1和5.0默认使用的是latin1字符集(木头:妈的,老外真霸道,妄想让全世界都是使用瑞典字符集吗)
如果我们只想使用gbk字符集存储和获取数据,
我们在编译mysql 4.1和 5.0的时候,需要注意在my.ini或者my.cnf中添加两处参数

[mysqld]
default-character-set=utf8
#settings for clients (connection, results, clients)
[mysql]
default-character-set=utf8
下面我们来说主题,如何转换数据库字符集
两种方法,

第一种—-更改存储字符集
主要的思想就是把数据库的字符集有latin1改为gbk,big5,或者utf8; 以下操作必须拥有主机权限。假设当前操作的数据库名为:database 导出
首先需要把数据导为mysql4.0的格式,具体的命令如下:
mysqldump -uroot -p –default-character-set=latin1 –set-charset=gbk –skip-opt databse > d4.sql

–default-characte-set 以前数据库的字符集,这个一般情况下都是latin1的,
–set-charset 导出的数据的字符集,这个可以设置为gbk,utf8,或者big5
导入
首先使用下面语句新建一个GBK字符集的数据库(test)
CREATE DATABASE `d4` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
然后把刚才导出的数据导入到当前的数据库中就ok了。
mysql -uroot -p --default-character-set=gbk -f d4 < d4 .sql
通过以上的导出和导入就把数据库的字符集改为正确的存储方式了。
其中d4为新建库的名称,d4.sql为导出文件的名字
但是这种方法,发现数据库数据存储量无端变大30%,真是郁闷

QUOTE:
另外一种其实原理相同,但是需要手动操作,一般用于第一种方法失败后的选择
不过这种方法如果数据库很大,估计很难做,因为光打开文件就能让你死机

首先还是用phpmyadmin或者用mysql本身的dump导出 .sql文件
然后用UltraEdit打开你备份的所有xxxx.sql文件,查找
DEFAULT CHARSET=latin1
latin1这里也许是别的,反正是你不想要的,要转成gbk或者big5的字符集
把这个替换为“空”
在查找9
CREATE TABLE cdb_sessions (
sid char(6) character set latin1 collate latin1_bin NOT NULL default ”,
ip1 tinyint(3) unsigned NOT NULL default ‘0′,
ip2 tinyint(3) unsigned NOT NULL default ‘0′,
ip3 tinyint(3) unsigned NOT NULL default ‘0′,
ip4 tinyint(3) unsigned NOT NULL default ‘0′,
uid mediumint(8) unsigned NOT NULL default ‘0′,
username char(15) NOT NULL default ”,
groupid smallint(6) unsigned NOT NULL default ‘0′,
styleid smallint(6) unsigned NOT NULL default ‘0′,
invisible tinyint(1) NOT NULL default ‘0′,
`action` tinyint(1) unsigned NOT NULL default ‘0′,
lastactivity int(10) unsigned NOT NULL default ‘0′,
fid smallint(6) unsigned NOT NULL default ‘0′,
tid mediumint(8) unsigned NOT NULL default ‘0′,
nickname char(15) NOT NULL default ”,
UNIQUE KEY sid (sid)
) ENGINE=HEAP MAX_ROWS=1000;
替换为
CREATE TABLE `cdb_sessions` (
`sid` char(6) binary NOT NULL default ”,
`ip1` tinyint(3) unsigned NOT NULL default ‘0′,
`ip2` tinyint(3) unsigned NOT NULL default ‘0′,
`ip3` tinyint(3) unsigned NOT NULL default ‘0′,
`ip4` tinyint(3) unsigned NOT NULL default ‘0′,
`uid` mediumint(8) unsigned NOT NULL default ‘0′,
`username` char(15) NOT NULL default ”,
`groupid` smallint(6) unsigned NOT NULL default ‘0′,
`styleid` smallint(6) unsigned NOT NULL default ‘0′,
`invisible` tinyint(1) NOT NULL default ‘0′,
`action` tinyint(1) unsigned NOT NULL default ‘0′,
`lastactivity` int(10) unsigned NOT NULL default ‘0′,
`fid` smallint(6) unsigned NOT NULL default ‘0′,
`tid` mediumint(8) unsigned NOT NULL default ‘0′,
`nickname` char(15) NOT NULL default ”,
UNIQUE KEY `sid` (`sid`)
) TYPE=HEAP MAX_ROWS=2000;
这一步更为简单的办法就是删除掉关于cdb_sessions表的这一段,将来全新装一个d4,将这个表导出
将其内容复制,粘贴到 sql文件的最后面
保存后,再把这个sql文件导入到你的库中
就OK了
用这两种方法就可以很方便的把4.1和5.0的mysql数据库降级到4.0
简单的过程就是
A导出4.1/5.0的库
B进行处理,转换成gbk字符集
C彻底卸载4.1或者5.0
D安装4.0.26
E然后导入处理完的库
降级的时候导出库可以用这个方法
mysqldump -uroot -p –default-character-set=latin1 –set-charset=gbk –skip-opt databse –compatible=mysql40 > d4.sql
这样导出的就是4.0的库勒
至于mysql版本的升级,
如果数据文件中有中文信息,那么将MySQL 4.0的数据文件,直接拷贝到MySQL 4.1中就是不可以的,即便在my.ini中设置了default-character-set为正确的字符集。虽然貌似没有问题,但MySQL 4.1的字符集有一处非常恼人的地方,以gbk为例,原本MySQL 4.0数据中varchar,char等长度都会变为原来的一半,这样存储中文容量不变,而英文的存储容量就少了一半。这是直接拷贝数据文件带来的最大问题。
所以,升级的根本,如果想使用“正确”的字符集,还是先用mysqldump导出成文件,然后导入

03月 18th, 2008AJAX框架–Spry 介绍

最近看完了Adobe的AJAX框架Spry的所有文档和Demo,觉得这东西挺有意思的,在这里介绍给大家。
Spry框架的开发人员是来 自于DreamWeaver开发组,他们把Spry框架做为DreamWeaver的一个完美补充为设计者和开发者提供对AJAX技术的支持。Spry框 架是一个轻量级的AJAX框架,它的代码和标签十分的简洁和优雅,以保证让用户能便捷的使用,并不会为过繁杂的标签所惑。

Spry框架的官方网址:
http://labs.adobe.com/technologies/spry
在这里你能找到最新的文档和下载最新的Spry版本,目前版本是预览版1.3_08-11。
大家可以先在下面的看到Spry的示例和Demo:
http://labs.adobe.com/technologies/spry/samples/
http://labs.adobe.com/technologies/spry/demos/
Spry框架其实就是一个客户端的JavaScript类库,包含了一组JavaScript文件,CSS,图片文件,通过官方的框架结构图,我们能看 出Spry框架的核心是四部分:XML数据器(XML Data Sets),动态区域(Dynamic Regions),装饰器库(Widgets)和变化效果库(Transition Effects)。

我们可以看出,Spry框架接收的数据格式只是XML数据格式。
一,XML数据器(XML Data Sets)
XML数据器是一个提供了从XML文档中载入和管理数据的JavaScript对象。它是Spry框架中处理XML格式数据的一个JavaScript 功能实现。通过它,我们可以从XML中直接得到转换成表格数据格式的行和列的值,其实就是数组。它封装了获取XMLhttpRequest的方法,和发送 并接收数据等一系列获取数据的方法。
要创建一个XML数据器,你必须在你的HTML文件中加入两行引入JavaScript文件的代码:

上面引入的是Spry框架的核心js文件之一。”xpath.js”是Google基于XPath 1.0标准的JavaScript功能实现。你如果想获得更多的关于它的信息,可以访问Google的开源项目 google-ajaxslt project page .
“SpryData.js”则包含了定义XML数据器和动态区域的代码。
构造XML数据器就好像新建一个类一样,用”new”关键字即可:

var dsPhotos = new Spry.Data.XMLDataSet(”/photos.php?galleryid=2000″, “/gallery/photos/photo”);

Spry框架为XML数据器提供了一些有特色的功能:如数据排序,数据过滤,按指定时间间隔自动更新,并引入了观察者通知模式以支持事件的触发。
关于XML数据器更多资料,大家可以参考http://labs.adobe.com/technologies/spry/articles/data_set_overview/,这一部分笔者已经翻译完成了,但英文原文其实写的通俗易懂,如果对一些名词翻译的不准确反倒会误导了大家,所以还是不贴出来了,大家可以参考官方英文文档。
二,动态区域(Dynamic Regions)
一旦你建立了XML数据器,你就可以在动态区域中去显示这个数据器的数据了。
创建动态区域块很简单,只要在html标签的相应位置加上”spry:region”属性就可以了,Spry框架就会知道这一块是被标识成动态区域了。
在动态区域,你可以有条件的选择要输出的数据,也可用循环输出。
动态区域另一个特点就是,它分为master和detail两个区域类型。
如下面的Demo截图:

master区域的数据改变会使detail区域的数据相应发生改变

两者都注册成XML数据器的观察者

当master区域的数据变化时,触发detail区域的响应事件,从面达到更新相应数据。
大家可参考http://labs.adobe.com/technologies/spry/samples/DataSetMasterDetailSample.html所示的功能。
这只是动态区域简单的示例,复杂的情况可能会有多个XML数据器与多个动态区域相互关联触发。
三,装饰器库(Widgets)
一个装饰器是由一组HTML,CSS,JavaScript封装成的高级UI。最常见的装饰器有可折叠的菜单,树型菜单和选项table面板等。这些对 象都比较难于创建,需要一些更高级的编程经验。Spry的开发组在创建装饰器这一概念就是希望开发者们能相互协作,共享各自的设计,把这些高级界面元素用 在自己的页面上。
Spry框架下的装饰器是易于编辑的。这种模型非常适合于设计者和编辑人员:要改变外观,只要改变CSS就可以了,要增加一个可折叠菜单只要copy和paste一个代码块就够了。
如,你能看懂的这段代码是创建了一个可折叠菜单吗?

Panel Header 1
Panel 1 Content

Panel Header 2
Panel 2 Content

Panel Header 3
Panel 3 Content

var acc1 = new Hanzo.Widget.Accordion(”Acc1″);

这段代码是非常简洁清晰的,没有什么繁杂的标签,这样设计是为了易于阅读。
关于这个例子,可以参考http://labs.adobe.com/technologies/spry/samples/accordion/AccordionSample.html
四,变化效果库(Transition Effects)
Spry框架的变化效果库都存于SpryEffects.js文件中,是基于JavaScript的一些动态变化效果,如,淡出,改变形状等。
Spry框架在设计时,曾考虑直接用第三方的效果库,如Script.aculo.us,但后来开发小组觉得要保证框架代码和标签的一致性,还是选择了 自已开发,但是也基本上是以Script.aculo.us为原型进行设计,因为Script.aculo.us 本身就是一个非常优秀的变化效果库框架。
由于Spry框架现在只是预览版,所以目前只支持七种变换:
Appear/Fade Makes an element appear or fade away
Highlight Flashes a color as the background of an element
BlindUp/BlindDown Simulates a window blind, up or down, where the contents of the affected elements stay in place
SlideUp/SlideDown Simulates a window blind, where the contents of the affected element scroll accordingly
Grow/Shrink Increases/reduces the size of the element
Shake Moves the element slightly to the left, then to the right, repeatedly
Squish Reduces the element to its top-left corner and disappears

今天突然想到写一个nginx和php-fastcgi启动脚本,以方便以后开发方便做好准备

touch /etc/init.d/ngnix chmod 0775 nginx vi /etc/init.d/eginx文件写入shell脚本如下:

#!/bin/sh
#
# chkconfig: 2345 08 99
# description: Starts, stops nginx
#
#dscription: Startup script for nginx webserver on Debian. Place in /etc/init.d and
# run 'sudo update-rc.d nginx defaults', or use the appropriate command on your
# distro.
#
# Author: oscar zhang
# Modified: Oscar zhang http://blog.painiu.com
set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC=”nginx daemon”
NAME=nginx
DAEMON=/usr/local/nginx/sbin/$NAME
CONFIGFILE=/usr/local/nginx/conf/nginx.conf
PIDFILE=/usr/local/nginx/logs/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

d_start() {
echo “Starting $DESC: $NAME”
$DAEMON -c $CONFIGFILE || echo ” already running”
}

d_stop() {
echo “Stopping $DESC: $NAME”
test -f $PIDFILE && kill -QUIT `cat $PIDFILE`
}

d_reload() {
echo “Reloading $DESC configuration…”
kill -HUP `cat $PIDFILE` || echo ” can’t reload”
}
case “$1″ in
start)
d_start
echo “started.”
;;
stop)
d_stop
echo “stoped.”
;;
reload)
d_reload
echo “reloaded.”
;;
restart)
echo “Restarting $DESC: $NAME”
d_stop
# One second might not be time enough for a daemon to stop,
# if this happens, d_start will fail (and dpkg will break if
# the package is being upgraded). Change the timeout if needed
# be, or change d_stop to have start-stop-daemon use –retry.
# Notice that using –retry slows down the shutdown process somewhat.
sleep 3
d_start
echo “.”
;;
*)
echo “Usage: $SCRIPTNAME {start|stop|restart|force-reload}” >&2
exit 3
;;
esac
exit 0
保存文件,用chkconfig –list nginx查看是否是一个可用后台启动服务,如果是的话,可以直接执行chkconfig –add nginx,这个后台服务搞定
接下可以用service nginx start|restart|stop来操作你的nginx服务器

php-fastcgi后台服务和做法以上相册这里时间关系就粘这个代码


#!/bin/sh
#
# chkconfig: 2345 08 99
# description: Starts, stops nginx
#
#dscription: Startup script for nginx webserver on Debian. Place in /etc/init.d and
# run 'sudo update-rc.d nginx defaults', or use the appropriate command on your
# distro.
#
# Author: oscar zhang
# Modified: oscar zhang http://blog.painiu.com
set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC=”php-fastcgi daemon”
NAME=php-fastcgi
DAEMON=/usr/local/php/bin/spawn-fcgi
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

phpcgi=”/usr/local/php/bin/php-cgi”
prog=$(basename ${phpcgi})

FCGIPORT=”10080″
FCGIADDR=”127.0.0.1″
FCGIUSER=”nobody”
FCGIGROUP=”nobody”
PHP_FCGI_CHILDREN=5
PHP_FCGI_MAX_REQUESTS=1000

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

d_start() {
echo “Starting $DESC: $NAME”
#$DAEMON -c $CONFIGFILE || echo ” already running”
$DAEMON -a $FCGIADDR -p $FCGIPORT -C $PHP_FCGI_CHILDREN -u $FCGIUSER -g $FCGIGROUP -P $PIDFILE -f “${phpcgi}” || echo ” already r
unning”
}

d_stop() {
echo “Stopping $DESC: $NAME”
test -f $PIDFILE && kill -QUIT `cat $PIDFILE`
}

d_reload() {
echo “Reloading $DESC configuration…”
kill -HUP `cat $PIDFILE` || echo ” can’t reload”
}
case “$1″ in
start)
d_start
echo “started.”
;;
stop)
d_stop
echo “stoped.”
;;
reload)
d_reload
echo “reloaded.”
;;
restart)
echo “Restarting $DESC: $NAME”
d_stop
# One second might not be time enough for a daemon to stop,
# if this happens, d_start will fail (and dpkg will break if
# the package is being upgraded). Change the timeout if needed
# be, or change d_stop to have start-stop-daemon use –retry.
# Notice that using –retry slows down the shutdown process somewhat.
sleep 3
d_start
echo “.”
;;
*)
echo “Usage: $SCRIPTNAME {start|stop|restart|force-reload}” >&2
exit 3
;;
esac
exit 0

一、LiveJournal发展历程

LiveJournal是99年始于校园中的项目,几个人出于爱好做了这样一个应用,以实现以下功能:

  • 博客,论坛
  • 社会性网络,找到朋友
  • 聚合,把朋友的文章聚合在一起

LiveJournal采用了大量的开源软件,甚至它本身也是一个开源软件。在上线后,LiveJournal实现了非常快速的增长:

  • 2004年4月份:280万注册用户。
  • 2005年4月份:680万注册用户。
  • 2005年8月份:790万注册用户。
  • 达到了每秒钟上千次的页面请求及处理。
  • 使用了大量MySQL服务器。
  • 使用了大量通用组件。

二、LiveJournal架构现状概况

livejournal_backend.png

三、从LiveJournal发展中学习

LiveJournal从1台服务器发展到100台服务器,这其中经历了无数的伤痛,但同时也摸索出了解决这些问题的方法,通过对LiveJournal的学习,可以让我们避免LJ曾经犯过的错误,并且从一开始就对系统进行良好的设计,以避免后期的痛苦。

下面我们一步一步看LJ发展的脚步。

1、一台服务器

一 台别人捐助的服务器,LJ最初就跑在上面,就像Google开始时候用的破服务器一样,值得我们尊敬。这个阶段,LJ的人以惊人的速度熟悉的Unix的操 作管理,服务器性能出现过问题,不过还好,可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。

最终问题出现了,网站越来越慢,已经无法通过优过化来解决的地步,需要更多的服务器,这时LJ开始提供付费服务,可能是想通过这些钱来购买新的服务器,以解决当时的困境。
毫无疑问,当时LJ存在巨大的单点问题,所有的东西都在那台服务器的铁皮盒子里装着。

LJ-backend-7.png

2、两台服务器

用付费服务赚来的钱LJ买了两台服务器:一台叫做Kenny的Dell 6U机器用于提供Web服务,一台叫做Cartman的Dell 6U服务器用于提供数据库服务。

LJ-backend-8.png

LJ有了更大的磁盘,更多的计算资源。但同时网络结构还是非常简单,每台机器两块网卡,Cartman通过内网为Kenny提供MySQL数据库服务。

暂时解决了负载的问题,新的问题又出现了:

  • 原来的一个单点变成了两个单点。
  • 没有冷备份或热备份。
  • 网站速度慢的问题又开始出现了,没办法,增长太快了。
  • Web服务器上CPU达到上限,需要更多的Web服务器。

3、四台服务器

又买了两台,Kyle和Stan,这次都是1U的,都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。

LJ-backend-9.png

LJ把Kenny用于外部的网关,使用mod_backhand进行负载均横。

然后问题又出现了:

  • 单点故障。数据库和用于做网关的Web服务器都是单点,一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换,但还是无法解决数据库的单点,LJ当时也没做这个。
  • 网站又变慢了,这次是因为IO和数据库的问题,问题是怎么往应用里面添加数据库呢?

4、五台服务器

又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式),写操作全部针对主数据库(通过Binlog,主服务器上的写操作可以迅速同步到从服务器上),读操作在两个数据库上同时进行(也算是负载均横的一种吧)。

LJ-backend-10.png

实现同步时要注意几个事项:

  • 读操作数据库选择算法处理,要选一个当前负载轻一点的数据库。
  • 在从数据库服务器上只能进行读操作
  • 准备好应对同步过程中的延迟,处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可,读操作不存在同步问题。

5、更多服务器

有钱了,当然要多买些服务器。部署后快了没多久,又开始慢了。这次有更多的Web服务器,更多的数据库服务器,存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。

LJ-backend-11.png

6、现在我们在哪里:

LJ-backend-1.png

现在服务器基本上够了,但性能还是有问题,原因出在架构上。

数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内,这样唯一的好处就是将读操作分布到了多台机器,但这样带来的后果就是写操作被大量分发,每台机器都要执行,服务器越多,浪费就越大,随着写操作的增加,用于服务读操作的资源越来越少。

LJ-backend-2.png

由一台分布到两台

LJ-backend-3.png

最终效果

现在我们发现,我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID,数据库也进行了备份,这么多的备份完全是对资源的浪费,属于冗余极端过度。那为什么不把数据分布存储呢?

问题发现了,开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储,以实现数据的分布式存储,让每台机器只为相对固定的用户服务,以实现平行的架构和良好的可扩展性。

为 了实现用户分组,我们需要为每一个用户分配一个组标记,用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个slave 组成,并且slave的数量在2-3台,以实现系统资源的最合理分配,既保证数据读操作分布,又避免数据过度冗余以及同步操作对系统资源的过度消耗。

LJ-backend-4.png

由一台(一组)中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上,所有针对用户的操作需要先查询这台机器得到用户的组号,然后再到相应的数据库组中获取数据。

这样的用户架构与目前LJ的架构已经很相像了。

在具体的实现时需要注意几个问题:

  • 在数据库组内不要使用自增ID,以便于以后在数据库组之间迁移用户,以实现更合理的I/O,磁盘空间及负载分布。
  • 将userid,postid存储在全局服务器上,可以使用自增,数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。
  • 在数据库组之间迁移用户时要万分小心,当迁移时用户不能有写操作。

7、现在我们在哪里

LJ-backend-5.png

问题:

  • 一个全局主服务器,挂掉的话所有用户注册及写操作就挂掉。
  • 每个数据库组一个主服务器,挂掉的话这组用户的写操作就挂掉。
  • 数据库组从服务器挂掉的话会导致其它服务器负载过大。
  • 对于Master-Slave模式的单点问题,LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的,并不是由MySQL直接提供的,实际上也就是两台机器同时是Master,也同时是Slave,互相同步。

Master-Master实现时需要注意:

  • 一个Master出错后恢复同步,最好由服务器自动完成。
  • 数字分配,由于同时在两台机器上写,有些ID可能会冲突。

解决方案:

  • 奇偶数分配ID,一台机器上写奇数,一台机器上写偶数
  • 通过全局服务器进行分配(LJ采用的做法)。

Master-Master模式还有一种用法,这种方法与前一种相比,仍然保持两台机器的同步,但只有一台机器提供服务(读和写),在每天晚上的时候进行轮换,或者出现问题的时候进行切换。

8、现在我们在哪里

LJ-backend-6.png

现在插播一条广告,MyISAM VS InnoDB。

使用InnoDB:

  • 支持事务
  • 需要做更多的配置,不过值得,可以更安全的存储数据,以及得到更快的速度。

使用MyISAM:

  • 记录日志(LJ用它来记网络访问日志)
  • 存储只读静态数据,足够快。
  • 并发性很差,无法同时读写数据(添加数据可以)
  • MySQL非正常关闭或死机时会导致索引错误,需要使用myisamchk修复,而且当访问量大时出现非常频繁。

9、缓存

去年我写过一篇文章介绍memcached,它就是由LJ的团队开发的一款缓存工具,以key-value的方式将数据存储到分布的内存中。LJ缓存的数据:

  • 12台独立服务器(不是捐赚的)
  • 28个实例
  • 30GB总容量
  • 90-93%的命中率(用过squid的人可能知道,squid内存加磁盘的命中率大概在70-80%)

如何建立缓存策略?

想缓存所有的东西?那是不可能的,我们只需要缓存已经或者可能导致系统瓶颈的地方,最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。

缓存的缺点?

  • 没有完美的事物,缓存也有缺点:
  • 增大开发量,需要针对缓存处理编写特殊的代码。
  • 管理难度增加,需要更多人参与系统维护。
  • 当然大内存也需要钱。

10、Web访问负载均衡

在数据包级别使用BIG-IP,但BIG-IP并不知道我们内部的处理机制,无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用,不是已经够快了,就是达不到我们想要的效果。

所以,LJ又开发了Perlbal。特点:

  • 快,小,可管理的http web 服务器/代理
  • 可以在内部进行转发
  • 使用Perl开发
  • 单线程,异步,基于事件,使用epoll , kqueue
  • 支持Console管理与http远程管理,支持动态配置加载
  • 多种模式:web服务器,反向代理,插件
  • 支持插件:GIF/PNG互换?

11、MogileFS

LJ使用开源的MogileFS作为分布式文件存储系统。MogileFS使用非常简单,它的主要设计思想是:

  • 文件属于类(类是最小的复制单位)
  • 跟踪文件存储位置
  • 在不同主机上存储
  • 使用MySQL集群统一存储分布信息
  • 大容易廉价磁盘

到目前为止就这么多了,更多文档可以在http://www.danga.com/words/找到。Danga.comLiveJournal.com的 同学们拿这个文档参加了两次MySQL Con,两次OS Con,以及众多的其它会议,无私的把他们的经验分享出来,值得我们学习。在web2.0时代快速开发得到大家越来越多的重视,但良好的设计仍是每一个应 用的基础,希望web2.0们在成长为Top500网站的路上,不要因为架构阻碍了网站的发展。

参考资料:http://www.danga.com/words/2005_oscon/oscon-2005.pdf


© 2007 ~~派牛博客~~ | iKon Wordpress Theme by TextNData | Powered by Wordpress | rakCha web directory