产品需求需要输出那那文档

来源: 新浪微博

 

点击查看原图

 

发表在 article | 标签为 | 产品需求需要输出那那文档已关闭评论

Linux下高并发socket最大连接数

Linux下高并发socket最大连接数所受的限制问题

  1、修改用户进程可打开文件数限制

  在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:

  [speng@as4 ~]$ ulimit -n

  1024

  这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。

  对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

  修改上述限制的最简单的办法就是使用ulimit命令:

  [speng@as4 ~]$ ulimit -n

  上述命令中,在中指定要设置的单一进程允许打开的最大文件数。如果系统回显类似于"Operation notpermitted"之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。

  第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:

  speng soft nofile 10240

  speng hard nofile 10240

  其中speng指定了要修改哪个用户的打开文件数限制,可用'*'号表示修改所有用户的限制;

  soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。

  第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

  session required /lib/security/pam_limits.so 这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。

  第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

  [speng@as4 ~]$ cat /proc/sys/fs/file-max

  12158

  这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。

  修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:

  echo 22158 > /proc/sys/fs/file-max

  这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158.修改完后保存此文件。

  完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的最大文件数限制设为指定的数值。如果重启后用 ulimit-n命令查看用户可打开文件数限制仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit -n命令已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的最大数限制时,新修改的值只能小于或等于上次 ulimit-n设置的值,因此想用此命令增大这个限制值是不可能的。

  所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了ulimit-n限制了用户可同时打开的最大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。 通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。

 

  2、修改网络内核对TCP连接的有关限制

  在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。

  第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是"Can't assign requestedaddress".同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。

  其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为"Can't assignrequested address".

  有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:

  static int tcp_v4_hash_connect(struct sock *sk)

  请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文件中的如下函数中设置:

  void __init tcp_init(void)

  内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。

  第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

  net.ipv4.ip_local_port_range = 1024 65000

  这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535.修改完后保存此文件。

  第二步,执行sysctl命令:

  [speng@as4 ~]$ sysctl -p

  如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。

  第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对最大跟踪的TCP连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpdump工具监视网络,也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对最大跟踪的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:

  第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

  net.ipv4.ip_conntrack_max = 10240

  这表明将系统对最大跟踪的TCP连接数限制设置为10240.请注意,此限制值要尽量小,以节省对内核内存的占用。

  第二步,执行sysctl命令:

  [speng@as4 ~]$ sysctl -p

  如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。

  3、使用支持高并发网络I/O的编程技术在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O.在高TCP并发的情形下,如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。

  但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用同步 I/O是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O.非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO.

  从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用"轮询"机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分TCP连接上的I/O出现"饥饿"现象。而如果使用epoll或AIO,则没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个 I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。

  综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。

  内核参数sysctl.conf的优化

  /etc/sysctl.conf 是用来控制linux网络的配置文件,对于依赖网络的程序(如web服务器和cache服务器)非常重要,RHEL默认提供的最好调整。

  推荐配置(把原/etc/sysctl.conf内容清掉,把下面内容复制进去):

  net.ipv4.ip_local_port_range = 1024 65535

  net.core.rmem_max=16777216

  net.core.wmem_max=16777216

  net.ipv4.tcp_rmem=4096 87380 16777216

  net.ipv4.tcp_wmem=4096 65536 16777216

  net.ipv4.tcp_fin_timeout = 10

  net.ipv4.tcp_tw_recycle = 1

  net.ipv4.tcp_timestamps = 0

  net.ipv4.tcp_window_scaling = 0

  net.ipv4.tcp_sack = 0

  net.core.netdev_max_backlog = 30000

  net.ipv4.tcp_no_metrics_save=1

  net.core.somaxconn = 262144

  net.ipv4.tcp_syncookies = 0

  net.ipv4.tcp_max_orphans = 262144

  net.ipv4.tcp_max_syn_backlog = 262144

  net.ipv4.tcp_synack_retries = 2

  net.ipv4.tcp_syn_retries = 2

  这个配置参考于cache服务器varnish的推荐配置和SunOne 服务器系统优化的推荐配置。

  varnish调优推荐配置的地址为:http://varnish.projects.linpro.no/wiki/Performance

  不过varnish推荐的配置是有问题的,实际运行表明"net.ipv4.tcp_fin_timeout = 3"的配置会导致页面经常打不开;并且当网友使用的是IE6浏览器时,访问网站一段时间后,所有网页都会

  打不开,重启浏览器后正常。可能是国外的网速快吧,我们国情决定需要调整"net.ipv4.tcp_fin_timeout = 10",在10s的情况下,一切正常(实际运行结论)。

  修改完毕后,执行:

  /sbin/sysctl -p /etc/sysctl.conf

  /sbin/sysctl -w net.ipv4.route.flush=1

  命令生效。为了保险起见,也可以reboot系统。

  调整文件数:

  linux系统优化完网络必须调高系统允许打开的文件数才能支持大的并发,默认1024是远远不够的。

  执行命令:

  Shell代码

  echo ulimit -HSn 65536 》 /etc/rc.local

  echo ulimit -HSn 65536 》/root/.bash_profile

  ulimit -HSn 65536

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

