<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>N.S.thoughts &#187; Technotes</title>
	<atom:link href="http://nightsailer.com/category/coding/technotes/feed" rel="self" type="application/rss+xml" />
	<link>http://nightsailer.com</link>
	<description>...silent is golden...</description>
	<lastBuildDate>Wed, 01 Sep 2010 17:01:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>不同数据中心同步处理</title>
		<link>http://nightsailer.com/2010/07/14/755.html</link>
		<comments>http://nightsailer.com/2010/07/14/755.html#comments</comments>
		<pubDate>Tue, 13 Jul 2010 16:58:06 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[同步]]></category>
		<category><![CDATA[多数据中心]]></category>
		<category><![CDATA[延迟]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=755</guid>
		<description><![CDATA[很久之前看过facebook关于不同数据中心之间的延迟处理。
目前我们也遇到类似的问题。这次我们使用的是mongodb。
由于国内恶劣的环境和昂贵的价格，我们被迫将一些大量消耗带宽的服务迁移到国外的主机。这导致了大量的网络延迟。
大概200-400ms。 这样，仅仅依靠mongodb的同步是无法解决数据的一致性了。
由于数据同步量很大，又通过VPN，主数据中心和国外同步的时间周期要以分钟甚至小时计算了。
没办法，只能土法了。
当前解决方案是：
1. 数据一律从国内dc进行更新，此时设置更新数据状态为未同步
2. 数据更新后，发送一个消息到国外dc的队列，对应的worker则开始监控此数据的同步情况
3. 数据未同步前，所有的数据均从国内的主数据进行分发处理
4. 同步完毕，国外dc通知国内dc，将数据状态更改为已同步
5. 一旦同步，后续的数据处理工作自动转发到国外，从而实现分流
缺点：
监控worker和队列的工作状态需要监控。否则会导致流量无法分发。
虽然是土法，但也能解决眼前的问题。
]]></description>
			<content:encoded><![CDATA[<p>很久之前看过facebook关于不同数据中心之间的延迟处理。</p>
<p>目前我们也遇到类似的问题。这次我们使用的是mongodb。<br />
由于国内恶劣的环境和昂贵的价格，我们被迫将一些大量消耗带宽的服务迁移到国外的主机。这导致了大量的网络延迟。<br />
大概200-400ms。 这样，仅仅依靠mongodb的同步是无法解决数据的一致性了。</p>
<p>由于数据同步量很大，又通过VPN，主数据中心和国外同步的时间周期要以分钟甚至小时计算了。</p>
<p>没办法，只能土法了。</p>
<p>当前解决方案是：</p>
<p>1. 数据一律从国内dc进行更新，此时设置更新数据状态为未同步<br />
2. 数据更新后，发送一个消息到国外dc的队列，对应的worker则开始监控此数据的同步情况<br />
3. 数据未同步前，所有的数据均从国内的主数据进行分发处理<br />
4. 同步完毕，国外dc通知国内dc，将数据状态更改为已同步<br />
5. 一旦同步，后续的数据处理工作自动转发到国外，从而实现分流</p>
<p>缺点：</p>
<p>监控worker和队列的工作状态需要监控。否则会导致流量无法分发。</p>
<p>虽然是土法，但也能解决眼前的问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/07/14/755.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Non-blocking/Evented/IO 将会改变我们传统的编程模式</title>
		<link>http://nightsailer.com/2010/05/17/739.html</link>
		<comments>http://nightsailer.com/2010/05/17/739.html#comments</comments>
		<pubDate>Sun, 16 May 2010 16:06:56 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=739</guid>
		<description><![CDATA[最近Node.js 很火， 我对此很有兴趣，我自己也在使用Perl的AnyEvent。
Event/IO的一个要点是non-blocking。 Nginx能够解决c10k的问题，一个关键是使用
Event Loop取代传统的thread/pre-fork。要想充分发挥nginx的优势，需要后端和对应
模块都能够non-blocking才行。
然而，现实多数的架构都是blocking的，比如PHP/FastCGI, 即便nginx的前端再好，后端的应用
依然是瓶颈。
所以，如何使用Event/IO实现non-blocking编程，是我们要关注的一个领域。
Ruby的EventMachine, Python的Twisted, Perl的AnyEvent都是不错的开始。
Node.js则是另一个选择。 Javascript似乎是天生的适合作Event/IO的编程语言。 上手轻松，简单。
对于我们来说，最困难的是开始，如何适应新的基于callback的处理模式，这是最大的挑战。
在未来一段时间内，我将把注意力集中到node.js和AnyEvent. 对于我目前正在规划的视觉中国C10平台中，这将是一个非常有趣解决方案。
推荐关于node.js的slide：
http://nodejs.org/cinco_de_node.pdf
Why You Should Pay Attention to Node.Js
]]></description>
			<content:encoded><![CDATA[<p>最近Node.js 很火， 我对此很有兴趣，我自己也在使用Perl的AnyEvent。<br />
Event/IO的一个要点是non-blocking。 Nginx能够解决c10k的问题，一个关键是使用<br />
Event Loop取代传统的thread/pre-fork。要想充分发挥nginx的优势，需要后端和对应<br />
模块都能够non-blocking才行。</p>
<p>然而，现实多数的架构都是blocking的，比如PHP/FastCGI, 即便nginx的前端再好，后端的应用<br />
依然是瓶颈。</p>
<p>所以，如何使用Event/IO实现non-blocking编程，是我们要关注的一个领域。</p>
<p>Ruby的EventMachine, Python的Twisted, Perl的AnyEvent都是不错的开始。</p>
<p>Node.js则是另一个选择。 Javascript似乎是天生的适合作Event/IO的编程语言。 上手轻松，简单。</p>
<p>对于我们来说，最困难的是开始，如何适应新的基于callback的处理模式，这是最大的挑战。</p>
<p>在未来一段时间内，我将把注意力集中到node.js和AnyEvent. 对于我目前正在规划的视觉中国C10平台中，这将是一个非常有趣解决方案。</p>
<p>推荐关于node.js的slide：</p>
<p><a href="http://nodejs.org/cinco_de_node.pdf">http://nodejs.org/cinco_de_node.pdf</a></p>
<p><a href="http://redmonk.com/sogrady/2010/05/13/node-js/">Why You Should Pay Attention to Node.Js</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/05/17/739.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ip_conntrack: table full, dropping packet.</title>
		<link>http://nightsailer.com/2010/04/23/723.html</link>
		<comments>http://nightsailer.com/2010/04/23/723.html#comments</comments>
		<pubDate>Fri, 23 Apr 2010 05:20:26 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[iptable]]></category>
		<category><![CDATA[ip_conntrack]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=723</guid>
		<description><![CDATA[ 流量比较大的服务器上经常出现 “ip_conntrack: table full, dropping packet.” 这类的信息。
由于CentOS/Redhat默认的ip conntrack参数值比较低，要做一些调整：
在/etc/sysctl.conf
net.ipv4.ip_conntrack_max = 131072
在/etc/rc.local 加入：
echo 16384 > /sys/module/ip_conntrack/parameters/hashsize
然后
sysctl -p
echo 16384 > /sys/module/ip_conntrack/parameters/hashsize
这样就调高了ip conntrack table的大小和对应优化ip conttrack模块的hash 大小，对于网络应用链接多的场合适用。
要查看当前链接数:
cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count
]]></description>
			<content:encoded><![CDATA[<p> 流量比较大的服务器上经常出现 “ip_conntrack: table full, dropping packet.” 这类的信息。<br />
由于CentOS/Redhat默认的ip conntrack参数值比较低，要做一些调整：</p>
<p>在/etc/sysctl.conf<br />
net.ipv4.ip_conntrack_max = 131072<br />
在/etc/rc.local 加入：<br />
echo 16384 > /sys/module/ip_conntrack/parameters/hashsize</p>
<p>然后<br />
sysctl -p<br />
echo 16384 > /sys/module/ip_conntrack/parameters/hashsize</p>
<p>这样就调高了ip conntrack table的大小和对应优化ip conttrack模块的hash 大小，对于网络应用链接多的场合适用。</p>
<p>要查看当前链接数:</p>
<p>cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/04/23/723.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在CentOS/Redhat 5.4上使用openswan搭建数据中心之间的VPN</title>
		<link>http://nightsailer.com/2010/03/22/699.html</link>
		<comments>http://nightsailer.com/2010/03/22/699.html#comments</comments>
		<pubDate>Sun, 21 Mar 2010 16:03:16 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[ipsec]]></category>
		<category><![CDATA[openswan]]></category>
		<category><![CDATA[vpn]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=699</guid>
		<description><![CDATA[最近由于主数据中心的流量过大，为了分流和成本，在国外购买了几个独立主机。这样就需要在2个数据中心之间进行
数据的同步，包括mysql，mongodb，以及反向代理等。通过在使用IPSec创建VPN从而将2个子网连接在一起是
最合适的方案。
在最初曾经考虑过使用OpenVPN，但是由于我们的应用涉及到较大的数据传输，OpenVPN的性能相对于IPSec的方案还是差，
我们也无法通过为openvpn部署硬件加速。出于成本考虑，最后选择纯软的vpn。
首先尝试使用CentOS自带的IPSec进行配置，不过很快失败。RedHat的文档描述的很不清楚，此外，配置比较繁琐，
按照其说明配置也无法连通，实在没有耐心，于是改用openswan来部署。
在部署openswan之前，先要简单画出2个子网的拓扑图，只要分出“左”《－》“右” 即可：
A(192.168.8.x/211.x.x.x)    +&#8212;&#8212;&#8212;&#8212;+ B(192.168.9.x/174.xx.xx.xx)
按照上图，A为left 节点，B 为 right节电。192.168.8.x和 192.168.9.x分别为2个网络的网段。
在2个网段分别选择一个主机作为网关，这样分别设置这个2个网关就可以了。
实际为：
gate_a(192.168.8.70/211.x.x.x)  , gate_b(192.168.9.1/174.x.x.x)
这2个host都需要有2个网卡，分别是链接内网和公网,记住上面的内网和公网ip。
下面开始安装：(gate_a)
1. 安装openswan
gate_a.nightsailer.com> yum install ipsec-tools
gate_a.nightsailer.com> yum install openswan
注意：下面这步很关键，CentOS-5.4有个bug，安装openswan时自动创建cert db并不正确，所以首先需要
重新创建，否则下一步生成key的时候就会报错。
gate_a.nightsailer.com>certutil -N -d /etc/ipsec.d
2. 现在，为gate_a生成密钥:
gate_a.nightsailer.com>ipsec newhostkey &#8211;configdir /etc/ipsec.d/  &#8211;output /etc/ipsec.d/keys.secrets
3.显示输出gate_a 作为left的公钥:
gate_a.nightsailer.com>ipsec showhostkey &#8211;left
ipsec showhostkey nss directory showhostkey: /etc/ipsec.d
        # rsakey Axxxx
      [...]]]></description>
			<content:encoded><![CDATA[<p>最近由于主数据中心的流量过大，为了分流和成本，在国外购买了几个独立主机。这样就需要在2个数据中心之间进行<br />
数据的同步，包括mysql，mongodb，以及反向代理等。通过在使用IPSec创建VPN从而将2个子网连接在一起是<br />
最合适的方案。</p>
<p>在最初曾经考虑过使用OpenVPN，但是由于我们的应用涉及到较大的数据传输，OpenVPN的性能相对于IPSec的方案还是差，<br />
我们也无法通过为openvpn部署硬件加速。出于成本考虑，最后选择纯软的vpn。</p>
<p>首先尝试使用CentOS自带的IPSec进行配置，不过很快失败。RedHat的文档描述的很不清楚，此外，配置比较繁琐，<br />
按照其说明配置也无法连通，实在没有耐心，于是改用openswan来部署。</p>
<p>在部署openswan之前，先要简单画出2个子网的拓扑图，只要分出“左”《－》“右” 即可：</p>
<p>A(192.168.8.x/211.x.x.x)    +&#8212;&#8212;&#8212;&#8212;+ B(192.168.9.x/174.xx.xx.xx)</p>
<p>按照上图，A为left 节点，B 为 right节电。192.168.8.x和 192.168.9.x分别为2个网络的网段。<br />
在2个网段分别选择一个主机作为网关，这样分别设置这个2个网关就可以了。<br />
实际为：<br />
gate_a(192.168.8.70/211.x.x.x)  , gate_b(192.168.9.1/174.x.x.x)</p>
<p>这2个host都需要有2个网卡，分别是链接内网和公网,记住上面的内网和公网ip。</p>
<p>下面开始安装：(gate_a)</p>
<p>1. 安装openswan<br />
gate_a.nightsailer.com> yum install ipsec-tools<br />
gate_a.nightsailer.com> yum install openswan</p>
<p>注意：下面这步很关键，CentOS-5.4有个bug，安装openswan时自动创建cert db并不正确，所以首先需要<br />
重新创建，否则下一步生成key的时候就会报错。</p>
<p>gate_a.nightsailer.com>certutil -N -d /etc/ipsec.d</p>
<p>2. 现在，为gate_a生成密钥:<br />
gate_a.nightsailer.com>ipsec newhostkey &#8211;configdir /etc/ipsec.d/  &#8211;output /etc/ipsec.d/keys.secrets</p>
<p>3.显示输出gate_a 作为left的公钥:<br />
gate_a.nightsailer.com>ipsec showhostkey &#8211;left<br />
ipsec showhostkey nss directory showhostkey: /etc/ipsec.d<br />
        # rsakey Axxxx<br />
       leftrsasigkey=0sA&#8230;&#8230;&#8230;</p>
<p>将eftrsasigkey=0sA&#8230;.. 这行输出记下，后面备用</p>
<p>4. 修改/etc/ip_sec.conf</p>
<p># /etc/ipsec.conf &#8211; Openswan IPsec configuration file<br />
#<br />
# Manual:     ipsec.conf.5<br />
#<br />
# Please place your own config files in /etc/ipsec.d/ ending in .conf</p>
<p>version 2.0     # conforms to second version of ipsec.conf specification</p>
<p># basic configuration<br />
config setup<br />
        # Debug-logging controls:  &#8220;none&#8221; for (almost) none, &#8220;all&#8221; for lots.<br />
        # klipsdebug=none<br />
        # plutodebug=&#8221;control parsing&#8221;<br />
        # For Red Hat Enterprise Linux and Fedora, leave protostack=netkey<br />
        protostack=netkey<br />
        nat_traversal=yes<br />
        virtual_private=<br />
        oe=off<br />
        # Enable this if you see &#8220;failed to find any available worker&#8221;<br />
        nhelpers=0</p>
<p>#You may put your configuration (.conf) file in the &#8220;/etc/ipsec.d/&#8221; and uncomment this.<br />
include /etc/ipsec.d/*.conf</p>
<p>5. 现在为这个vpn单独创建一个conf文件，放到/etc/ipsec.d/nightsailer.com_vpn.conf</p>
<p>conn nightsailer_vpn<br />
        #左节点的公网ip(gate_a)<br />
        left=211.x.x.x<br />
        #左节点的内网网段<br />
        leftsubnet=192.168.8.0/24<br />
        #左节点的网关的内网ip（可选）<br />
        leftsourceip=192.168.8.70<br />
        #左节点的id，可以是ip，也可以是域名:<br />
        # leftid=@gate_a.chinavisual.com<br />
        # 建议最好用ip，域名需要反向解析，dns没配好很容易出问题<br />
        leftid=211.x.x.x<br />
        # 上一步显示的gate_a作为left的公钥<br />
        leftrsasigkey=0sAQO&#8230;<br />
        leftnexthop=%defaultroute<br />
        #以下参数含义和上面的一样<br />
        right=174.x.x.x<br />
        rightsubnet=192.168.9.0/24<br />
        rightsourceip=192.168.9.1<br />
        rightid=174.x.x.x<br />
        rightrsasigkey=0sAQOp&#8230;.<br />
        rightnexthop=%defaultroute<br />
        #是否在ipsec启动时自动启用这个链接<br />
        #auto = add ( 若这个选项，则需要手动up vpn链接)<br />
        auto=start</p>
<p>现在，登录到gate_b,重复上面的步骤1-5。</p>
<p>注意，第3步略有不同，因为gate_b是right节点，所以要显示它的right 密钥:<br />
gate_b.nightsailer.com>ipsec showhostkey &#8211;right<br />
ipsec showhostkey nss directory showhostkey: /etc/ipsec.d<br />
        # rsakey Axxxx<br />
       rightrsasigkey=0sA&#8230;&#8230;&#8230;</p>
<p>将rightrsasigkey=0sA&#8230;.. 这行输出更新/etc/ipsec.d/nightsailer.com_vpn.conf（包括gate_a上的）</p>
<p>现在分别启动ipsec<br />
gate_a.nightsailer.com>/etc/init.d/ipsec start<br />
gate_b.nightsailer.com>/etc/init.d/ipsec start</p>
<p>好了，现在在gate_a和gate_b上相互ping，就可以ping通了。</p>
<p>网关通了，那么还需要再各自子网添加一个路由:<br />
A网段添加：<br />
route add -net 192.168.9.0 netmask 255.255.255.0 gw 192.168.8.70 eth1<br />
#添加静态路由<br />
在 /etc/sysconfig/network-scripts/route-eth1 追加：<br />
192.168.9.0/24 via 192.168.8.70 dev eth1</p>
<p>B网段添加：<br />
route add -net 192.168.8.0 netmask 255.255.255.0 gw 192.168.9.1 eth1<br />
在 /etc/sysconfig/network-scripts/route-eth1 追加：<br />
192.168.8.0/24 via 192.168.9.1 dev eth1</p>
<p>一切就大功告成了。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/03/22/699.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>快速恢复mysql master－master同步</title>
		<link>http://nightsailer.com/2010/03/15/689.html</link>
		<comments>http://nightsailer.com/2010/03/15/689.html#comments</comments>
		<pubDate>Sun, 14 Mar 2010 19:25:15 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[mmm]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=689</guid>
		<description><![CDATA[系统出现错误导致2个Master之间出现不一致。需要立刻同步。
由于错误出现的时间超过了binlog的保留范围（已经被清除），所以只能重新做。
1. 用mmm_control 关闭对应节点
mmm_control  set_offline db11
mmm_control  set_offline db2
2. 重置master/slave(db2,db11)
reset master;
reset slave;
slave stop
3. 复制最新的master到后备master(from db2 to db11)
使用 mk-parallel-dump和mk-parallel-restore 安全，快速。
xtrabackup 也可以,但不够快速和安全，且需要各个节点配置完全一样。
4. 重新启用replication
db2:
change master to  master_host=&#8217;192.168.8.11&#8242;,master_user=&#8217;xxxxxx&#8217;,master_password=&#8217;xxxx&#8217;, master_log_file=&#8217;mysql-bin.000001&#8242;,master_log_pos=0;
db11:
change master to  master_host=&#8217;192.168.8.2&#8242;,master_user=&#8217;xxxxx&#8217;,master_password=&#8217;xxxx&#8217;, master_log_file=&#8217;mysql-bin.000001&#8242;,master_log_pos=0;
both:
slave start
show master status\G
show slave status\G
5. set db online
mmm_control  set_online db2
mmm_control  set_online db11
完毕。
]]></description>
			<content:encoded><![CDATA[<p>系统出现错误导致2个Master之间出现不一致。需要立刻同步。<br />
由于错误出现的时间超过了binlog的保留范围（已经被清除），所以只能重新做。</p>
<p>1. 用mmm_control 关闭对应节点<br />
mmm_control  set_offline db11<br />
mmm_control  set_offline db2</p>
<p>2. 重置master/slave(db2,db11)<br />
reset master;<br />
reset slave;<br />
slave stop</p>
<p>3. 复制最新的master到后备master(from db2 to db11)<br />
使用 mk-parallel-dump和mk-parallel-restore 安全，快速。<br />
xtrabackup 也可以,但不够快速和安全，且需要各个节点配置完全一样。</p>
<p>4. 重新启用replication<br />
db2:<br />
change master to  master_host=&#8217;192.168.8.11&#8242;,master_user=&#8217;xxxxxx&#8217;,master_password=&#8217;xxxx&#8217;, master_log_file=&#8217;mysql-bin.000001&#8242;,master_log_pos=0;<br />
db11:<br />
change master to  master_host=&#8217;192.168.8.2&#8242;,master_user=&#8217;xxxxx&#8217;,master_password=&#8217;xxxx&#8217;, master_log_file=&#8217;mysql-bin.000001&#8242;,master_log_pos=0;</p>
<p>both:<br />
slave start<br />
show master status\G<br />
show slave status\G</p>
<p>5. set db online<br />
mmm_control  set_online db2<br />
mmm_control  set_online db11</p>
<p>完毕。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/03/15/689.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>令我发狂IE cookie的问题</title>
		<link>http://nightsailer.com/2010/03/09/685.html</link>
		<comments>http://nightsailer.com/2010/03/09/685.html#comments</comments>
		<pubDate>Tue, 09 Mar 2010 15:40:17 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[ie6]]></category>

		<guid isPermaLink="false">http://nightsailer.com/?p=685</guid>
		<description><![CDATA[这个问题基本上可以令人发狂。在 6.0 sp3 091208-2036以后的版本（其他版本也可能有问题）。
如果使用php的set_cookie 如果设置的过期时间比较短，比如180秒后过期，那么cookie将无法创建。
而之前的IE版本以及如Firefox,Chrome,Safari等均没有这个现象。
发现这个原因，是我折腾了一晚上，并且特意弄了台windows，用QQ远程在一个网友的机器上反复折腾，
当临近崩溃的最后一秒发现的。
血泪的教训。 cookie的过期时间最好在1个小时以上，通过将过期时间写入值存入cookie，然后判断，不要依赖浏览器，尤其是
狗屎的IE6. 
听说国外有人给IE6举办了葬礼，什么时候国内能有呢，那对于web开发真是个福音。不过，IE7/8对于网银的支持实在
是糟糕透顶，对于我这种mac用户，IE乃至windows的唯一用途就是上网银。。。所以，我的虚拟机用的还是IE6.。。
天大的讽刺！
还好，招商银行支持iphone，方便多了。
]]></description>
			<content:encoded><![CDATA[<p>这个问题基本上可以令人发狂。在 6.0 sp3 091208-2036以后的版本（其他版本也可能有问题）。<br />
如果使用php的set_cookie 如果设置的过期时间比较短，比如180秒后过期，那么cookie将无法创建。<br />
而之前的IE版本以及如Firefox,Chrome,Safari等均没有这个现象。</p>
<p>发现这个原因，是我折腾了一晚上，并且特意弄了台windows，用QQ远程在一个网友的机器上反复折腾，<br />
当临近崩溃的最后一秒发现的。</p>
<p>血泪的教训。 cookie的过期时间最好在1个小时以上，通过将过期时间写入值存入cookie，然后判断，不要依赖浏览器，尤其是<br />
狗屎的IE6. </p>
<p>听说国外有人给IE6举办了葬礼，什么时候国内能有呢，那对于web开发真是个福音。不过，IE7/8对于网银的支持实在<br />
是糟糕透顶，对于我这种mac用户，IE乃至windows的唯一用途就是上网银。。。所以，我的虚拟机用的还是IE6.。。<br />
天大的讽刺！</p>
<p>还好，招商银行支持iphone，方便多了。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/03/09/685.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes: CentOS5.4编译Perl IO::Tty的处理</title>
		<link>http://nightsailer.com/2010/01/29/649.html</link>
		<comments>http://nightsailer.com/2010/01/29/649.html#comments</comments>
		<pubDate>Thu, 28 Jan 2010 17:40:59 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[Technotes]]></category>

		<guid isPermaLink="false">http://night9.cn/?p=649</guid>
		<description><![CDATA[直接编译IO::Tty,会导致:
Can&#8217;t load &#8216;/root/.cpan/build/IO-Tty-1.08-PWZkbn/blib/arch/auto/IO/Tty/Tty.so&#8217; for module IO::Tty:
 undefined symbol: strlcpy at &#8230;..
快速修正, 打开Makefile
DEFINE = -DHAVE_DEV_PTMX -DHAVE_GETPT -DHAVE_GRANTPT -DHAVE_OPENPTY -DHAVE_POSIX_OPENPT -DHAVE_PTSNAME -DHAVE_PTSNAME_R -DHAVE_PTY_H -DHAV
E_SIGACTION -DHAVE_STRLCPY -DHAVE_SYS_STROPTS_H -DHAVE_TERMIOS_H -DHAVE_TERMIO_H -DHAVE_TTYNAME -DHAVE_UNLOCKPT -DHAVE__GETPTY
去掉 中间的-DHAVE_STRLCPY和最后的-DHAVE__GETPTY
重新编译, make test.
ok!
]]></description>
			<content:encoded><![CDATA[<p>直接编译IO::Tty,会导致:</p>
<p>Can&#8217;t load &#8216;/root/.cpan/build/IO-Tty-1.08-PWZkbn/blib/arch/auto/IO/Tty/Tty.so&#8217; for module IO::Tty:<br />
 undefined symbol: strlcpy at &#8230;..</p>
<p>快速修正, 打开Makefile<br />
DEFINE = -DHAVE_DEV_PTMX -DHAVE_GETPT -DHAVE_GRANTPT -DHAVE_OPENPTY -DHAVE_POSIX_OPENPT -DHAVE_PTSNAME -DHAVE_PTSNAME_R -DHAVE_PTY_H -DHAV<br />
E_SIGACTION -DHAVE_STRLCPY -DHAVE_SYS_STROPTS_H -DHAVE_TERMIOS_H -DHAVE_TERMIO_H -DHAVE_TTYNAME -DHAVE_UNLOCKPT -DHAVE__GETPTY</p>
<p>去掉 中间的-DHAVE_STRLCPY和最后的-DHAVE__GETPTY</p>
<p>重新编译, make test.</p>
<p>ok!</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/01/29/649.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>技巧:用ETag产生更为有效的304 Not Modified</title>
		<link>http://nightsailer.com/2010/01/09/613.html</link>
		<comments>http://nightsailer.com/2010/01/09/613.html#comments</comments>
		<pubDate>Sat, 09 Jan 2010 05:46:20 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technotes]]></category>
		<category><![CDATA[ETag]]></category>

		<guid isPermaLink="false">http://night9.cn/?p=613</guid>
		<description><![CDATA[对于大流量的网站, 尽可能使用304 Not Modified, 这将大大节约带宽的使用,也节省你的资金投入.
通常,对于静态文件, 一般都无须配置, 多数的http server能够产生有效的last-modifed-time和Expires header,
同时下次请求的时候自动判断并输出304.
但是对于动态输出的页面, 依赖时间戳并不是一个有效的方式. 很多时候, 我们需要频繁更新文件,但是
文件内容并没有改变. 这是就要用到ETag了.
关于ETag即Entity Tag是W3C在HTTP 1.1中定义的. 对于动态输出,我们可以使用md5值作为etag的值, 这样
可以当内容没有变更,那么就可以直接返回304了.
结合MongoDB的GridFS,ETag更加有用. 当文件被存储到db中的时候, 计算文件的md5值,保存. 当输出gridfs中的文件时候,
同时输出日期和etag.
以下是一个简单的PHP类, 用于检查是否刷新, 这个类首先检查过期时间, 同时检查etag, 并且etag的优先级高于日期检查:

]]></description>
			<content:encoded><![CDATA[<p>对于大流量的网站, 尽可能使用304 Not Modified, 这将大大节约带宽的使用,也节省你的资金投入.<br />
通常,对于静态文件, 一般都无须配置, 多数的http server能够产生有效的last-modifed-time和Expires header,<br />
同时下次请求的时候自动判断并输出304.<br />
但是对于动态输出的页面, 依赖时间戳并不是一个有效的方式. 很多时候, 我们需要频繁更新文件,但是<br />
文件内容并没有改变. 这是就要用到ETag了.</p>
<p>关于ETag即Entity Tag是W3C在HTTP 1.1中定义的. 对于动态输出,我们可以使用md5值作为etag的值, 这样<br />
可以当内容没有变更,那么就可以直接返回304了.</p>
<p>结合MongoDB的GridFS,ETag更加有用. 当文件被存储到db中的时候, 计算文件的md5值,保存. 当输出gridfs中的文件时候,<br />
同时输出日期和etag.<br />
以下是一个简单的PHP类, 用于检查是否刷新, 这个类首先检查过期时间, 同时检查etag, 并且etag的优先级高于日期检查:</p>
<p><?php<br />
/**<br />
 * Cache Validator<br />
 *<br />
 * A helper class to mainipulate/validate cache.<br />
 *<br />
 * The code is ported from my oooold project(eps2004),but works!<br />
 * @author night<br />
 */<br />
class CZone_Core_Util_HttpCacheValidator {<br />
	/**<br />
	 * Validate client headers and check wheather to send 304 header.<br />
	 *<br />
	 * @param int $lastModified timestamp to validate<br />
	 * @param string $tag ETag to validate<br />
	 */<br />
	public static function is_expired($lastModified,$tag,$headers){<br />
	//	$now = time();<br />
        // $headers = getallheaders();<br />
    	$refresh=TRUE;<br />
    	if(isset($headers["If-Modified-Since"])) {<br />
			$arraySince = explode(";", $headers["If-Modified-Since"]);<br />
			$since = strtotime($arraySince[0]);<br />
			if($since >= $lastModified) $refresh=FALSE;<br />
    	}<br />
		/**<br />
		 * Check Entity Tag(ETag)<br />
		 *<br />
		 * Entity tags are used for comparing two or more entities from the same requested resource.<br />
		 * HTTP/1.1 uses entity tags in the ETag (section 14.19), If-Match (section 14.24),<br />
		 * If-None-Match (section 14.26), and If-Range (section 14.27) header<br />
		 * fields. The definition of how they are used and compared as cache<br />
		 * validators is in section 13.3.3. An entity tag consists of an opaque<br />
		 * quoted string, possibly prefixed by a weakness indicator.<br />
		 *<br />
		 * entity-tag = [ weak ]<br />
		 * opaque-tag weak       = &#8220;W/&#8221;<br />
		 * opaque-tag =quoted-string<br />
		 *<br />
		 * A &#8220;strong entity tag&#8221; MAY be shared by two entities of<br />
		 * a resource only if they are equivalent by octet equality. A &#8220;weak<br />
		 * entity tag,&#8221; indicated by the &#8220;W/&#8221; prefix, MAY be shared by two<br />
		 * entities of a resource only if the entities are equivalent and could<br />
		 * be substituted for each other with no significant change in<br />
		 * semantics. A weak entity tag can only be used for weak comparison.An<br />
		 * entity tag MUST be unique across all versions of all entities<br />
		 * associated with a particular resource. A given entity tag value MAY<br />
		 * be used for entities obtained by requests on different URIs. The use<br />
		 * of the same entity tag value in conjunction with entities obtained by<br />
		 * requests on different URIs does not imply the equivalence of those<br />
		 * entities.<br />
		 *<br />
		 * See HTTP/1.1(W3C)<br />
		 *<br />
		 */<br />
		if(isset($headers["If-None-Match"])) { // check ETag<br />
            if(strcmp($headers["If-None-Match"], $tag) == 0 ){<br />
                $refresh=FALSE;<br />
            }<br />
            else {<br />
                $refresh=TRUE;<br />
            }</p>
<p>		}<br />
		if(isset($headers["If-Match"])) { // check ETag<br />
		  if(strcmp($headers["If-Match"], $tag) == 0 )<br />
		     $refresh=FALSE;<br />
		  else<br />
		     $refresh=TRUE;<br />
		}<br />
		//firefox style,resume download<br />
		if(isset($headers["If-Range"])) { // check ETag<br />
		  if(strcmp($headers["If-Range"], $tag) == 0 )<br />
		     $refresh=FALSE;<br />
		  else<br />
		     $refresh=TRUE;<br />
		}<br />
		return $refresh;<br />
}<br />
?></p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2010/01/09/613.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Patch for build gmagick on mac osx 10.6(snow leopard)</title>
		<link>http://nightsailer.com/2009/12/03/571.html</link>
		<comments>http://nightsailer.com/2009/12/03/571.html#comments</comments>
		<pubDate>Wed, 02 Dec 2009 17:33:27 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technotes]]></category>
		<category><![CDATA[compile]]></category>
		<category><![CDATA[gmagick]]></category>
		<category><![CDATA[Snow Leopard]]></category>

		<guid isPermaLink="false">http://night9.cn/?p=571</guid>
		<description><![CDATA[在mac osx 10.6.2(snow leopard)编译gmagick失败. 错误如下:
ld: duplicate symbol _php_gmagick_sc_entry in .libs/gmagick_methods.o and .libs/gmagick_helpers.o
collect2: ld returned 1 exit status
make: *** [gmagick.la] Error 1
感觉很奇怪,因为在centos上没问题. 检查了下gmagick_methods.c和gmagic_helpers.c 也没有重复定义啊.
$ nm .libs/gmagick_methods.o &#124;grep _php_gmagick_sc_entry
000000000000f570 S _php_gmagick_sc_entry
$ nm .libs/gmagick_helpers.o &#124;grep _php_gmagick_sc_entry
00000000000034b8 S _php_gmagick_sc_entry
Oh, ld没错, 的确是重复定义了,由于类型是S,那么还是php_gmagick_sc_entry的声明有问题.
再仔细查看了一下,果然. 由于php_gmagick_sc_entry是在php_gmagick.h中声明,而在gmagick_methods.c
和gmagic_helpers.c中都include了这个文件. 由于没有显示声明为exten导致了问题. 重新加入exten修饰符,
ok.
===========Patch=============
&#8212; php_gmagick.h       1970-01-01 17:13:08.000000000 +0800
+++ php_gmagick.h.ns    2009-12-03 [...]]]></description>
			<content:encoded><![CDATA[<p>在mac osx 10.6.2(snow leopard)编译gmagick失败. 错误如下:</p>
<p>ld: duplicate symbol _php_gmagick_sc_entry in .libs/gmagick_methods.o and .libs/gmagick_helpers.o<br />
collect2: ld returned 1 exit status<br />
make: *** [gmagick.la] Error 1</p>
<p>感觉很奇怪,因为在centos上没问题. 检查了下gmagick_methods.c和gmagic_helpers.c 也没有重复定义啊.</p>
<p>$ nm .libs/gmagick_methods.o |grep _php_gmagick_sc_entry<br />
000000000000f570 S _php_gmagick_sc_entry<br />
$ nm .libs/gmagick_helpers.o |grep _php_gmagick_sc_entry<br />
00000000000034b8 S _php_gmagick_sc_entry</p>
<p>Oh, ld没错, 的确是重复定义了,由于类型是S,那么还是php_gmagick_sc_entry的声明有问题.<br />
再仔细查看了一下,果然. 由于php_gmagick_sc_entry是在php_gmagick.h中声明,而在gmagick_methods.c<br />
和gmagic_helpers.c中都include了这个文件. 由于没有显示声明为exten导致了问题. 重新加入exten修饰符,<br />
ok.</p>
<p>===========Patch=============<br />
&#8212; php_gmagick.h       1970-01-01 17:13:08.000000000 +0800<br />
+++ php_gmagick.h.ns    2009-12-03 01:17:52.000000000 +0800<br />
@@ -18,7 +18,7 @@<br />
 */</p>
<p> #ifndef HAVE_PHP_GMAGICK_H<br />
-# define HAVE_PHP_GMAGICK_H<br />
+#define HAVE_PHP_GMAGICK_H</p>
<p> /* Define Extension Properties */<br />
 #define PHP_GMAGICK_EXTNAME    &#8220;gmagick&#8221;<br />
@@ -107,12 +107,12 @@<br />
 #endif</p>
<p> /* Class entries */<br />
-zend_class_entry *php_gmagick_sc_entry;<br />
-zend_class_entry *php_gmagickdraw_sc_entry;<br />
-zend_class_entry *php_gmagickpixel_sc_entry;<br />
-zend_class_entry *php_gmagick_exception_class_entry;<br />
-zend_class_entry *php_gmagickdraw_exception_class_entry;<br />
-zend_class_entry *php_gmagickpixel_exception_class_entry;<br />
+extern zend_class_entry *php_gmagick_sc_entry;<br />
+extern zend_class_entry *php_gmagickdraw_sc_entry;<br />
+extern zend_class_entry *php_gmagickpixel_sc_entry;<br />
+extern zend_class_entry *php_gmagick_exception_class_entry;<br />
+extern zend_class_entry *php_gmagickdraw_exception_class_entry;<br />
+extern zend_class_entry *php_gmagickpixel_exception_class_entry;</p>
<p> /* Forward declarations */<br />
 PHP_METHOD(gmagick, __construct);<br />
&#8212; gmagick.c   1970-01-01 17:13:08.000000000 +0800<br />
+++ gmagick.c.ns        2009-12-03 01:44:20.000000000 +0800<br />
@@ -27,6 +27,13 @@<br />
 static zend_object_handlers gmagickdraw_object_handlers;<br />
 static zend_object_handlers gmagickpixel_object_handlers;</p>
<p>+zend_class_entry *php_gmagick_sc_entry;<br />
+zend_class_entry *php_gmagickdraw_sc_entry;<br />
+zend_class_entry *php_gmagickpixel_sc_entry;<br />
+zend_class_entry *php_gmagick_exception_class_entry;<br />
+zend_class_entry *php_gmagickdraw_exception_class_entry;<br />
+zend_class_entry *php_gmagickpixel_exception_class_entry;<br />
+<br />
 /* {{{ static void php_gmagick_object_free_storage(void *object TSRMLS_DC)<br />
 */<br />
 static void php_gmagick_object_free_storage(void *object TSRMLS_DC)<br />
===========END PATCH============</p>
<p>UPDATE: 作者<a href="http://vitochin.blogspot.com/">Vito</a>回信很迅速啊, 他只使用Linux,patch已经被采纳了.</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2009/12/03/571.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>解决GraphicsMagick 和 ImageMagick冲突(PHP imagick and gmagick extension)</title>
		<link>http://nightsailer.com/2009/12/02/565.html</link>
		<comments>http://nightsailer.com/2009/12/02/565.html#comments</comments>
		<pubDate>Wed, 02 Dec 2009 08:18:29 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technotes]]></category>
		<category><![CDATA[gmagick]]></category>
		<category><![CDATA[imagick]]></category>

		<guid isPermaLink="false">http://night9.cn/2009/12/02/565.html</guid>
		<description><![CDATA[发现PHP imagick or magickwand无法正确加载. 经过测试发现是由于和gmagick冲突. 解决, 在编译GraphicsMagick时候加入:
 &#8211;enable-symbol-prefix 
重新编译后正常.
]]></description>
			<content:encoded><![CDATA[<p>发现PHP imagick or magickwand无法正确加载. 经过测试发现是由于和gmagick冲突. 解决, 在编译GraphicsMagick时候加入:</p>
<p> &#8211;enable-symbol-prefix </p>
<p>重新编译后正常.</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2009/12/02/565.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
