Archive for 三月, 2011

前两天对lighttpd+fastcgi(php)进行了压力测试,在我的破虚拟机上,对一个简单的php页面访问QPS是60+,而纯静态页面QPS是700+。

所以坚定了对部分关键页面静态化的决心。但是希望尽量不破坏网站原有逻辑,所以使用了bash来做。具体流程图如下:

静态化流程图

静态化流程图

触发静态化

我们的内容是由运营人员在后台发布的,所以当新增、修改、删除(相当于修改了产品的状态为deleted)的时候需要触发静态化。我的做法是插入一条新纪录到static_help表,该表的id是自增的。

cron判断是否需要静态化

该脚本定时运行,首先会检查本地文件static_flag.txt,其中保存了上次运行的static_help.id。如果static_help.id不存在或者为空,则需要重新静态化。然后curl’获取线上的动态内容首页,获取其中的js变量index(动态获取的max(static_help.id)),如果static_help.id > page.index,说明有新变动,则需要更新。

cron单例

为了避免多个cron同时运行,造成冲突,所以使用了以下简单的脚本,保证同一时刻仅有一个进程运行:

function LockFile() {
        [ -e /dev/shm/${0##*/} ] && errorexit "Self already Run!"
        ln -s /proc/$$ /dev/shm/${0##*/}
        trap "Exit" 0 1 2 3 15 22 24
}
function Exit(){
        unlink /dev/shm/${0##*/} >/dev/null 2>&1
        exit 0;
}

在程序中,首先调用LockFile函数,检查临时目录中是否存在以当前程序名称命名的link,如果存在则退出;否则建立该link。同时,为了保证程序中异常中断的时候也可以调用Exit函数释放link,使用trap函数注册了single的handle。在程序结束的时候,调用Exit函数。

cron获取待静态化内容

这里,为了尽量少的破坏现有代码的结构,在lighttpd中做了如下配置:

url.rewrite                = (
                "^/try/(?:\?(?:s=(\w+)&?)?(?:page=(\d+))?)?$" => "/static/try_$1_$2.htm", # pure static
)

这里我希望把http://127.0.0.1/try/?s=time&page=1重定向到/path/to/dir/static/try_time_1.htm,而htm文件是不经过fastcgi的。

通过以上配置可以看出,如果url不匹配该正则,就不会发生这样的重定向。所以为了获取动态内容,可以使用http://127.0.0.1/try/?s=time&page=1&v=dynamic类似的链接。

但是,这样的配置还有一个问题是,如果静态化失败,/path/to/dir/static/try_time_1.htm类似的文件不存在,则返回404error。待解决。

ajax加载动态内容

页面上肯定会有动态内容,比如访问数、用户相关信息等,这些可以使用ajax的方式动态加载。

这样就完成了整个静态化的步骤,附上完整的bash脚本:http://staticize-webpage.googlecode.com/files/static_listpage.tar.gz。

升级到4.2.1重新破解后,装的一些软件没了,比如sshd软件openssh。

cydia重新安装后,在ipad未锁定的情况下,用winscp或者secureCRT之类的软件登录,用户名是root,默认密码是alpine。

zz from:http://hi.baidu.com/baijunhui/blog/item/2622e14555ac4d22cffca395.html

架构原理

Apache通常是开源界的首选Web服务器,因为它的强大和可靠,已经具有了品牌效应,可以适用于绝大部分的应用场合。但是它的强大有时候却显得笨重,配置文件得让人望而生畏,高并发情况下效率不太高。而轻量级的Web服务器Lighttpd却是后起之秀,其静态文件的响应能力远高于Apache,据说是Apache的2-3倍。Lighttpd的高性能和易用性,足以打动我们,在它能够胜任的领域,尽量用它。Lighttpd对PHP的支持也很好,还可以通过Fastcgi方式支持其他的语言,比如Python。

毕竟Lighttpd是轻量级的服务器,功能上不能跟Apache比,某些应用无法胜任。比如Lighttpd还不支持缓存,而现在的绝大部分站点都是用程序生成动态内容,没有缓存的话即使程序的效率再高也很难满足大访问量的需求,而且让程序不停的去做同一件事情也实在没有意义。首先,Web程序是需要做缓存处理的,即把反复使用的数据做缓存。即使这样也还不够,单单是启动Web处理程序的代价就不少,缓存最后生成的静态页面是必不可少的。而做这个是 Squid的强项,它本是做代理的,支持高效的缓存,可以用来给站点做反向代理加速。把Squid放在Apache或者Lighttpd的前端来缓存 Web服务器生成的动态内容,而Web应用程序只需要适当地设置页面实效时间即可。

即使是大部分内容动态生成的网站,仍免不了会有一些静态元素,比如图片、JS脚本、CSS等等,将Squid放在Apache或者Lighttp前端后,反而会使性能下降,毕竟处理HTTP请求是Web服务器的强项。而且已经存在于文件系统中的静态内容再在Squid中缓存一下,浪费内存和硬盘空间。因此可以考虑将Lighttpd再放在Squid的前面,构成 Lighttpd+Squid+Apache的一条处理链,Lighttpd在最前面,专门用来处理静态内容的请求,把动态内容请求通过proxy模块转发给Squid,如果Squid中有该请求的内容且没有过期,则直接返回给Lighttpd。新请求或者过期的页面请求交由Apache中Web程序来处理。经过Lighttpd和Squid的两级过滤,Apache需要处理的请求将大大减少,减少了Web应用程序的压力。同时这样的构架,便于把不同的处理分散到多台计算机上进行,由Lighttpd在前面统一把关。

在这种架构下,每一级都是可以进行单独优化的,比如Lighttpd可以采用异步IO方式,Squid可以启用内存来缓存,Apache可以启用MPM 等,并且每一级都可以使用多台机器来均衡负载,伸缩性很好。

实例讲解

下面以daviesliu.net和rainbud.net域下面的几个站点为例来介绍一下此方案的具体做法。daviesliu.net域下有几个用 mod_python实现的blog站点,几个php的站点,一个mod_python的小程序,以后可能还会架设几个PHP和Django的站点。而服务器非常弱,CPU为Celeron 500,内存为PC 100 384M,因此比较关注Web服务器的效率。这几个站点都是采用虚拟主机方式,开在同一台机器的同一个端口上。

Lighttpd服务于80端口,Squid运行在3128端口,Apache运行在81端口。

Lighttpd的配置

多个域名采用/var/www/domain/subdomain 的目录结构,用evhost模块配置document-root如下:

evhost.path-pattern        = var.basedir + “/%0/%3/”

FtpSearch中有Perl脚本,需要启用CGI支持,它是用来做ftp站内搜索的,缓存的意义不大,直接由lighttpd的mod_cgi处理:

$HTTP[“url”] =~ “^/cgi-bin/” { # only allow cgi’s in this directory

dir-listing.activate = “disable”    # disable directory listings

cgi.assign = ( “.pl”   => “/usr/bin/perl”, “.cgi” => “/usr/bin/perl” )

}

bbs使用的是phpBB,访问量不大,可以放在lighttpd(fastcgi)或者apache(mod_php)下,暂时使用 lighttpd,设置所有.php的页面请求有fastcgi处理:

fastcgi.server = ( “.php” => ( ( “host” => “127.0.0.1”, “port”=> 1026, “bin-path” => “/usr/bin/php-cgi” ) ) )

blog.daviesliu.net 和 blog.rainbud.net 是用mod_python编写的blogxp程序,所有静态内容都有扩展名,而动态内容没有扩展名。blogxp是用python程序生成XML格式的数据再交由mod_xslt转换成HTML页面,只能放在Apache下运行。该站点采用典型Lighttpd+Squid+Apache方式处理:

$HTTP[“host”] =~ “^blog” {

$HTTP[“url”] !~ “\.” {

proxy.server = ( “” => ( “localhost” => ( “host”=> “127.0.0.1”, “port”=> 3128 ) ) ) #3128端口为

}

}

share中有静态页面,也有用mod_python处理的请求,在/cgi/下:

$HTTP[“host”] =~ “^share” {

proxy.server = (

“/cgi” => ( “localhost” => ( “host”=> “127.0.0.1”, “port”=> 3128 ) )

)

}

Squid的配置

只允许本地访问:

http_port   3128

http_access allow localhost

http_access deny all

启用反向代理:

httpd_accel_host 127.0.0.1

httpd_accel_port 81                   #apache的端口

httpd_accel_single_host on

httpd_accel_with_proxy on          #启用缓存

httpd_accel_uses_host_header on #启用虚拟主机支持

此方向代理支持该主机上的所有域名。

Apache的配置

配置/etc/conf.d/apache2,让其加载mod_python、mod_xslt、mod_php模块:

APACHE2_OPTS=”-D PYTHON -D XSLT -D PHP5″

所有网站的根目录:

<Directory “/var/www”>

AllowOverride All     #允许.htaccess覆盖

Order allow,deny

Allow from all

</Directory>

基于域名的虚拟主机:

<VirtualHost *:81>

ServerName blog.daviesliu.net

DocumentRoot /var/www/daviesliu.net/blog

</VirtualHost>

这里明显没有lighttpd的evhost配置方便。

blog.daviesliu.net下的.htaccess设置(便于开发,不用重启Apache):

SetHandler mod_python

PythonHandler blogxp.publisher

PythonDebug On

PythonAutoReload On

<FilesMatch “\.”>

SetHandler None        #静态文件直接由Apache处理

</FilesMatch>

<IfModule mod_xslt.c>

AddType text/xsl .xsl #防止对xsl文件进行转化

AddOutputFilterByType mod_xslt text/xml

XSLTCache off

XSLTProcess on

</IfModule>

Header set Pragma “cache”

Header set Cache-Control “cache”

在blogxp.publisher里面,还需要设置返回的文档类型和过期时间:

req.content_type = “text/xml”

req.headers_out[‘Expires’] = formatdate( time.time() + 60 * 5 )

经过这样的配置,所有站点都可以通过80、3128、81三个端口进行正常访问,80端口用作对外的访问,以减少负荷。81端口可以用作开发时的调试,没有缓存的困扰。

性能测试

由于时间和精力有限,下面只用ab2做一个并不规范的性能对比测试(每项都测多次取平均),评价指标为每秒钟的请求数。

测试命令,以测试lighttpd上并发10个请求 scripts/prototype.js 为例:

ab2 -n 1000 -c 10 http://blog.daviesliu.net:80/scripts/prototype.js

静态内容:prototype.js (27kB)

Con Lighttpd(:80) Squid(:3128) Apache(:81)
1 380 210 240
10 410 215 240
100 380 160 230

可见在静态内容上,Lighttpd表现强劲,而Squid在没有配内存缓存的情况下比另两个Web服务器的性能要差些。

动态页面:/rss (31kB)

Con Lighttpd(:80) Squid(:3128) Apache(:81)
1 103 210 6.17
10 110 200 6.04
100 100 100 6.24

在动态内容上,Squid的作用非常明显,而Lighttpd受限于Squid的效率,并且还要低一大截。如果是有多台Squid来做均衡的话,Lighttpd的功效才能发挥出来。

在单机且静态内容很少的情况下,可以不用Lighttpd而将Squid置于最前面。

http://blog.daviesliu.net/2006/09/09/010620/

环境:centos,linux 2.6.18核。 lighttpd 1.4.28。php 5.2.17。

工具: http_load

lighttpd加载的module:

“mod_expire”,
“mod_rewrite”,
“mod_redirect”,
“mod_alias”,
“mod_access”,
“mod_status”,
“mod_fastcgi”,
“mod_compress”,
“mod_accesslog”

测试.htm后缀的文件,不经过fastcgi,运行多次,平均QPS为575。.php后缀的文件(仅echo短字符串),平均QPS为100+。

fastcgi配置为:

fastcgi.server             = (
                ".php" =>
                ( "localhost" =>
                  (
                   "socket" => "/usr/local/lighttpd/php-pid/php-fastcgi.socket",
                   "bin-path" => "/usr/local/php-cgi/bin/php-cgi -c /etc/php.ini",
                   "max-procs" => 10,
                   "bin-environment" => (
                           "PHP_FCGI_CHILDREN" => "10",
                           "PHP_FCGI_MAX_REQUESTS" => "5000"
                           ),
                   "bin-copy-environment" => ( "USER" ),
                   "broken-scriptfilename" => "enable"
                  )
                ),
                ".html" =>
                ( "localhost" =>
                  (
                   "socket" => "/usr/local/lighttpd/php-pid/php-fastcgi.socket-0"
                  )
                )
        )

这时,每个php-cgi进程占用的vss内存为5m左右(其中包含了共享lib的内存)。一共启动的php-cgi个数为:(max-procs+1)× PHP_FCGI_CHILDREN。其中max-procs个父进程并不真正处理http请求。

遇到一个奇怪的问题,尝试将PHP_FCGI_CHILDREN增大到100,即启动550个php进程。再重启lighttpd的时候,虚拟机直接挂死(kill)。

猜测可能是中止lighttpd的时候,其会进行一系列的后缀处理,而进程太多,消耗内存和fd过多而至的(不确定)。

这时,即使再加大http_load的压力,也无法取得更好的QPS了。查看http://127.0.0.1/server-counters又发现一个奇怪的现象,即fastcgi.backend.localhost.9.connected占据了90%+的连接数。是由于长连接的问题吗?但是将server.max-keep-alive-requests设置为0,还是这种情况。

http://redmine.lighttpd.net/boards/2/topics/2027看到如下解释:

In 1.4.x lighty tends to stick to one backend, which is not really a bad thing, as this backend probably has a better cache than the other backends. It will move ofc to another one if one backend isn´t avail or loaded.

集中在相同的php backend,是为了最大限度的利用缓存,而当负载过重或不可用时,它会自动切换到其他php backend。ok,我接受这种解释。

最后,我调整了如下的参数:

server.max-keep-alive-requests=16 # maximum number of request within a keep-alive session

server.max-keep-alive-idle = 5 # 无动作保持连接的超时时长

server.max-read-idle = 60 # 读取被阻塞的超时时长

server.max-write-idle = 360 # 写数据被阻塞的超时时长(大文件的读写会被trunk,针对每个trunk计算时长)

server.max-fds = 4096 # 最多可打开的文件描述符个数(包括socket、本地文件等)

server.max-connections = 2048 # 最多连接数(lighttpd本身进程的限制)

server.stat-cache-engine = “fam” # stat的缓存方式,需要在编译lighttpd时候指定–enable-fam

由于我认为线上服务器的fd是宝贵的,希望每个fd能够尽可能多的服务于不同的users,而不是为了一个users keep alive等待。

所以我减少了keep alive的可能性。

而由于线上的errorlog中经常出现“sockets disabled, connection limit reached ”,说明socket不够用,

间接说明文件描述符不够用,所以我调大了fd的上限。因为可用连接数=fd上限/2。

lighttpd需要同user间通过socket建立连接,也需要同php-cgi间通过原始套接口建立连接,其实还需要一些其他连接,比如log等。

所以得出上述公式。

此外,系统本身也有限制,查看Linux的最大文件描述符:
# cat /etc/redflag-release
Red Flag DC Server release 5.0 (Trinity SP2)


# cat /proc/sys/fs/file-nr
580     0       131072
三个值的意思分别是:
580:总共打开的文件描述符的数量(从系统开机开始算, 所有打开的文件描述符的数量)
0:总共的空闲的文件描述符的数量
131072:最大能打开的文件描述符的数量


修改:
# echo “132096″ > /proc/sys/fs/file-max
或加入/etc/sysctl.conf文件中。

我猜测的lighttpd处理流程:

1、用户输入url,尝试连接lighttpd web server

2、如果lighttpd已经达到了最大连接数max-connections,则用户无法连接,一直在等待(可以将max-connections配置为很小的数值看看)

3、lighttpd检查该url是否正确,是否需要被php-cgi处理

4、如果需要且有空闲的php-cgi,将处理权交给php-cgi

5、如果没有空闲的php-cgi,则压入队列,等待

所以,王道还是配置合理的php-cgi数目,并且减少php的处理时间!!

ps:查看lighttpd连接情况 sudo netstat -punt | grep lighttpd

为了监测每个响应的时长,可以使用如下配置:其中%T是time used in seconds。更精准的%D目前不支持。

accesslog.format = “%h^F%V^F%u^F%t^F%T^F\”%r\”^F%>s^F%b^F\”%{Referer}i\”^F\”%{User-Agent}i\””

————————————————————

2011-3-23

仍然在虚拟机针对本机压力测试(没机器,就是可怜)。

针对某页面A(7.7k),直接访问数据库,无缓存。http_load -parallel 100 -fetches 1000 local.txt多次运行结果为54QPS。运行期间,load average较重,cpu100%,其中wa占到80%左右。

对memcached进行基准测试:针对另一页面B,仅从memcache中获取一次数据,不输出。当数据是MEMCACHE_COMPRESSED 存入的时候,http_load -parallel 100 -fetches 1000就会导致大批量的memcache->get失败:Failed reading line from stream。改为不压缩存入,则结果为100QPS(偶尔还是会有连接失败的情况)。

仍然针对页面A,部分数据修改为访问memcache,部分访问数据库。仍然不行,当memcached无法连接的时候,压力又转嫁到mysql上,http_load总是报无法连接的错误。这种情况,应该不是mysql、memcached或者php-memcache的问题,而是我本机是笔记本的虚拟机,性能太差。

最后,做页面的静态化,将页面A保存为.htm后缀,不经过php-cgi。结果为747QPS,且系统负载很轻。所以坚定了要对部分页面做完全静态化的信念。

可以通过lighttpd的rewrite来重定向动态url到静态,如 “^/try/$” => “/index.htm”,

information-retrieval algorithms, massive scalability and storage solutions, and large-scale applications that enrich the user experience,networking systems, advertising systems and complex transaction systems

信息提取、大规模运算和存储,网络、广告系统、交易系统

google仍是我心目中的圣殿。

linux、C、php。 设计模式。apache/lighttpd/ngnix。Mysql。Memcached。

不能只是使用了,需要了解它内部的原理。

好久没写过字了,甜菜又洋洋洒洒了1k文,压力巨大。

其实看完312,同之前的3场有个同样的感觉,就是“一片空白”!那就从视频中找寻失去的记忆吧。
sina微博里,搜索与“周笔畅上海演唱会”相关的视频,这两天就是靠它来活的了(我什么时候开始依赖sina微博了?!)

如果没有你+夜上海+给我一个吻

http://www.tudou.com/programs/view/dfGliSYWZl0/

原谅我,实在大爱给我一个吻。开始时的欲语还休,突然间破空而出的“给我,一个吻”,略带停顿后的“可以不可以”,还露着小牙,得意地看着台下,听我们嗷嗷叫唤着“可以!!!”,然后耸耸肩,似乎还嫌刺激不够似的,随着“吻在我的脸上”,抚面俏皮地前倾靠近我们!再下一刻,你,作为一个完美的歌者,抛弃下我们,沉浸在你的歌里,忘情的演绎,只剩下满场的狼亲们吐血的嚎叫。

但是,周笔畅,借我一百个胆子,我也不敢给你一个吻,虽然彼时彼刻,我也响亮的喊着“可以”。你是天使,是最纯洁的小孩,我心甘情愿的远远看着你,看你坚持自己的梦想,看你快乐的笑、偶尔小小的烦心,看你在微博里调皮胡闹。就像你唱的,我做你的翅膀上一小片羽毛就好,为你的快乐填上一小份力,就足够。

一周年+你们的爱+单面镜

http://v.youku.com/v_show/id_XMjUwNzE5OTAw.html

3首抒情歌。一周年和单面镜,两首苦情歌,都是我喜欢的风格。记得广州那场,第一次听单面镜(我是坏笔亲,我out,我自pia),音乐响起,阿笔的歌声似水流淌,再待到听清楚了歌词,眼泪就哗哗的流了。悲伤的歌,配上阿笔那浸淫其中的忧伤表情,心疼。

你们的爱,刚开始的时候,并不是很喜欢,就像某中立说的,歌词略显直白。但是每次现场,听阿笔那么认真的唱,一句句歌词,就像这个词穷的人在诉说她的感激。那么直白又怎样?舞台是你的,场子我们给你撑,每个有你的时候,都是最美好的!

氧气

http://v.youku.com/v_show/id_XMjUxMzU4NDA4.html

承载记忆的歌,还是05、06你唱过的吧?只是,再一次心疼,你锁住的眉头,你轻轻吟唱的声音,你微微低下的头,你回拢双手抱紧的身体,你虚空着伸向前方的手指。多么想为你做点什么,让你时刻都感到温暖啊!周笔,我纠结!喜欢听你唱悲伤的歌,但是不喜欢看你悲伤的表情!!

她来听我的演唱会

http://v.youku.com/v_show/id_XMjUwODk3NDQw.html

灯光暗下来。宝贝,我来听你的演唱会了,阿笔,我兑现了6年前的诺言。

第一场,广州,看着你破茧成蝶。

第二场,北京,和朋友一起听你,我圆了自己的梦。

第三场,杭州,犹豫再三,终于成行,看你疯癫,为你痴狂。

这一场,上海,只有满满的幸福。

17岁的时候,我没遇见你,是我的遗憾。05年,我21,你20,我还有大把的时间用来弥补这遗憾。那句很俗的话,下辈子你是周笔畅,我还是你的亲。

记忆中,我们一直是嚎叫、呐喊,而这次,我们安静的听你唱完这歌,放下手中的荧光棒,痴痴的为你鼓掌。你不是个艺人,你的性格压根不适合这演艺圈。但你天生就是唱歌的,这掌声,单纯的只为音乐。

告白+就是爱你

http://v.youku.com/v_show/id_XMjUwNDM1OTc2.html

不会说话的人,只是平平淡淡念出来的句子,怎么就一下子打入人心里了呢?

现在,听着你的声音,六年的时光一点一点流淌。

05年,很遗憾的,没有为你投过票。

06年,幸运的,看到了你的超女北京巡演,第一次为你的现场折服。

06、07年,追踪你的脚步,去北大、去人大、去sina、去欢乐谷,有辛酸,但更多的是幸福。

08、09年,我工作了,对不起,给你的时间少了,不再追视频、图片、文章,再也没有写过关于你的文字。

10、11年,你开演唱会了,我来看了。听你的信,听你说出的感激,除了愧疚和感动,再没有别的。对不起,对不起,我不称职,我配不上笔亲这个温暖的称号。从今而后,我不能保证别的,但是,你的每一张CD、每一本写真我都收藏,你的每一首歌我都会学着去唱,你拍的每部电影我一定去电影院看,你的每场演唱会,请给我荣幸,保佑我买到前排的座位。

六年,全化入这首属于我们的歌,我们才懂得歌,周笔畅,就是爱你。


然后,碎碎念下我的福利。

万分感激,我是你的粉,帮我抢到票的gaia大腿!上海,第一排,那距离近的,连小丫头片子忘情处微皱的眉头都看的清楚!!要知道,我可
是800度近视,N年未换眼镜了啊!!围栏和舞台间不到一米,我和阿笔的距离。。。。OMG!!!

某首歌,某笔看着我唱了几句。但是,瞬间空白的我,忘记了那是那首歌,忘记了那时的她穿着怎样的衣服、有怎样的表情,是深情还是调皮
的眼神呢?然后不争气的我,在跟甜菜求证了之后,居然坐着坐着就摔到了地上 ……,…… 幸好没被某笔看到吧。。。

最后,完场后,居然遇到了笔笔的车,我跑出来20多年来的最快速度,然后,当我的前前后后左左右右都没人了之后,阿笔和她的车来了。阿
笔,隔着茶色的玻璃,冲我挥了挥、又挥了挥手。


ok,最后的最后,我要感谢甜菜童鞋,和我一起走完这4场,如果只有我一个,或许没这魄力。

最后的最后的最后,又听了一遍阿笔的她来听我的演唱会。其实,我真的是一个感情粗糙的人,比如现在,有点想哭,却找不出哭的理由。我奔三的人了,别人问我,为什么喜欢周笔畅?每每给不出一个像样的理由。这感情不同于爱情、友情,我不求认识或者接近她,却早已觉得她熟悉的像身边人。或者,何必去纠结理由,作个笔亲,便是莫大的幸福了。

在godaddy上买了域名,但是DNS服务器是放在linode的(同时也租用了linode的虚拟机)。

配置一级域名,首先需要在godaddy上讲nameserver指向DNS server(即linode)。二级域名的配置就不需要这一步了,它会默认使用一级域名的DNS server。

如果这时还没配置一级域名,那么需要在DNS server(即linode)新建该域名(不带www的!!)。然后,点击进入该一级域名,为其添加A record,填写二级域名(如 test.flykobe.com)和服务器的ip地址。稍等一会就会生效。

如果生效前,访问者(本机)的浏览器访问过未生效的网址,可能需要清理浏览器到dns缓存。最好cmd ipconfig /flushdns清理下本机的缓存。

出差归来,不太顺利,总结下自己的几点疑问。

这次出差,并不单纯仅是技术,还需要同对方沟通产品流程,并且“交流感情”,也就是吃吃喝喝。我不知道这些事情对于别人是怎样的意义,但是用我朋友打趣我的话而言,就是“同我的人生观、价值观产生了极大的矛盾”。事实上,没这么严重,又没做什么违法乱纪的事情。只是,要请几乎陌生的人吃饭、聊天,还是蛮挑战的,至少,不能冷场、要想话题吧?!

自我感觉,其实做的还不错,同对方的基层干部们都交往甚欢。暗自庆幸的是,还真是遇到几个蛮对脾气的人,所以有些时候,并没觉得是公务上的交往,反而仅仅是像朋友一样交谈、逛街。

但是,这样的工作是我想要的吗?答案毋庸置疑。我只是想单纯的做技术,这样的成长或许是有好处的,可以锻炼我与人沟通的能力,但是如果次数多了,我肯定是极其反感的。

另一方面,结果不大好的原因,我们回来也总结了。但是,我觉得最核心的一点却被忽略了,我们真的是在过河拆桥。这个应该也是这两天我老打不起精神的原因吧。

我们同对方的合作,本来是从部门A开始的,而我这次去,受命的却是与部门B一起coding合作,压根没听说有部门A的事情。但是兜兜转转,我们还是需要部门A的资源。当我我见了部门A的人,才发现人家一直都在等我们的消息。部门A的愤怒理所当然。而我的错误,我觉得,并不是像同事说的,“没做过大项目,没能把话说得婉转”!我的错误,我们的错误,根本上是,不应该在部门B提出单独合作的时候单方面同意,而没有知会部门A!!

我不知道商务上的事情,是否都是这样,但是我觉得有些失望。即使一辈子发不了财,即使一辈子讲话都结结巴巴,我也不想学会这种圆滑。

1、直接从线上服务器复制了项目代码 ,根目录下包括:cake,app目录

2、复制线上数据库,部署到本地

3、若不存在,则在app下建立tmp/cache目录,并更改权限为0777

4、访问,出现fatal error:Class ‘Dispatcher’ not found;经查,清空tmp/cache下的所有目录、文件

5、访问,出现错误提示,数据库配置有误,是用户名密码与线上不一致导致的

这时就配置完成了。

web开发中,form表单的提交是经常使用到的,原来做php工程师时仅关注于后端检验,就比较简单。

而这次,需要用前端的方式对form进行检查,由于我们使用了mootools框架,所以自然而言就想到利用其提供的组件进行检查,避免二次开发。

http://mootools.net/forge/上搜索form关键词,可以看到不少组件,这里我仅使用了简单的form.validator组件。在http://mootools.net/more/上选择以下4个包,下载(当然,如果您使用的是mootools的全代码版本,就可以略过此步了)。

首先当然是学习其docdemo

.validation-failed {
border-color: #ff0000;
background-color: #ffdddd;
}

.validation-advice {
padding-bottom: 5px;
font-weight: bold;
color: #ff0000;
}

这里两个css样式是必须的,否则可能导致错误提示无法显示(应该是显示了,但是用户看不到)。

js中核心的就是这两句:

// The elements used.
var myForm = document.id('myForm');
// Validation.
var validator = new Form.Validator.Inline(myForm, {
'useTitles': true  // 是否使用element的title进行错误提示
});

html中,input text和textarea比较简单,就是在element的class中添加上required就可以了,也可检查长度等,例如:

<input type=”text” class=”required”  data-validators=”minLength:10″  name=”test” />

长度检查有多种方式,可以选择习惯的方式使用。

而radio和checkbox稍微需要注意点,通过查看其源码的validate-one-required属性,针对radio和checkbox,它将位于同一parent下的input归为一组!所以,千万保证这一点!

如:

<li>

<label>Would you like to &lt;something&gt;?</label>

<input type="radio" id="news_y" name="newsletter" />

<label for="news_y">Yes</label>

<input type="radio" id="news_n" name="newsletter" class="validate-one-required" />

<label for="news_n">No</label>

</li>

在上面这种情况下,如果未选择radio,错误提示默认显示在news_n的parent的最后。要改变其位置,可以使用msgPos属性。
<li>

<label>Would you like to &lt;something&gt;?</label>

<input type="radio" id="news_y" name="newsletter" />

<label for="news_y">Yes</label>

<input type="radio" id="news_n" name="newsletter" class="validate-one-required msgPos:'notify'" />

<label for="news_n">No</label>

</li>

<div id="notify"></div>

那么,提示将出现在notify div内。

另外,有些情况下,我们的radio或者checkbox中含有其他选项,用户勾选之后,需要再填写些文字,那么就可以定义自己的check属性:

// Validation.

var validator = new Form.Validator.Inline(myForm, {

'useTitles': true

});

validator.add('mustIfSelect', {

errorMsg: '请填写理由',

test: function(field){

var s = field.getPrevious('input');

if (!s){

return true;

}

if (s.get('checked')){

return !Form.Validator.getValidator('IsEmpty').test(field);

}

return true;

}

});

<input type="radio" name="{$name}" value="other" />其他

<input class="cy-other mustIfSelect" type="text" name="{$name}_other_t" value="" title="请填写您选择该项的理由"/>

这样就定义了mustIfSelect属性并关联到了其他上。