net.ipv4.ip_local_port_range = 1024     61000
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 20
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

发表在 linux | 标签为 | Linux下高并发socket最大连接数已关闭评论

postfix 多域名

需求:

假设现在我有两个这样的域名 domain.com 和 domain.cn。现在 domain.com 作为主域名已经成功地在ip地址为 125.168.2.16 的服务器上配置了postfix。即可以通过 abc@domain.com 发送和接收邮件。现在希望 domain.cn 域名也指向该服务器,并可以通过 abc@domain.cn 发送和接收邮件,并且两个域名对应的用户是一致的,即发送给 abc@domain.com 的邮箱的用户实际上也是给 abc@domain.cn 邮箱的用户的邮件,而同一个用户abc可以选择使用 abc@domain.com 或者 abc@domain.cn 发送邮件,而接收方看到的是不同的域名发出来的邮件。

 

够啰嗦了,好,马上开始吧。

 

一、对postfix的虚拟域名相关选项进行设置

$ vi /etc/postfix/main.cf

virtual_alias_maps=hash:/etc/postfix/virtual

二、定义虚拟域名转换规则

$ vi /etc/postfix/virtual                 //在文件末尾添加上下面两行

domain.cn anything

@domain.cn @domain.com

三、更新虚拟域名规则

$ postmap /etc/postfix/virtual

四、重启postfix

$ service postfix restart

 

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

另一

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

