通常解决服务器负载问题,都会通过多服务器分载来解决。常见的解决方案有:
那我们看看Nginx是如何实现负载均衡的,Nginx的upstream目前支持以下几种方式的分配 1、轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 2、weight 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。 2、ip_hash 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 3、fair(第三方) 按后端服务器的响应时间来分配请求,响应时间短的优先分配。 4、url_hash(第三方) 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
Upstream配置如何实现负载
http { upstream www.test1.com { ip_hash; server 172.16.125.76:8066 weight=10; server 172.16.125.76:8077 down; server 172.16.0.18:8066 max_fails=3 fail_timeout=30s; server 172.16.0.18:8077 backup; } upstream www.test2.com { server 172.16.0.21:8066; server 192.168.76.98:8066; } server { listen 80; server_name www.test1.com; location /{ proxy_pass http://www.test1.com; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 80; server_name www.test2.com; location /{ proxy_pass http://www.test2.com; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
当有请求到www.test1.com/www.test2.com 时请求会被分发到对应的upstream设置的服务器列表上。test2的每一次请求分发的服务器都是随机的,就是第一种情况列举的。而test1刚是根据来访问ip的hashid来分发到指定的服务器,也就是说该IP的请求都是转到这个指定的服务器上。
根据服务器的本身的性能差别及职能,可以设置不同的参数控制。
down 表示负载过重或者不参与负载
weight 权重过大代表承担的负载就越大
backup 其它服务器时或down时才会请求backup服务器
max_fails 失败超过指定次数会暂停或请求转往其它服务器
fail_timeout 失败超过指定次数后暂停时间
以上就Nginx的负载均衡的简单配置。那继续我们的本节讨论内容:
一、Session问题
当我们确定一系列负载的服务器后,那我们的WEB站点会分布到这些服务器上。这个时候如果采用Test2 每一次请求随机访问任何一台服务器上,这样导致你访问A服务器后,下一次请求又突然转到B服务器上。这个时候与A服务器建立的Session,传到B站点服务器肯定是无法正常响应的。我们看一下常用的解决方案:
第一种缓存的方式比较理想,缓存的效率也比较高。但是每一台请求服务器都去访问Session会话服务器,那不是加载重了这台Session服务器的负担吗?
第二种保存到数据库中,除了要控制Session的有效期,同时加重了数据库的负担,所以最终的转变为SQL Server 负载均衡,涉及读,写,过期,同步。
第三种通过nginx ip_hash负载保持对同一服务器的会话,这种看起来最方便,最轻量。
正常情况下架构简单的话, ip_hash可以解决Session问题,但是我们来看看下面这种情况
这个时候ip_hash 收到的请求都是来自固定IP代理的请求,如果代理IP的负载过高就会导致ip_hash对应的服务器负载压力过大,这样ip_hash就失去了负载均衡的作用了。
如果缓存可以实现同步共享的话,我们可以通过多session服务器来解决单一负载过重的问题。那Memcached是否可以做Session缓存服务器呢?MemcachedProvider提供了Session的功能,即将Session保存到数据库中。那为什么不直接保存到数据库中,而要通过Memcached保存到数据库中呢?很简单,如果直接保存到数据库中,每一次请求Session有效性都要回数据库验证一下。其次,即使我们为数据库建立一层缓存,那这个缓存也无法实现分布式共享,还是针对同一台缓存服务器负载过重。网上也看到有用Memcached实现Session缓存的成功案例,当然数据库方式实现的还是比较常用的,比如开源Disuz.net论坛。缓存实现的小范围分布式也是比较常用的,比如单点登录也是一种特殊情况。
二、文件上传下载
如果实现了负载均衡,除了Session问题,我们还会碰到文件的上传下载问题。文件不可能上传不同的服务器上,这样会导致下载不到对应文件的问题。我们看一下下面的方案
两种方案都是常用的,我们来说一下文件压缩数据库,以前的方式都是将文件二进制压缩至关系型数据库,而现在NOSQL的流行,加上MongoDB处理文件又比较方便,所以文件压库又多了一种选择。毕竟文件服务器的效率和管理以及安全都不及数据库。
随便聊聊这点事,其实也就是一些应用的趋势和多一种解决方案的实现。
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。 Igor 将源代码以类 BSD 许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。
根据最新一期(08 年 6 月份)的 NetCraft 调查报告显示,已经有超过两百万的主机使用了 Nginx,这个数字超过了另外一个轻量级的 HTTP 服务器 lighttpd, 排名第四,并且发展迅速。下面是这份报告的前几名的报表:
产品 | 网站数 |
Apache | 84,309,103 |
IIS | 60,987,087 |
Google GFE | 10,465,178 |
Unknown | 4,903,174 |
nginx | 2,125,160 |
Oversee | 1,953,848 |
lighttpd | 1,532,952 |
关于这期调查报告的更详细信息请看下面链接:
http://survey.netcraft.com/Reports/200806/
下图是最近几个月使用 Nginx 和 lighttpd 的网站数比较
图 1. 最近几个月使用 Nginx 和 lighttpd 的网站数比较
为了确保能在 Nginx 中使用正则表达式进行更灵活的配置,安装之前需要确定系统是否安装有 PCRE(Perl Compatible Regular Expressions)包。您可以到 ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的 PCRE 源码包,使用下面命令下载编译和安装 PCRE 包:
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.7.tar.gz # tar zxvf pcre-7.7.tar.gz # cd pcre-7.7 # ./configure # make # make install |
接下来安装 Nginx,Nginx 一般有两个版本,分别是稳定版和开发版,您可以根据您的目的来选择这两个版本的其中一个,下面是把 Nginx 安装到 /opt/nginx 目录下的详细步骤:
# wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz # tar zxvf nginx-0.6.31.tar.gz # cd nginx-0.6.31 # ./configure --with-http_stub_status_module –prefix=/opt/nginx # make # make install |
其中参数 --with-http_stub_status_module
是为了启用 nginx 的 NginxStatus
功能,用来监控 Nginx 的当前状态。
安装成功后 /opt/nginx 目录下有四个子目录分别是:conf、html、logs、sbin 。其中 Nginx 的配置文件存放于 conf/nginx.conf,Nginx 只有一个程序文件位于 sbin 目录下的 nginx 文件。确保系统的 80 端口没被其他程序占用,运行 sbin/nginx 命令来启动 Nginx,打开浏览器访问此机器的 IP,如果浏览器出现 Welcome to nginx! 则表示 Nginx 已经安装并运行成功。
Nginx 安装后只有一个程序文件,本身并不提供各种管理程序,它是使用参数和系统信号机制对 Nginx 进程本身进行控制的。 Nginx 的参数包括有如下几个:
-c <path_to_config>:使用指定的配置文件而不是 conf 目录下的 nginx.conf 。
-t:测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。
-v:显示 nginx 版本号。
-V:显示 nginx 的版本号以及编译环境信息以及编译时的参数。
例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令
sbin/nginx – t – c conf/nginx2.conf |
Nginx 支持下表中的信号:
信号名 | 作用描述 |
TERM, INT | 快速关闭程序,中止当前正在处理的请求 |
QUIT | 处理完当前请求后,关闭程序 |
HUP | 重新加载配置,并开启新的工作进程,关闭就的进程,此操作不会中断请求 |
USR1 | 重新打开日志文件,用于切换日志,例如每天生成一个新的日志文件 |
USR2 | 平滑升级可执行程序 |
WINCH | 从容关闭工作进程 |
有两种方式来通过这些信号去控制 Nginx,第一是通过 logs 目录下的 nginx.pid 查看当前运行的 Nginx 的进程 ID,通过
kill – XXX <pid>
来控制 Nginx,其中 XXX 就是上表中列出的信号名。如果您的系统中只有一个
Nginx 进程,那您也可以通过 killall
命令来完成,例如运行 killall – s HUP
nginx
来让 Nginx 重新加载配置。
先来看一个实际的配置文件:
user nobody;# 工作进程的属主 worker_processes 4;# 工作进程数,一般与 CPU 核数等同 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { use epoll;#Linux 下性能最好的 event 模式 worker_connections 2048;# 每个工作进程允许最大的同时连接数 } http { include mime.types; default_type application/octet-stream; #log_format main ‘$remote_addr - $remote_user [$time_local] $request ‘ # ‘"$status" $body_bytes_sent "$http_referer" ‘ # ‘"$http_user_agent" "$http_x_forwarded_for"‘; #access_log off; access_log logs/access.log;# 日志文件名 sendfile on; #tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; include gzip.conf; # 集群中的所有后台服务器的配置信息 upstream tomcats { server 192.168.0.11:8080 weight=10; server 192.168.0.11:8081 weight=10; server 192.168.0.12:8080 weight=10; server 192.168.0.12:8081 weight=10; server 192.168.0.13:8080 weight=10; server 192.168.0.13:8081 weight=10; } server { listen 80;#HTTP 的端口 server_name localhost; charset utf-8; #access_log logs/host.access.log main; location ~ ^/NginxStatus/ { stub_status on; #Nginx 状态监控配置 access_log off; } location ~ ^/(WEB-INF)/ { deny all; } location ~ \.(htm|html|asp|php|gif|jpg|jpeg|png|bmp|ico|rar|css|js| zip|java|jar|txt|flv|swf|mid|doc|ppt|xls|pdf|txt|mp3|wma)$ { root /opt/webapp; expires 24h; } location / { proxy_pass http://tomcats;# 反向代理 include proxy.conf; } error_page 404 /html/404.html; # redirect server error pages to the static page /50x.html # error_page 502 503 /html/502.html; error_page 500 504 /50x.html; location = /50x.html { root html; } } } |
上面是一个实际网站的配置实例,其中灰色文字为配置说明。上述配置中,首先我们定义了一个 location ~ ^/NginxStatus/,这样通过 http://localhost/NginxStatus/ 就可以监控到 Nginx 的运行信息,显示的内容如下:
Active connections: 70 server accepts handled requests 14553819 14553819 19239266 Reading: 0 Writing: 3 Waiting: 67 |
NginxStatus 显示的内容意思如下:
通过正则表达式,我们可让 Nginx 识别出各种静态文件,例如 images 路径下的所有请求可以写为:
location ~ ^/images/ { root /opt/webapp/images; } |
而下面的配置则定义了几种文件类型的请求处理方式。
location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|ico|css|js|txt)$ { root /opt/webapp; expires 24h; } |
对于例如图片、静态 HTML 文件、js 脚本文件和 css 样式文件等,我们希望 Nginx
直接处理并返回给浏览器,这样可以大大的加快网页浏览时的速度。因此对于这类文件我们需要通过 root 指令来指定文件的存放路径,同时因为这类文件并不常修改,通过
expires
指令来控制其在浏览器的缓存,以减少不必要的请求。 expires
指令可以控制 HTTP
应答中的“ Expires ”和“ Cache-Control ”的头标(起到控制页面缓存的作用)。您可以使用例如以下的格式来书写 Expires:
expires 1 January, 1970, 00:00:01 GMT; expires 60s; expires 30m; expires 24h; expires 1d; expires max; expires off; |
Nginx 本身并不支持现在流行的 JSP、ASP、PHP、PERL 等动态页面,但是它可以通过反向代理将请求发送到后端的服务器,例如
Tomcat、Apache、IIS 等来完成动态页面的请求处理。前面的配置示例中,我们首先定义了由 Nginx 直接处理的一些静态文件请求后,其他所有的请求通过
proxy_pass 指令传送给后端的服务器(在上述例子中是 Tomcat)。最简单的 proxy_pass
用法如下:
location / { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; } |
这里我们没有使用到集群,而是将请求直接送到运行在 8080 端口的 Tomcat 服务上来完成类似 JSP 和 Servlet 的请求处理。
当页面的访问量非常大的时候,往往需要多个应用服务器来共同承担动态页面的执行操作,这时我们就需要使用集群的架构。 Nginx 通过
upstream
指令来定义一个服务器的集群,最前面那个完整的例子中我们定义了一个名为 tomcats
的集群,这个集群中包括了三台服务器共 6 个 Tomcat 服务。而 proxy_pass 指令的写法变成了:
location / { proxy_pass http://tomcats; proxy_set_header X-Real-IP $remote_addr; } |
在 Nginx 的集群配置中,Nginx 使用最简单的平均分配规则给集群中的每个节点分配请求。一旦某个节点失效时,或者重新起效时,Nginx 都会非常及时的处理状态的变化,以保证不会影响到用户的访问。
尽管整个程序包只有五百多 K,但麻雀虽小、五脏俱全。 Nginx 官方提供的各种功能模块应有尽有,结合这些模块可以完整各种各样的配置要求,例如:压缩、防盗链、集群、FastCGI、流媒体服务器、Memcached 支持、URL 重写等等,更关键的是 Nginx 拥有 Apache 和其他 HTTP 服务器无法比拟的高性能。您甚至可以在不改变原有网站的架构上,通过在前端引入 Nginx 来提升网站的访问速度。
本文只是简单介绍了 Nginx 的安装以及常见的基本的配置和使用,更多关于 Nginx 的信息请阅读文章后面的参考资源。在这里要非常感谢我的朋友——陈磊(chanix@msn.com),他一直在做 Nginx 的中文 WIKI(http://wiki.codemongers.com/NginxChs),同时也是他介绍给我这么好的一款软件。
如果您的网站是运行在 Linux 下,如果您并没有使用一些非常复杂的而且确定 Nginx 无法完成的功能,那您应该试试 Nginx 。
ginx的upstream目前支持4种方式的分配 1、轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、weight 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。 2、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 3、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。 4、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
负载均衡: 只需要在http中增加
upstream tgcluster {#定义负载均衡设备的Ip及设备状态 ip_hash; server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2; server 127.0.0.1:6060; server 127.0.0.1:7070
backup; } 在需要使用负载均衡的server中增加 proxy_pass http://tgcluster/; 每个设备的状态设置为: 1.down 表示单前的server暂时不参与负载
2.weight 默认为1.weight越大,负载的权重就越大。 3.max_fails
:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4.fail_timeout:max_fails次失败后,暂停的时间。 5.backup:
其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
研究这个东西好多天了...没人教,难啊...什么都得一个一个搜索。Fuck
来源 v
http://blog.s135.com/tags/nginx/
中文文档:http://wiki.nginx.org/NginxChs
#用户 用户组 user www www; #工作进程,根据硬件调整,有人说几核cpu,就配几个,我觉得可以多一点
worker_processes 5; #错误日志 error_log logs/error.log; #pid文件位置 pid logs/nginx.pid;
worker_rlimit_nofile 8192;
events { #工作进程的最大连接数量,根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行 worker_connections 4096; }
http { include conf/mime.types; #反向代理配置,可以打开proxy.conf看看 include /etc/nginx/proxy.conf; #fastcgi配置,可以打开fastcgi.conf看看 include /etc/nginx/fastcgi.conf;
default_type application/octet-stream; #日志的格式 log_format main ‘$remote_addr – $remote_user [$time_local] $status ‘ ‘”$request” $body_bytes_sent “$http_referer” ‘ ‘”$http_user_agent” “$http_x_forwarded_for”’; #访问日志 access_log logs/access.log main; sendfile on; tcp_nopush on; #根据实际情况调整,如果server很多,就调大一点 server_names_hash_bucket_size 128; # this seems to be required for some vhosts
#这个例子是fastcgi的例子,如果用fastcgi就要仔细看 server { # php/fastcgi listen 80; #域名,可以有多个 server_name domain1.com www.domain1.com; #访问日志,和上面的级别不一样,应该是下级的覆盖上级的 access_log logs/domain1.access.log main; root html;
location / { index index.html index.htm index.php; }
#所有php后缀的,都通过fastcgi发送到1025端口上 #上面include的fastcgi.conf在此应该是有作用,如果你不include,那么就把fastcgi.conf的配置项放在这个下面。 location ~ .php$ { fastcgi_pass 127.0.0.1:1025; } }
#这个是反向代理的例子 server { # simple reverse-proxy listen 80; server_name domain2.com www.domain2.com; access_log logs/domain2.access.log main;
#静态文件,nginx自己处理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { root /var/www/virtual/big.server.com/htdocs; #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。 expires 30d; }
#把请求转发给后台web服务器,反向代理和fastcgi的区别是,反向代理后面是web服务器,fastcgi后台是fasstcgi监听进程,当然,协议也不一样。 location / { proxy_pass http://127.0.0.1:8080; } }
#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。据说nginx可以根据后台响应时间调整。后台需要多个web服务器。
01 |
upstream big_server_com { |
02 |
server 127.0.0.3:8000 weight=5;
|
03 |
server 127.0.0.3:8001 weight=5;
|
04 |
server 192.168.0.1:8000; |
05 |
server 192.168.0.1:8001; |
06 |
} |
07 |
08 |
server { |
09 |
listen 80; |
10 |
server_name big.server.com; |
11 |
access_log logs/big.server.access.log main;
|
12 |
13 |
location / { |
14 |
proxy_pass http: //big_server_com;
|
15 |
} |
16 |
} |
17 |
} |
—————————————–
Nginx 安置后只有一个法式文件,自己并不供给各类办理法式,它是利用参数和体系旌旗灯号机制对 Nginx 历程自己举行节制的。 Nginx 的参数包罗有如下几个:
-c :利用指定的设置装备摆设文件而不是 conf 目次下的 nginx.conf 。
-t:测试设置装备摆设文件是否准确,在运行时必要从头加载设置装备摆设的时辰,此号令很是主要,用来检测所点窜的设置装备摆设文件是否有语法错误。
-v:表现 nginx 版本号。
-V:表现 nginx 的版本号以及编译情况信息以及编译时的参数。
比方我们要测试某个设置装备摆设文件是否誊写准确,我们可以利用以下号令
Nginx 撑持下表中的旌旗灯号:
旌旗灯号名
感化形貌
TERM, INT
快速封闭法式,中断当前正在处置的恳求
QUIT
处置完当前恳求后,封闭法式
HUP
从头加载设置装备摆设,并开启新的事情历程,封闭就的历程,此操纵不会间断恳求
USR1
从头打开日记文件,用于切换日记,比方天天天生一个新的日记文件
USR2
光滑进级可实行法式
WINCH
自在封闭事情历程
有两种体例来经由过程这些旌旗灯号去节制 Nginx,第一是经由过程 logs 目次下的 nginx.pid 检察当前运行的 Nginx 的历程
ID,经由过程 kill – XXX
来节制 Nginx,此中 XXX 便是上表中列出的旌旗灯号名。若是您的体系中只有一个 Nginx
历程,那您也可以经由过程 killall
号令来完成,比方运行 killall – s HUP nginx
来让 Nginx 从头加载设置装备摆设。
先来看一个现实的设置装备摆设文件:
上 面是一个现实网站的设置装备摆设实例,此中灰色笔墨为设置装备摆设申明。上述设置装备摆设中,起首我们界说了一个 location ~ ^/NginxStatus/,如许经由过程 http://localhost/NginxStatus/ 就可以监控到 Nginx 的运行信息,表现的内容如下:
NginxStatus 表现的内容意思如下:
经由过程正则表达式,我们可让 Nginx 辨认出各类静态文件,比方 images 路径下的全部恳求可以写为:
而下面的设置装备摆设则界说了几种文件范例的恳求处置体例。
对付比方图片、静态 HTML 文件、js 剧本文件和 css 样式文件等,我们但愿 Nginx
直接处置并返回给欣赏器,如许可以大大的加速网页欣赏时的速率。是以对付这类文件我们必要经由过程 root
指令来指定文件的存放路径,同时由于这类文件并不常点窜,经由过程 expires
指令来节制其在欣赏器的缓存,以削减不需要的恳求。
expires
指令可以节制 HTTP 应答中的“ Expires ”和“ Cache-Control
”的头标(起到节制页面缓存的感化)。您可以利用比方以下的格局来誊写 Expires:
Nginx 自己并不撑持此刻风行的 JSP、ASP、PHP、PERL 等动态页面,可是它可以经由过程反向代办署理将恳求发送到后真个办事器,比方
Tomcat、Apache、IIS 等来完成动态页面的恳求处置。前面的设置装备摆设示例中,我们起首界说了由 Nginx
直接处置的一些静态文件恳求后,其他全部的恳求经由过程 proxy_pass 指令传送给后真个办事器(在上述例子中是 Tomcat)。最简略的
proxy_pass
用法如下:
这里我们没有利用到集群,而是将恳求直接送到运行在 8080 端口的 Tomcat 办事上来完成近似 JSP 和 Servlet 的恳求处置。
当页面的拜候量很是大的时辰,每每必要多个应用办事器来配合负担动态页面的实行操纵,这时我们就必要利用集群的架构。 Nginx 经由过程
upstream
指令来界说一个办事器的集群,最前面阿谁完备的例子中我们界说了一个名为 tomcats
的集群,这个集群中包罗了三台办事器共 6 个 Tomcat 办事。而 proxy_pass 指令的写法酿成了:
在 Nginx 的集群设置装备摆设中,Nginx 利用最简略的均匀分派法则给集群中的每个节点分派恳求。一旦某个节点失效时,大概从头起效时,Nginx 城市很是实时的处置状况的转变,以包管不会影响到用户的拜候。
尽 管整个法式包只有五百多 K,但麻雀虽小、五脏俱全。 Nginx 官方供给的各类功效模块包罗万象,连系这些模块可以完备各类百般的设置装备摆设要求,比方:压缩、防盗链、集群、FastCGI、流媒体办事器、 Memcached 撑持、URL 重写等等,更关头的是 Nginx 拥有 Apache 和其他 HTTP 办事器无法对比的高机能。您乃至可以在不转变原有网站的架构上,经由过程在前端引入 Nginx 来晋升网站的拜候速率。
本文只是简略先容了 Nginx 的安置以及常见的根基的设置装备摆设和利用,更多关于 Nginx 的信息请阅读文章背面的参考资本。在这里要很是感激我的伴侣——陈磊(chanix@msn.com),他一向在做 Nginx 的中文 WIKI(http://wiki.codemongers.com/NginxChs),同时也是他先容给我这么好的一款软件。
若是您的网站是运行在 Linux 下,若是您并没有利用一些很是庞大的并且确定 Nginx 无法完成的功效,那您应该尝尝 Nginx 。
如果你关注过nginx,必定知道nginx这个软件有什么用的,如果你的网站访问量越来越高,一台服务器已经没有办法承受流量压力,那就增多几台 服务器来做负载吧。做网站负载可以买硬件设备来实现,比如F5,不过价格就几十万到上百万,够贵,本文介绍做网站负载的软件是免费的,nginx目前好多 门户网站与大访问量的网站都在使用做为HTTP服务器,所以nginx是非常优秀的,下面介绍做负载测试吧。 环境: (2台服务器) 第一台: CPU:Inter(R) Pentium(R) 4 CPU 2.8G 内存:1G 系统:windows 7 IIS: IIS 7 nginx:nginx/Windows-0.8.22 IP:172.10.1.97 环境:本地 第二台: CPU:Inter(R) Pentium(R) 4 CPU 3.0G 内存:2G 系统:windows Server 2003 IIS: IIS 6 IP:172.10.1.236 环境:远程
说明: 本次测试,软件nginx放在本地(172.10.1.97),也就是说放在域名绑定的那台服务器,这台服务器的IIS不能使用80端口,因为等下nginx软件要使用80这个端口。 下载nginx的地址如下: nginx下载:http://nginx.net/ 本次测试使用的版本下载:nginx/Windows-0.8.22
下载解压到C:,把目录名改成nginx
好,下面进入实践:
第一:
在本地(172.10.1.97)这台服务器IIS创建一个网站,使用端口为808,如下图:
IIS 网站绑定设置图
第二:
在远程172.10.1.236的IIS创建一个网站,使用端口为80,如下图:
远程IIS绑定设置图
第三:
好了,以上已经设置好两台服务器的IIS了,下面配置nginx软件来实现网站负载均衡,打开如下文件:
C:\nginx\conf\nginx.conf
1、找到内容server {
在这上面加入如下内容:
upstream xueit.com { server 172.10.1.97:808; server 172.10.1.236:80; }
(这是负载切换使用的服务器网站IP)
2、找到location / { root html; index index.html index.htm; }
把内容更改如下:
location / { proxy_pass http://xueit.com/; proxy_redirect default; }
3、找到server { listen 80; server_name localhost;
把内容改成如下:
server { listen 80; server_name 172.10.1.97;
(这是监听访问域名绑定那台服务器80端口的请求)
好,在这里就这么简单配置好了,下面看下以上3步配置的图:
负载配置图
第四:
都配置好了,下面启动nginx这软件
进入命令提示符CMD,进入c:\nginx>,输入nginx命令,如下图:
启动nginx
这时候,系统进程有两个nginx.exe进程,如下图:
系统nginx进程
停止nginx运行输入nginx -s stop 即可
第五:
经过以上的配置,现在我们看下负载效果:
在本地(172.10.1.97)这服务器打开IE,输入:http://172.10.1.97/
第一次打开网站的结果图:
第一次运行网站图
再刷新一下网页,出现的结果图:
很好,网站已经负载成功。
经过这次测试,实现网站负载再也不是难事了。也不用购买非常贵的硬件设备了。网上介绍说nginx软件可以处理并发上万,所以绝对是个非常不错的选择。
如果网站访问量非常大,可以专门用一台服务器跑nginx,其它服务器跑网站程序(几台服务器的程序都是一样的),这样负载就没有太大问题,如果再不行,把网站一些栏目做一个2级域名,2级域名同样做负载,这样更厉害了吧。
nginx软件在linux上跑性能比在windows上跑要好,所以做负载可以用linux跑nginx,.net开发的网站放到windows服务器IIS上。
在linux下配置nginx可以看下这篇文章http://www.xueit.com/html/2009-11-04/29-964604915343.html
转自学IT网:http://www.xueit.com/nginx/show-4866-3.aspx
nginx的upstream目前支持5种方式的分配
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
例如:
1
2
3
4 |
upstream bakend { server 192.168.0.14 weight=10; server 192.168.0.15 weight=10; } |
3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
例如:
1
2
3
4
5 |
upstream bakend { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; } |
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
1
2
3
4
5 |
upstream backend { server server1; server server2; fair; } |
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
1
2
3
4
5
6 |
upstream backend { server squid1:3128; server squid2:3128; hash $request_uri ; hash_method crc32; } |
tips:
upstream bakend{#定义负载均衡设备的Ip及设备 状态
1
2
3
4
5
6 |
ip_hash; server 127.0.0.1:9090 down; server 127.0.0.1:8080 weight=2; server 127.0.0.1:6060; server 127.0.0.1:7070 backup; } |
在需要使用负载均衡的server中增加
proxy_pass http://bakend/;
每个设备的状态设置为:
1.down 表示单前的server暂时不参与负载
2.weight 默认为1.weight越大,负载的权重就越大。
3.max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4.fail_timeout:max_fails次失败后,暂停的时间。
5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
client_body_in_file_only 设置为On 可以讲client post过来的数据记录到文件中用来做debug
client_body_temp_path 设置记录文件的目录 可以设置最多3层目录
location 对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有发生变化每次获取这些数据的时候直接从内存中区获取性能肯定会大大地提高。在.NET中提供了一个Cache类可以实现这些功能。在ASP.NET中可以通过HttpContext 对象的 Cache 属性或 Page 对象的 Cache 属性来获取这个类的实例。 在大部分情况下我们都可以使用Cache类来提高ASP.NET的性能,但是使用Cache类也有一些不足,比如我们不能指定Cache类所占用的内存的大小,此外在Cache中缓存的数据没有办法被另一台机器上的应用程序直接访问,因此在本文中提出另一种数据缓存方案,那就是使用分布式缓存。分布式缓存的特点是缓存的数据不必和应用程序在同一台机器上,从而大大增强了缓存数据的复用性。在本文介绍如何在.NET应用中使用Memcache作为分布式缓存。 Memcached介绍 Memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。在通常的应用中我们都会将数据保存到数据库中,每次需要的时候都会从数据库去查询这些数据,如果应用程序的用户很多就会出现大量并发访问数据库的情况,这样就会增加应用程序的响应时间,使用Memcached就可以有效解决这个问题。memcached是高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。像大名鼎鼎的Facebook网站就使用了Memcached。周公稍后会提供Windows平台上32位和64位的Memcached程序。 为了提高性能,Memcached中的数据都保存在Memcached内置的存储空间中。因为当Memcached重启会导致其中的数据全部丢失,所以一般的方案是将数据保存在数据库中,每次请求数据的时候先查看在Memcached有没有缓存,如果有就直接从缓存中取出数据;如果没有,就从数据库中取出数据返回给应用程序并将请求的数据缓存到Memcached中,这样一来下次请求相同的数据就可以直接从Memcached中读取而不用再去查数据库了;一旦对数据有更新,同时更新数据库和Memcached。 Memcached是一个命令行窗口程序,可以在命令行窗口中启动也可以封装在系统服务中启动。在启动Memcached时需要提供一些必须的参数,指定Memcached运行时监听的端口和最大使用的内存大小等。如果缓存的数据大小超过指定内存,那么Memcached就会按照LRU(Least Recently Used)算法自动“删除”不使用的缓存(标记为失效),新增的缓存数据就可以使用这些标记为失效的数据所占用的内存,这样就不用担心Memcached超出所指定内存的问题。此外,为了提高性能,在缓存数据过期后Memcached并不是从物理内存中删除缓存的数据,仅仅在取出改数据的时候检查它是否已经过了有效期。 目前有多种平台的Memcached版本,比如Linux、FreeBSD、Solaris (memcached 1.2.5以上版本)、Mac OS X及Windows平台,在Windows平台上还有32位和64位版本。 Memcached有一套协议,利用这套协议可以对Memcached进行数据存取和查看Memcached的状态,很多程序语言都依据这套协议来操作Memcached,比如PHP、Java、C、C++及C#等。 获取了对应平台的Memcached版本就可以运行Memcached了。在这里仅以Windows平台上的32位Memcached为例。 运行Memcached: memcached.exe -p 11121 -m 64 上面的命令是运行Memcached,指定它的监听端口是11121(这是它的默认端口,可以指定为其它大于1024的端口,因为小于1024的端口已经有了默认指定),最大使用内存为64m,如果启用了Windows防火墙,切记要在防火墙上打开这个端口。 在调试程序时可以使用下面的命令行来运行: memcached.exe -p 11121 -m 64 -vv 这样就会看到如下的结果: slab class 1: chunk size 88 perslab 11915 slab class 2: chunk size 112 perslab 9362 slab class 3: chunk size 144 perslab 7281 slab class 4: chunk size 184 perslab 5698 slab class 5: chunk size 232 perslab 4519 slab class 6: chunk size 296 perslab 3542 slab class 7: chunk size 376 perslab 2788 slab class 8: chunk size 472 perslab 2221 slab class 9: chunk size 592 perslab 1771 slab class 10: chunk size 744 perslab 1409 slab class 11: chunk size 936 perslab 1120 slab class 12: chunk size 1176 perslab 891 slab class 13: chunk size 1472 perslab 712 slab class 14: chunk size 1840 perslab 569 slab class 15: chunk size 2304 perslab 455 slab class 16: chunk size 2880 perslab 364 slab class 17: chunk size 3600 perslab 291 slab class 18: chunk size 4504 perslab 232 slab class 19: chunk size 5632 perslab 186 slab class 20: chunk size 7040 perslab 148 slab class 21: chunk size 8800 perslab 119 slab class 22: chunk size 11000 perslab 95 slab class 23: chunk size 13752 perslab 76 slab class 24: chunk size 17192 perslab 60 slab class 25: chunk size 21496 perslab 48 slab class 26: chunk size 26872 perslab 39 slab class 27: chunk size 33592 perslab 31 slab class 28: chunk size 41992 perslab 24 slab class 29: chunk size 52496 perslab 19 slab class 30: chunk size 65624 perslab 15 slab class 31: chunk size 82032 perslab 12 slab class 32: chunk size 102544 perslab 10 slab class 33: chunk size 128184 perslab 8 slab class 34: chunk size 160232 perslab 6 slab class 35: chunk size 200296 perslab 5 slab class 36: chunk size 250376 perslab 4 slab class 37: chunk size 312976 perslab 3 slab class 38: chunk size 391224 perslab 2 slab class 39: chunk size 489032 perslab 2 <96 server listening <112 server listening <116 send buffer was 8192, now 268435456 <116 server listening (udp) 在客户端还可以通过telnet来查看和操作Memcached,前提是服务器端和客户端都支持Telnet协议,在Windows7和Windows2008中默认都不支持,需要在控制面板中安装和启用。 首先打开控制面板,然后点击“打开或关闭Windows功能”,如下图所示:
点击“打开或关闭Windows功能”之后会看到当前系统启用的功能的状态,根据当前机器选择打开Telnet服务器端或者客户端功能,如下图所示:
经过上面的操作之后就可以在客服端远程查看Memcached的状态或者操作Memcached了。下面的命令就是连接到Memcached: telnet
localhost 11121
连接之后会出现一个命令行窗口,在这个命令行窗口中输入"stats"就可以看到当前Memcached的状态,如下就是刚刚启动的Memcached的状态数据:
STAT pid 852 STAT uptime 1399 STAT time 1300979378 STAT version 1.2.5 STAT
pointer_size 32 STAT curr_items 0 STAT total_items 0 STAT bytes 0 STAT
curr_connections 3 STAT total_connections 5 STAT connection_structures 4 STAT
cmd_get 0 STAT cmd_set 0 STAT get_hits 0 STAT get_misses 0 STAT evictions 0 STAT
bytes_read 23 STAT bytes_written 415 STAT limit_maxbytes 67108864 STAT threads 1
END 通过这个数据我们就可以了解Memcached的状态了。 这些数据所代表的意义如下: pid:32u,服务器进程ID。 uptime:32u,
服务器运行时间,单位秒。 time :32u, 服务器当前的UNIX时间。 version :string, 服务器的版本号。 curr_items :32u,
服务器当前存储的内容数量 Current number of items stored by the server total_items :32u,
服务器启动以来存储过的内容总数。 bytes :64u, 服务器当前存储内容所占用的字节数。 curr_connections :32u, 连接数量。
total_connections :32u, 服务器运行以来接受的连接总数。 connection_structures:32u,
服务器分配的连接结构的数量。 cmd_get :32u, 取回请求总数。 cmd_set :32u, 存储请求总数。 get_hits :32u,
请求成功的总次数。 get_misses :32u, 请求失败的总次数。 bytes_read :64u, 服务器从网络读取到的总字节数。
bytes_written :64u, 服务器向网络发送的总字节数。 limit_maxbytes :32u, 服务器在存储时被允许使用的字节总数。
上面的描述中32u和64u表示32位和64位无符号整数,string表示是string类型数据。
在.NET中应用Memcached 有很多.NET版本的Memcached客户端程序,在这里周公使用的Enyim Memcached,可以到https://github.com/enyim/EnyimMemcached/下载最新的版本。 要想在项目中使用Memcached,需要添加对Enyim.Caching.dll的应用。除此之外,我们可能还需要在config文件中配置Memcached的信息(也可以在程序代码中指定,但那样不灵活),如下就是一个config文件配置的例子:
<?xmlversion="1.0"encoding="utf-8"?> <configuration> <configSections> <sectionGroupname="enyim.com"> <sectionname="memcached"type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/> </sectionGroup> </configSections> <enyim.comprotocol="Binary"> <memcached> <servers> <addaddress="localhost"port="11121"/> <!--<addaddress="localhost"port="11131"/> <addaddress="localhost"port="11141"/> <addaddress="localhost"port="11151"/>--> </servers> <socketPoolminPoolSize="10"maxPoolSize="100"connectionTimeout="00:00:10"deadTimeout="00:02:00"/> </memcached> </enyim.com> </configuration>
如果我们配置了多个Memcached的实例,可以想上面的注释部分那样在<servers>节点下添加多个Memcached的实例配置。 这里需要说明的是如果我们需要向Memcached中添加自定义数据类型时,我们需要将该数据类型添加上[Serializable]标记。 下面是一个Enyim Memcached的例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Enyim.Caching; using Enyim.Caching.Memcached; /* * 作者:周公(zhoufoxcn) * 日期:2011-03-24 * 原文出处:http://blog.csdn.net/zhoufoxcn 或http://zhoufoxcn.blog.51cto.com * 版权说明:本文可以在保留原文出处的情况下使用于非商业用途,周公对此不作任何担保或承诺。 * */ namespace MemcachedMonitor { [Serializable] publicclass Person { publicint UserId { get; set; } publicstring UserName { get; set; } } publicclass MemcachedDemo { privatestatic MemcachedClient client = new MemcachedClient("enyim.com/memcached"); publicvoid SetDemo() { Person person = new Person { UserId = 1, UserName = "李刚" }; //不带过期时间的存储,Memcached将根据LRU来决定过期策略 bool success=client.Store(StoreMode.Add, person.UserName, person); //带过期时间的缓存 //bool success = client.Store(StoreMode.Add, person.UserName, person, DateTime.Now.AddMinutes(10)); Console.WriteLine("存储[{0}]的结果:{1}", person.UserName, success); } publicvoid GetDemo() { Person person = client.Get<Person>("李刚"); if (person != null) { Console.WriteLine("取回[{0}]的结果——UserId:{1},UserName:{2}", "李刚", person.UserId, person.UserName); } else { Console.WriteLine("取回[{0}]失败!", "李刚"); } } publicvoid MultiGetDemo() { List<string> personNameList = new List<string>(); for (int i = 0; i < 10; i++) { personNameList.Add("李刚00" + i); } //批量获取,只通过一次网络通讯就取回所有personNameList中的指定的所有数据 IDictionary<string, object> resultList = client.Get(personNameList); Person person; foreach (KeyValuePair<string, object> item in resultList) { person = item.Value as Person; if (person != null) { Console.WriteLine("取回[{0}]的结果——UserId:{1},UserName:{2}", "李刚", person.UserId, person.UserName); } else { Console.WriteLine("取回[{0}]失败!", "李刚"); } } } } }
说明:如果需要一次从Memcached中取回多个缓存的数据,可以参考MultiGetDemo()方法,这样一来只需要一次网络通讯就可以取回全部数据,减少网络连接时间。此外,在Memcached客户端可以使用Text或者Binary协议,经过周公千万次测试比较,使用Binary协议性能略高于使用Text协议。在上面的config文件中周公就配置使用了Binary协议。 总结,使用Memcached这样的分布式缓存可以大大提高应用程序的性能,经过周公测试,正确使用Memcached可以将单台服务器的并发访问数从20提高到1000左右,也就是提高了50倍,这是一个相当客观的提升!限于篇幅,关于Memcached的更深更详细的用法没有在本篇介绍,此文算作抛砖引玉,读者可以自行参考其它相关资料。
周公
这两天和一朋友讨论这样一个问题:你认为公司的架构怎样,有哪些缺点? 其实在回答这个问题之前,有一些概念需要搞清楚,那就是什么是架构? 目前对于架构还并未有一个统一的标准及定义,所以架构的概念就会因为每个人不同而不同,如果尝试问一百人关于架构的理解,可能有一百个答案。 我开始做基础架构到现在已经有两年时间了,但对架构的理解也并不深,有时感觉无从说起,总觉的是一个无形的东西。下面我就总结下我个人对架构的理解,下面纯属个人理解。 第一:架构分层,这里我将架构分为以下两层: 1:基础架构,这也是由于架构本身的一大特点,具备基础性,它的基础性可以这样理解:通常涉及解决各种关键问题的通用方案,即重用性概念,以及涉及系统设计中影响深远的各种方案决策,影响深远说明一旦确定再次修改的代码往往过大。 示例1:各种中间件,中间件就是对某些组件的一种包装,比如我们的系统在访问数据库是需要同时支持多种类型的数据库,比如SQL SERVER,MYSQL ,ORCAL,等等,为了在各种系统访问数据时形成统一的管理,我们可以编写一个通用化的组件来解决此种问题,达到管理容易,编写简单的目的。 示例2:各种通用服务,例如为所有项目提供分布式缓存系统,所有的项目数据都可以通过它来完成数据的缓存,以加强系统性能。 示例3:面向服务概念SOA的实现,通过SOA可以使复杂的业务系统得到解耦。 示例4:项目的分层,比如分几层,每层的功能,想到之间的关系等。 2:对于全局的组织,全局的结构控制,为特定需求提供特殊解决方案,这类重在设计思维。 示例1:如何将复杂系统化分成N个子系统; 示例2:如何实现系统的非功能性需求,比如并发性,稳定性,可扩展性等等; 示例3:设计方案的选择,评估等。
下面是我对于架构的分层结构图:
的。 1:全局组织和全局结构 2:数据存取协议 3:各种组件的功能定义 4:软件的物理部署 5:设计方案的选择 6:架构评估与实现 第三:架构都有哪些重要作用 1:它是项目干系人进行交流的手段。它代表了系统公共的最高层次抽象,系统相关的很大部分人员均可将它作为互相理解的基础,以此达成共识; 2:上面说到架构具备基础性,所以具备可传递性与可重性的特点,架构层次上的重用性与代码级的重用性有本质区别,它意味着架构的决策能在相似的需求中出现在多个系统中,体现在决策,而不是实现细节; 3:它是早期设计决策的体现,这些决策比以后的开发,设计以及编码以后期的维护工作重要的多。 第四:需要注意的几个观点,为了更加正确的认识架构,需要正确对待类似下面的观点 1:框架(Framework),框架在一定程度上容易让人理解为架构,其实框架只是架构内容中的一种,代码级别的组件,不能认为搞搞框架就是架构的全部了。比如我们写的各种是间件,为某种特定需求开发的某种具备特殊功能的组件。
2:写大量的中间件是架构吗?是,但它也只属于架构的一小部分,说的准确点是框架的一部分;
3:SOA算架构吗,当然算,它就是上面我理解的基础架构一部分,但这些均只是架构的冰山一角;
4:某公司成功的架构模式能直接移置到另外一家公司的项目中吗?这个问题不能武断,我认为如果项目类型大致相同,移置的可能性会比较大,否则就需要慎重,比如我们不能将一个C/S架构上的思想直接移到到B/S架构的项目上,它们之间的差距是非常大的,即使勉强移置,也需要非常明确以后需要改进的地方,比如说性能问题,原来的架构所应用的环境对性能要求不高,所以运行良好,但如果不变的移置到互联网项目了,郁闷的事就会出来了。 第五:如何表示软件架构,可以通过非常经典的4+1视图模型来从5个不同的视角来反映系统的整体架构: 1:逻辑视图,主要体现的是系统需求,在逻辑视图中,系统会被抽象成一堆的功能抽象,这些抽象主要是来自需求。功能分解有两个功能,第一:进行功能分析;第二:可以提取不同功能模块中可重用点。 2:进程视图,它主要体现系统中的一些非功能性需求,侧重于系统运行时的特征,例如:系统的性能,稳定性,申缩性,并发性,容错能力,分布式等等。 3:物理视图,它主要考虑的是系统的部署问题,比如部署在什么样的硬件上,解决系统的拓扑结构,通信等问题,比如数据库的备份容灾方案等。 4:开发视图,主要解决系统的组织以及管理,比如如何划分子系统,如何编写要重用性组件等。 5:场景视图,它联系以上四个视图,是系统活动的重要抽象,它用来解决在特定场景上分析一个特定的视图。
下面是它们的关系图
总结:架构是一个大概念,不会有统一的定义,每个公司每个项目都会对架构产生影响,只有根据实际情况出发,才有可能开发出最适合自己公司项目的架构模式。
2011-10-23 C#类特性和属性特性 using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using System.Reflection; namespace ConsoleApplication6 { /// <summary> /// AttributeTargets.Class可以对类应用属性 /// Inherited能否由派生类或重写成员继承 /// AllowMultiple能否为一个程序元素指定多个指示属性实例 /// 也就是说AllowMultiple=false 对于一个类型,该特性只能用一次 /// 若一个Class类型前面出现多个TableAttribute,则会出现编译错误 /// </summary> [AttributeUsage(AttributeTargets.Class,Inherited=true,AllowMultiple=false)] public class TableAttribute : Attribute { private string _tableName; public TableAttribute() { } public TableAttribute(string tableName) { this._tableName = tableName; } public string TableName { get { return this._tableName; } set { this._tableName = value; } } } /// <summary> /// 列特性 /// AttributeTargets.Property可以对属性应用特性 /// </summary> [AttributeUsage(AttributeTargets.Property,Inherited=false,AllowMultiple=false)] public class ColumAttribute : Attribute { private string _columName; private DbType _dbType; public ColumAttribute() { } public ColumAttribute(string columName) { this._columName = columName; } public ColumAttribute(string columName, DbType dbType) { this._columName = columName; this._dbType = dbType; } public string ColumName { get { return this._columName; } set { this._columName = value; } } public DbType DbTypeAttr { get { return this._dbType; } set { _dbType = value; } } } [Table("User")] public class User { [Colum("userId",DbType.Int32)] public int UserId { get; set; } [Colum("userName", DbType.String)] public string UserName { get; set; } } class Program { static void Main(string[] args) { User u = new User(); u.UserId = 6; u.UserName = "allen"; Type myObjType = u.GetType(); Dictionary<string,string> columName = new Dictionary<string,string>(); //获取自定义特性 object temp = myObjType.GetCustomAttributes(typeof(TableAttribute),false).First(); TableAttribute myAttr = temp as TableAttribute; Console.WriteLine("表名:{0}", myAttr.TableName); Console.WriteLine("列的名称和值:"); foreach (PropertyInfo pi in myObjType.GetProperties()) { object attr = pi.GetCustomAttributes(false).First(); ColumAttribute cattr = attr as ColumAttribute; Console.WriteLine("{0}:{1}",cattr.ColumName,pi.GetValue(u,null)); } Console.ReadKey(); } } }
转载自:http://www.cnblogs.com/ITangle/archive/2011/12/11/2283901.html
Nginx网络负载均衡,负载均衡,网络负载,网络均衡,布布扣,bubuko.com
原文:http://www.cnblogs.com/wzq806341010/p/3571513.html