Virtual、Aliases、虚拟表等概念之间的关系

  使用Postfix的别名、虚拟域、用MySQL数据库保存用户信息(Postfix+MySQL)等功能的用户,都会与Postfix中virtual、aliases、transport、本地投递、虚拟投递等相关概念打交道。这篇文档就是关于这些概念之间关系的论述。在文章最后,以若干Postfix+MySQL配置方案为例,说明这几个概念在方案中的应用。
  此文档是我在学习Postfix中的一个小结,也让它与时俱进吧:)

  当我开始试图了解Postfix+MySQL做法时,发现自己对上述概念(相关的参数)的关系发生了混乱。于是,我试图找出其中关系,并理顺它。后来,我发现根据Postfix的那张大图(the Big Picture,http://www.postfix.org/big-picture.html),将有助于梳理我们的思路。下面就是按着这样的想法来写的。
  注:下面关于各概念的描述并不完整,主要是从有助于讲清它们起作用的位置,以及理解相互关系的角度出发。更详细的说明请参考相关文档。

  1、首先是virtual。从左向右看这张图,首先遇到的是virtual。virtual是什么?virtual是一张重定向表,用于本地和非本地接收者或接收域的重定向操作。virtual的重定向是一个地址到地址的映射(map),它只是应用在邮件的接收者信封地址(recipient envelope address)部分,没有涉及到邮件的信息头和正文部分。这个重定向操作是在smtpd从网络上接收邮件后,由cleanup程序来完成的。Postfix的虚拟域支持就是通过它来实现的。
  virtual这张表,可以保存在数据库文件中,如/etc/postfix/virtual.db;也可以保存在数据库服务器上,如在MySQL库的一张表中;还可以保存在NIS、LDAP等等。具体的保存方式通过virtual_maps参数值来告诉Postfix。

  2、然后我们继续向右看,接下来的是transport。在这里我们把transport看成一张表,Postfix根据这张表来决定哪些邮件由本地投递代理(local delivery agent)来执行,哪些邮件由虚拟投递代理(virtual delivery agent)来执行。至于这张表保存在什么地方,则由transport_maps参数来指定。
  注:这些邮件一般是根据它们的域进行区分,从而由不同的投递代理来处理。另外,我们不用这张表,完全由本地代理来投递,或是完全由虚拟代理来投递也都是可以的。

  3、接着向右,图中给出的是本地投递代理。从图中可以看出,与本地投递代理相关的两个概念是aliases和.forward。  别名(alias)是由本地投递代理执行的一种系统内的邮件重定向机制,与virtual不同,别名是把整个邮件重定向到另外的一个或多个邮箱。aliases这张表,给出了别名和实际接收者的对应关系。
  aliases表的保存位置,由aliases_maps和aliases_database两个参数来指定。这两个参数互不相关,都发挥作用。aliases_database指定在本地上的别名数据库,是数据库文件形式。aliases_maps除了指定数据库文件外,还可以指定保存在nis或数据库服务器上的别名表。
  .forward则是在用户目录中的一个文件,也用于重定向邮件。但它和我们这里所讨论就没有关系了。这只是提一下。
  
  4、虽然图上没有标出虚拟投递代理,但从transport部分描述,我们知道它是和本地投递代理处于同一级别(位置)的。virtual机制和本地投递代理最终都是把邮件投到系统中一个真实用户的邮箱,而虚拟投递代理所投的邮箱的主人(用户)不是系统真实用户。虚拟投递代理不支持aliases和.forward。它使用虚拟表(virtual table),这些表包括:
  virtual_mailbox_maps,指定保存虚拟用户邮箱的路径表在哪里。相关参数virtual_mailbox_base,指出邮箱路径的前缀;
  virtual_uid_maps,指出保存虚拟用户邮箱的uid的表在哪里,这是针对每个虚拟用户邮箱在系统中的uid都不一样的情况。虚拟用户的邮箱也可以共用一个uid值。
  virtual_gid_maps,这是关于虚拟用户邮箱的gid值。相关情况与uid相同。

 

 

发表在 mail | 标签为 | postfix 多域名已关闭评论

网络流量监控软件

1、WinpCap

WinpCap 是一个免费、公共的网络访问系统,主要是 Windows32平台下用于抓包和分析,同时提供了一个强大的编程接口,容易在各个操作系统之间进行移植,也方便程序员进行开发。

2、MRTG

MRTG (Multi Router Traffic Grapher, MRTG)是一个监控网络链路流量负载的工具软件,它通过SNMP协议从设备得到设备的流量信息,并将流量负载以包含PNG格式的图形的 HTML文档方式显示给用户,以非常直观的形式显示流量负载。

3、Cacti

Cacti 是一套基于PHP、MySQL、SNMP及RRDTool开发的网络流量监测图形分析工具,它利用SNMPGET采集数据,使用 RRDTool绘图引擎绘图,其数据能重复使用并且可以定义任意时间段画图,此外它提供了非常强大的数据和用户管理功能。

4、Nagios

Nagios是一个监视系统运行状态和网络信息的监视系统。Nagios能监视所指定的本地或远程主机以及服务,同时提供异常通知功能等。Nagios可运行在Linux/Unix平台之上,同时提供一个可选的基于浏览器的WEB界面以方便系统管理人员查看网络状态,各种系统问题,以及日志等等。

5、Cacti+Nagios

cacti:在监控方面有良好的绘图,cacti在流量和图型塑造上要强于nagios,但是在故障分析上有些略逊,而且报警机制也有待完善,这时nagios就派上用场了。

nagios:适合监视大量服务器上面的大批服务是否正常,重点并不在图形化的监控,其集成的很多功能例如报警,都是cacti没有或者很弱的。但在绘图以及图型塑造方面精细度比cacti要弱。

因此,将Cacti和Nagios整合在一起可起到互补的作用。

来源: 网络

发表在 technologys | 标签为 , , | 网络流量监控软件已关闭评论

msftp

用户创建的两种方式:

均需设置NTFS权限,主目录需具有所有用户可读取权

一、创建隔离用户站:

主目录: c:\inetpub\ftproot

用户目录: c:\inetpub\ftproot\LocalUser

匿名目录:c:\inetpub\ftproot\LocalUser\public

用户A目录:c:\inetpub\ftproot\LocalUser\a

用户B目录:c:\inetpub\ftproot\LocalUser\b

 

二、默FTP认站+虚拟目录

主目录: c:\inetpub\ftproot,

 

用户所在目录可为任意。

如: 立a用户, 建帐号a,  默认FTP站添加对应的a虚拟目录, 虚拟目录指向用户实际目录。

用户实际目录应至少具有 administrator / system / a 三个用户读写权(但主意别串帐户权限)

建立b,c,d,e等帐户同理。

 

 

可能产生的故障分析

故障现象: 

登陆FTP的时候提示 530 User waadmin cannot log in, home directory inaccessible. 

故障原因: 

FTP根目录权限不够 

第一种解决方法: 

把该用户所在组加个“读取”权限 

或为以下原因

可能是在FTP服务器创建时,选择了FTP隔离用户模式。 

解决方法: 

在用户的ftp根目录下创建LocalUser\用户名 这样的目录,因为用户登录时会自动将主目录移到这里。如果打算允许FTP站点提供匿名登录应在LocalUser目录下另建一个public的子目录LocalUser\public 

IIS FTP "530 User cannot log in home directory inaccessible"错误原因:可能是在FTP服务器创建时,选择了FTP隔离用户模式。

发表在 windows | 标签为 | msftp已关闭评论

openssl update to 1.0.1g

cd /usr/src

wget https://www.openssl.org/source/openssl-1.0.1g.tar.gz -O openssl-1.0.1g.tar.gz

tar -zxf openssl-1.0.1g.tar.gz

cd openssl-1.0.1g

./config

make

make test

make install

 

openssl version

 

mv /usr/bin/openssl /usr/bin/openssl.old
mv /usr/include/openssl /usr/include/openssl.old

ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl /usr/include/openssl

echo "/usr/local/ssl/lib">> /etc/ld.so.conf

openssl version

OpenSSL 1.0.1g 7 Apr 2014

 

 

 

发表在 linux | 标签为 | openssl update to 1.0.1g已关闭评论

一致性哈希(consistent hash)

consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛;

1 基本场景

比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 hash 值,然后均匀的映射到到 N 个 cache ;

hash(object)%N

一切都运行正常,再考虑如下的两种情况;

1 一个 cache 服务器 m down 掉了(在实际应用中必须要考虑这种情况),这样所有映射到 cache m 的对象都会失效,怎么办,需要把 cache m 从 cache 中移除,这时候 cache 是 N-1 台,映射公式变成了 hash(object)%(N-1) ;

2 由于访问加重,需要添加 cache ,这时候 cache 是 N+1 台,映射公式变成了 hash(object)%(N+1) ;

1 和 2 意味着什么?这意味着突然之间几乎所有的 cache 都失效了。对于服务器而言,这是一场灾难,洪水般的访问都会直接冲向后台服务器;

再来考虑第三个问题,由于硬件能力越来越强,你可能想让后面添加的节点多做点活,显然上面的 hash 算法也做不到。

有什么方法可以改变这个状况呢,这就是 consistent hashing…

2 hash 算法和单调性

Hash 算法的一个衡量指标是单调性( Monotonicity ),定义如下:

单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。

容易看到,上面的简单 hash 算法 hash(object)%N 难以满足单调性要求。

3 consistent hashing 算法的原理

consistent hashing 是一种 hash 算法,简单的说,在移除 / 添加一个 cache 时,它能够尽可能小的改变已存在 key 映射关系,尽可能的满足单调性的要求。

下面就来按照 5 个步骤简单讲讲 consistent hashing 算法的基本原理。

3.1 环形hash 空间

考虑通常的 hash 算法都是将 value 映射到一个 32 为的 key 值,也即是 0~2^32-1 次方的数值空间;我们可以将这个空间想象成一个首( 0 )尾( 2^32-1 )相接的圆环,如下面图 1 所示的那样。

 点击查看原图

图 1 环形 hash 空间

3.2 把对象映射到hash 空间

接下来考虑 4 个对象 object1~object4 ,通过 hash 函数计算出的 hash 值 key 在环上的分布如图 2 所示。

hash(object1) = key1;

… …

hash(object4) = key4;

 点击查看原图

图 2 4 个对象的 key 值分布

3.3 把cache 映射到hash 空间

Consistent hashing 的基本思想就是将对象和 cache 都映射到同一个 hash 数值空间中,并且使用相同的hash 算法。

假设当前有 A,B 和 C 共 3 台 cache ,那么其映射结果将如图 3 所示,他们在 hash 空间中,以对应的 hash值排列。

hash(cache A) = key A;

… …

hash(cache C) = key C;

 点击查看原图

图 3 cache 和对象的 key 值分布

说到这里,顺便提一下 cache 的 hash 计算,一般的方法可以使用 cache 机器的 IP 地址或者机器名作为hash 输入。

3.4 把对象映射到cache

现在 cache 和对象都已经通过同一个 hash 算法映射到 hash 数值空间中了,接下来要考虑的就是如何将对象映射到 cache 上面了。

在这个环形空间中,如果沿着顺时针方向从对象的 key 值出发,直到遇见一个 cache ,那么就将该对象存储在这个 cache 上,因为对象和 cache 的 hash 值是固定的,因此这个 cache 必然是唯一和确定的。这样不就找到了对象和 cache 的映射方法了吗?!

依然继续上面的例子(参见图 3 ),那么根据上面的方法,对象 object1 将被存储到 cache A 上; object2和 object3 对应到 cache C ; object4 对应到 cache B ;

3.5 考察cache 的变动

前面讲过,通过 hash 然后求余的方法带来的最大问题就在于不能满足单调性,当 cache 有所变动时,cache 会失效,进而对后台服务器造成巨大的冲击,现在就来分析分析 consistent hashing 算法。

3.5.1 移除 cache

考虑假设 cache B 挂掉了,根据上面讲到的映射方法,这时受影响的将仅是那些沿 cache B 逆时针遍历直到下一个 cache ( cache C )之间的对象,也即是本来映射到 cache B 上的那些对象。

因此这里仅需要变动对象 object4 ,将其重新映射到 cache C 上即可;参见图 4 。

 点击查看原图

图 4 Cache B 被移除后的 cache 映射

3.5.2 添加 cache

再考虑添加一台新的 cache D 的情况,假设在这个环形 hash 空间中, cache D 被映射在对象 object2 和object3 之间。这时受影响的将仅是那些沿 cache D 逆时针遍历直到下一个 cache ( cache B )之间的对象(它们是也本来映射到 cache C 上对象的一部分),将这些对象重新映射到 cache D 上即可。

 

因此这里仅需要变动对象 object2 ,将其重新映射到 cache D 上;参见图 5 。

点击查看原图

图 5 添加 cache D 后的映射关系

4 虚拟节点

考量 Hash 算法的另一个指标是平衡性 (Balance) ,定义如下:

平衡性

平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。

hash 算法并不是保证绝对的平衡,如果 cache 较少的话,对象并不能被均匀的映射到 cache 上,比如在上面的例子中,仅部署 cache A 和 cache C 的情况下,在 4 个对象中, cache A 仅存储了 object1 ,而 cache C 则存储了 object2 、 object3 和 object4 ;分布是很不均衡的。

为了解决这种情况, consistent hashing 引入了“虚拟节点”的概念,它可以如下定义:

“虚拟节点”( virtual node )是实际节点在 hash 空间的复制品( replica ),一实际个节点对应了若干个“虚拟节点”,这个对应个数也成为“复制个数”,“虚拟节点”在 hash 空间中以 hash 值排列。

仍以仅部署 cache A 和 cache C 的情况为例,在图 4 中我们已经看到, cache 分布并不均匀。现在我们引入虚拟节点,并设置“复制个数”为 2 ,这就意味着一共会存在 4 个“虚拟节点”, cache A1, cache A2 代表了 cache A ; cache C1, cache C2 代表了 cache C ;假设一种比较理想的情况,参见图 6 。

点击查看原图

图 6 引入“虚拟节点”后的映射关系

此时,对象到“虚拟节点”的映射关系为:

objec1->cache A2 ; objec2->cache A1 ; objec3->cache C1 ; objec4->cache C2 ;

因此对象 object1 和 object2 都被映射到了 cache A 上,而 object3 和 object4 映射到了 cache C 上;平衡性有了很大提高。

引入“虚拟节点”后,映射关系就从 { 对象 -> 节点 } 转换到了 { 对象 -> 虚拟节点 } 。查询物体所在 cache时的映射关系如图 7 所示。

点击查看原图

图 7 查询对象所在 cache

“虚拟节点”的 hash 计算可以采用对应节点的 IP 地址加数字后缀的方式。例如假设 cache A 的 IP 地址为202.168.14.241 。

引入“虚拟节点”前,计算 cache A 的 hash 值:

Hash(“202.168.14.241”);

引入“虚拟节点”后,计算“虚拟节”点 cache A1 和 cache A2 的 hash 值:

Hash(“202.168.14.241#1”);  // cache A1

Hash(“202.168.14.241#2”);  // cache A2

 

PHP 

在PHP使用pecl::memcache  的时候,客户端也已经实现了 consistent 算法。需要修改如下参数。

memcache.hash_strategy=consistent
memcache.hash_function=crc32

发表在 technologys | 标签为 , | 一致性哈希(consistent hash)已关闭评论

WebSocket

首先认识HTML5的websocket:

在HTML5规范中,我最喜欢的Web技术就是正迅速变得流行的WebSocket API。WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术。这个新的API提供了一个方法,从客户端使用简单的语法有效地推动消息到服务器。让我们看一看HTML5的WebSocket API:它可用于客户端、服务器端。而且有一个优秀的第三方API,名为Socket.IO。

什么是WebSocket API?

WebSocket API是下一代客户端-服务器的异步通信方法。该通信取代了单个的TCP套接字,使用ws或wss协议,可用于任意的客户端和服务器程序。WebSocket目前由W3C进行标准化。WebSocket已经受到Firefox 4、Chrome 4、Opera 10.70以及Safari 5等浏览器的支持。



WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信。


Ajax技术很聪明的一点是没有设计要使用的方式。WebSocket为指定目标创建,用于双向推送消息。

关于web实时通信技术的发展(poll,ajax,comet等)以及websocket的介绍具体请参见:

使用 HTML5 WebSocket 构建实时 Web 应用 http://www.linuxidc.com/Linux/2012-02/54014.htm

链接的文章介绍了websocket的旧版协议草案,并用.net实现了该草案。

在2011年7月份,websocket发布了最新版的协议草案,草案的最新版本是草案10,草案的链接地址为:http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10,新的草案增加了安全性和可扩展性。

新草案客户端与服务器端的握手协议:

客户端发起websocket请求

[javascript]
  1. socket = new MozWebSocket("ws://localhost:12345/websocket/server.php")  

这里用的是firefox浏览器,所以用MozWebSocket(),其他浏览器像chrome,需要用WebSocket()

请求头信息格式:

[plain]
  1. GET /chat HTTP/1.1  
  2. Host: localhost:12345  
  3. Upgrade: websocket  
  4. Connection: Upgrade  
  5. Sec-WebSocket-Key: kHuChwCCkr9PZDPWo+nMXg==  
  6. Sec-WebSocket-Origin: http://localhost  
  7. Sec-WebSocket-Protocol: websocket  
  8. Sec-WebSocket-Version: 8  

服务器端取得请求信息,主要是Sec-WebSocket-Key的值,取得该值之后,连接上字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11,然后计算其sha1散列值,生成一个20位的字符串,再对该字符串进行base64编码,最后得到的值,按照下列响应信息格式返回给客户端

[plain]
  1. HTTP/1.1 101 Switching Protocols  
  2. Upgrade: websocket  
  3. Connection: Upgrade  
  4. Sec-WebSocket-Accept: 0VXXdxNQxqV7u7vtIhrxqdYUgRA=  
  5. Sec-WebSocket-Protocol: websocket  

客户端接收到服务器的响应信息,连接建立。

新草案的数据传输格式请参考下文:

    2、数据传输的格式:

以下是一个格式标准图:

点击查看原图

FIN:1位,用来表明这是一个消息的最后的消息片断,当然第一个消息片断也可能是最后的一个消息片断;

RSV1, RSV2, RSV3: 分别都是1位,如果双方之间没有约定自定义协议,那么这几位的值都必须为0,否则必须断掉WebSocket连接;

Opcode:4位操作码,定义有效负载数据,如果收到了一个未知的操作码,连接也必须断掉,以下是定义的操作码:
      *  %x0 表示连续消息片断
      *  %x1 表示文本消息片断
      *  %x2 表未二进制消息片断
      *  %x3-7 为将来的非控制消息片断保留的操作码
      *  %x8 表示连接关闭
      *  %x9 表示心跳检查的ping
      *  %xA 表示心跳检查的pong
      *  %xB-F 为将来的控制消息片断的保留操作码

Mask:1位,定义传输的数据是否有加掩码,如果设置为1,掩码键必须放在masking-key区域,客户端发送给服务端的所有消息,此位的值都是1;

Payload length: 传输数据的长度,以字节的形式表示:7位、7+16位、或者7+64位。如果这个值以字节表示是0-125这个范围,那这个值就表示传输数据的长度;如果这个值是126,则随后的两个字节表示的是一个16进制无符号数,用来表示传输数据的长度;如果这个值是127,则随后的是8个字节表示的一个64位无符合数,这个数用来表示传输数据的长度。多字节长度的数量是以网络字节的顺序表示。负载数据的长度为扩展数据及应用数据之和,扩展数据的长度可能为0,因而此时负载数据的长度就为应用数据的长度。

Masking-key:0或4个字节,客户端发送给服务端的数据,都是通过内嵌的一个32位值作为掩码的;掩码键只有在掩码位设置为1的时候存在。
Payload data:  (x+y)位,负载数据为扩展数据及应用数据长度之和。
Extension data:x位,如果客户端与服务端之间没有特殊约定,那么扩展数据的长度始终为0,任何的扩展都必须指定扩展数据的长度,或者长度的计算方式,以及在握手时如何确定正确的握手方式。如果存在扩展数据,则扩展数据就会包括在负载数据的长度之内。
Application data:y位,任意的应用数据,放在扩展数据之后,应用数据的长度=负载数据的长度-扩展数据的长度。

    数据帧协议是按照扩展的巴科斯范式(ANBF:Augmented Backus-Naur Form RFC5234)组成的:       

[plain]
ws-frame                = frame-fin   
                          frame-rsv1   
                          frame-rsv2   
                          frame-rsv3   
                          frame-opcode   
                          frame-masked   
                          frame-payload-length   
                          [ frame-masking-key ]   
                          frame-payload-data   
 
 frame-fin               = %x0 ; 表示这不是当前消息的最后一帧,后面还有消息   
                        / %x1 ; 表示这是当前消息的最后一帧   
 
frame-rsv1              = %x0   
                          ; 1 bit, 如果没有扩展约定,该值必须为0    
 
 
frame-rsv2              = %x0   
                          ; 1 bit, 如果没有扩展约定,该值必须为0   
 
frame-rsv3              = %x0   
                          ; 1 bit, 如果没有扩展约定,该值必须为0   
 
frame-opcode            = %x0 ; 表示这是一个连续帧消息   
                        / %x1 ; 表示文本消息   
                        / %x2 ; 表示二进制消息   
                        / %x3-7 ; 保留   
                        / %x8 ; 表示客户端发起的关闭   
                        / %x9 ; ping(用于心跳)   
                        / %xA ; pong(用于心跳)   
                        / %xB-F ; 保留    
   
frame-masked            = %x0 ; 数据帧没有加掩码,后面没有掩码key   
                        / %x1 ; 数据帧加了掩码,后面有掩码key   
 
 
frame-payload-length    = %x00-7D   
                        / %x7E frame-payload-length-16   
                        / %x7F frame-payload-length-63   
   ; 表示数据帧的长度   

 
 
frame-payload-length-16 = %x0000-FFFF   
   ; 表示数据帧的长度   
   
frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF   
   ; 表示数据帧的长度   
   
frame-masking-key       = 4( %0x00-FF ) ; 掩码key,只有当掩码位为1时出现   
   
frame-payload-data      = (frame-masked-extension-data   
                           frame-masked-application-data)   ; 当掩码位为1时,这里的数据为带掩码的数据,扩展数据及应用数据都带掩码   
                        / (frame-unmasked-extension-data   
                           frame-unmasked-application-data) ; 当掩码位为0时,这里的数据为不带掩码的数据,扩展数据及应用数据都不带掩码   
   
frame-masked-extension-data     = *( %x00-FF ) ; 目前保留,以后定义   
   
frame-masked-application-data   = *( %x00-FF )   
   
frame-unmasked-extension-data   = *( %x00-FF ) ; 目前保留,以后定义   
   
frame-unmasked-application-data = *( %x00-FF ) 
发表在 technologys | 标签为 | WebSocket已关闭评论

基本数据类型

C#数据类型
.NET框架数据类型
说 明
bool
System.Boolean
逻辑值,true或者false,默认值为false
byte
System.Byte
无符号的字节,所存储的值的范围是0~255,默认值为0
sbyte
System.SByte
带符号的字节,所存储的值的范围是-128~127,默认值为0
char
System.Char
无符号的16位Unicode字符,默认值为’/0’
decimal
System.Decimal
不遵守四舍五入规则的十进制数,通常用于财务方面的计算,默认值为0.0m
double
System.Double
双精度的浮点类型,默认值为0.0d
float
System.Single
单精度的浮点类型,默认值为0.0f
int
System.Int32
带符号的32位整型,默认值为0
uint
System.UInt32
无符号的32位整型,默认值为0
long
System.Int64
带符号的64位整型,默认值为0
ulong
System.UInt64
无符号的64位整型,默认值为0
object
System.Object
指向类实例的引用,默认值为null
short
System.Int16
带符号的16位整型,默认值为0
ushort
System.UInt16
无符号的16位整型,默认值为0
string
System.String
指向字符串对象的引用,默认值为null

 

C语言中 float、double、long double精度、数值范围

IEEE754浮点数的表示方法。C语言里对float类型数据的表示范围为-3.4*10^38~+3.4*10^38。double为-1.7*10^-308~1.7*10^308,long double为-1.2*10^-4932~1.2*10^4932.

类型

比特(位)数

有效数字

数值范围

float

32

6~7

-3.4*10^38~+3.4*10^38

double

64

15~16

-1.7*10^-308~1.7*10^308

long
double

128

18~19

-1.2*10^-4932~1.2*10^4932

decimal

128

28~29

±1.0*10^28 ~ ±7.9*10^28

 

基础类型描述:

byte: 八位整数 -128——127,可用来节省内存的使用。
short: 16位整数 -32768——32,767,也比较省内存。
int: 32位整数 -2,147,483,648——2,147,483,647,一般来说整数都够用了
long: 64位整数 -9,223,372,036,854,775,808—— 9,223,372,036,854,775,807,一般不需要用
float: 32位浮点,如果浮点需要节省内存用这个。
Double: 64位浮点,一般非整数浮点可用这个。

 

究竟如何计算该范围,分析如下:

对于单精度浮点数(float)来说,符号位一位,指数位8位,尾数23位。指数能够表示的指数范围为-128~127。尾数为23位。

float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个
隐含着的“1”,由于它是不变的,故不能对精度造成影响。float:2^23 =
8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;double:2^52 =
4503599627370496,一共16位,同理,double的精度为15~16位。

 

其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。float的范围为-2^128 ~
+2^128,也即-3.40E+38 ~
+3.40E+38;double的范围为-2^1024 ~
+2^1024,也即-1.79E+308
~+1.79E+308。

 

以float为例,如下表:

符号

尾数

指数

1

23

8

数符(+-)

小数部分(决定精度)

-127~128 指数(决定范围)

 

例如:

+1.1111111111111111111111*2^127(小数点后面23个1,由于尾数的范围1~2,其最高位总为1,故只需存取小数部分,所以小数为是23位1),约等于2*2^127=3.4*10^38。为3.4*10^38负数亦然。

Double的计算与此类似,double的符号位为63位,指数为62~52位,共11位。表示的范围为-1024~1023。尾数为51~0。表示的
范围为+1.1111111111111111..11111*2^1023(小数点后面52个1)为1.7*10^308。负数亦然。

 

mysql & java:

类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int)
VARCHAR L+N VARCHAR java.lang.String 12
CHAR N CHAR java.lang.String 1
BLOB L+N BLOB java.lang.byte[] -4
TEXT 65535 VARCHAR java.lang.String -1
INTEGER 4 INTEGER UNSIGNED java.lang.Long 4
TINYINT 3 TINYINT UNSIGNED java.lang.Integer -6
SMALLINT 5 SMALLINT UNSIGNED java.lang.Integer 5
MEDIUMINT 8 MEDIUMINT UNSIGNED java.lang.Integer 4
BIT 1 BIT java.lang.Boolean -7
BIGINT 20 BIGINT UNSIGNED java.math.BigInteger -5
FLOAT 4+8 FLOAT java.lang.Float 7
DOUBLE 22 DOUBLE java.lang.Double 8
DECIMAL 11 DECIMAL java.math.BigDecimal 3
BOOLEAN 1 同TINYINT
ID 11 PK (INTEGER UNSIGNED) java.lang.Long 4
DATE 10 DATE java.sql.Date 91
TIME 8 TIME java.sql.Time 92
DATETIME 19 DATETIME java.sql.Timestamp 93
TIMESTAMP 19 TIMESTAMP java.sql.Timestamp 93
YEAR 4 YEAR java.sql.Date 91

 

 

 

发表在 .net | 标签为 | 基本数据类型已关闭评论

copy as html

Copy As HTML

 

http://visualstudiogallery.msdn.microsoft.com/98fef791-eb65-4cdf-bf84-077b98c234cf

 

 

发表在 .net | copy as html已关闭评论

mysql sort

按IN顺序排序

select * from table_name where doc_id IN ('1dba', 'c20a', '907b')

mysql返回的结果集的排序是按照入库顺序给出的,若希望按照doc_id列表的先后顺序进行排序,

select * from table_name where doc_id IN ('1dba', 'c20a', '907b') order by FIND_IN_SET('1dba', 'c20a', '907b')

 

 ORDER BY + 字段 + 排序方式

使用前:
SELECT `goods_id` FROM `sdb_goods` LIMIT 0 , 30

 点击查看原图

使用后
SELECT `goods_id` FROM `sdb_goods` ORDER BY `goods_id` = 4 DESC LIMIT 0 , 30

点击查看原图
`goods_id` = 4 的商品真排上来了,这个样子就省事情了,哈哈

再来完善下,

SELECT `goods_id` FROM `sdb_goods` ORDER BY `goods_id` = 4 DESC, `goods_id` ASC LIMIT 0 , 30

 点击查看原图

发表在 db | 标签为 | mysql sort已关闭评论

bind rndc

rndc -h       //查看rndc命令帮助

rndc: illegal option -- h

Usage: rndc [-c config] [-s server] [-p port]

[-k key-file ] [-y key] [-V] command



command is one of the following:



reload        Reload configuration file and zones.

reload zone [class [view]]

Reload a single zone.

refresh zone [class [view]]

Schedule immediate maintenance for a zone.

retransfer zone [class [view]]

Retransfer a single zone without checking serial number.

freeze zone [class [view]]

Suspend updates to a dynamic zone.

thaw zone [class [view]]

Enable updates to a frozen dynamic zone and reload it.

reconfig      Reload configuration file and new zones only.

stats         Write server statistics to the statistics file.

querylog      Toggle query logging.

dumpdb [-all|-cache|-zones] [view ...]

Dump cache(s) to the dump file (named_dump.db).

stop          Save pending updates to master files and stop the server.

stop -p       Save pending updates to master files and stop the server

reporting process id.

halt          Stop the server without saving pending updates.

halt -p       Stop the server without saving pending updates reporting

process id.

trace         Increment debugging level by one.

trace level   Change the debugging level.

notrace       Set debugging level to 0.

flush         Flushes all of the server's caches.

flush [view] Flushes the server's cache for a view.

flushname name [view]

Flush the given name from the server's cache(s)

status        Display status of the server.

recursing     Dump the queries that are currently recursing (named.recursing)

*restart      Restart the server.



* == not yet implemented

Version: 9.3.6-P1-RedHat-9.3.6-4.P1.el5

发表在 technologys | 标签为 | bind rndc已关闭评论

nginx install

./configure --prefix=/usr/local/nginx \
--user=apache \
--group=apache \
--with-http_ssl_module \
--with-http_gzip_static_module;
发表在 web server | 标签为 | nginx install已关闭评论

CSS:IE,Chrome,Firefox兼容性和CSS Hack

hack列表(全部经笔者测试,均为标准模式下,混杂模式由于很少会用到所以未对其进行测试):

点击查看原图

其中粉红色部分为属性hack,黄色部分为选择器hack,它们可以结合使用。此外Firefox和Chrome也有它们专有的hack,详细hack方式及使

用示例如下:

Firefox:

@-moz-document url-prefix()    /*写在选择器外层时(只可写在此处):Firefox only*/

Chrome:

@media screen and (-webkit-min-device-pixel-ratio:0)    /*写在选择器外层时(只可写在此处):Chrome only*/

使用示例-写在选择器前面:

 

 

@-moz-document url-prefix()    /*Firefox*/

{

        body

        {

                background-color:pink;

        }

}

注意事项:

浏览器对css的解析是从前到后的,并且采用最后一个样式声明。

 还是不知道怎么区分.好吧,来看个例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>区别IE6、IE7、IE8、FireFox的CSS hack - http://www.52css.com%3c/title>

<style type="text/css">

<!--

#test,#note{

    margin:0 auto;

    text-align:center;    

}

#test {

    width:200px;

    height:30px;

    border: 1px solid #000000;

    color:#fff;

    line-height:30px;

}

.color{

    background-color: #CC00FF;        /*所有浏览器都会显示为紫色*/

    background-color: #FF0000\9;    /*IE6、IE7、IE8会显示红色*/

    *background-color: #0066FF;        /*IE6、IE7会变为蓝色*/            

    _background-color: #009933;        /*IE6会变为绿色*/

}

-->

</style>

</head>

<body>

<div id="test" class="color">测试方块 www.mycsu.net </div>

<div id="note">

    <strong style="color:#009933">IE6</strong>

    <strong style="color:#0066FF">IE7</strong>

    <strong style="color:#FF0000">IE8</strong>

    <strong style="color:#CC00FF">FireFox</strong>

</div>

</body>

</html>

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

background: red;       /* 对FF Opera和Safari有效 */

#background: blue;      /* 对 IE6 和 IE7有效 */

_background: green;      /* 只对IE6有效 */

/*/background: orange;*/      /** 只对IE8有效 **/

!important         /*FF、IE7有效*/

*         /*IE都有效*/

============================================================

IE8是可以和IE7兼容的,简单一行代码,让IE8自动调用IE7的渲染模式

只需要在页面中加入如下HTTP meta-tag:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

只要IE8读到这个标签,它就会自动启动IE7兼容模式,保证页面完整展示。

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

<!--[if lt IE 8]> <html class="no-js lt-ie9 lt-ie8" lang="en-us"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en-us"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-us"> <!--<![endif]-->

条件注释参考:https://msdn.microsoft.com/en-us/library/ms537512%28v=vs.85%29.aspx

来源:http://www.cnblogs.com/wuchao/archive/2012/07/18/2596867.html

发表在 css | 标签为 | CSS:IE,Chrome,Firefox兼容性和CSS Hack已关闭评论

mobile check

if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
	if(window.location.href.indexOf("?mobile")<0){
		try{
			if(/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
				window.location.href="http://m.aooshi.com/";
			}else if(/iPad/i.test(navigator.userAgent)){
			}else{
				window.location.href="http://m.aooshi.com/simple/"
			}
		}catch(e){}
	}
}
发表在 javascript | 标签为 | mobile check已关闭评论