本节就聊聊采用Nginx负载均衡之后碰到的问题:
  • Session问题
  • 文件上传下载

通常解决服务器负载问题,都会通过多服务器分载来解决。常见的解决方案有:

  • 网站入口通过分站链接负载(天空软件站,华军软件园等)
  • DNS轮询
  • F5物理设备
  • Nginx等轻量级架构

那我们看看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: weight=;
server 172.16.125.76: down;
server 172.16.0.18: max_fails= fail_timeout=30s;
server 172.16.0.18: backup;
} upstream www.test2.com {
server 172.16.0.21:;
server 192.168.76.98:;
} server {
listen ;
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 ;
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;
}
}
按 Ctrl+C 复制代码

当有请求到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或凭据保存数据库中
  • nginx ip_hash 保持同一IP的请求都是指定到固定的一台服务器

第一种缓存的方式比较理想,缓存的效率也比较高。但是每一台请求服务器都去访问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 简介

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 前必须了解的事项

  1. 目前官方 Nginx 并不支持 Windows,您只能在包括 Linux、UNIX、BSD 系统下安装和使用;
  2. Nginx 本身只是一个 HTTP 和反向代理服务器,它无法像 Apache 一样通过安装各种模块来支持不同的页面脚本,例如 PHP、CGI 等;
  3. Nginx 支持简单的负载均衡和容错;
  4. 支持作为基本 HTTP 服务器的功能,例如日志、压缩、Byte ranges、Chunked responses、SSL、虚拟主机等等,应有尽有。

在 Linux 下安装 Nginx

为了确保能在 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 进程本身进行控制的。 Nginx 的参数包括有如下几个:

-c <path_to_config>:使用指定的配置文件而不是 conf 目录下的 nginx.conf 。

-t:测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。

-v:显示 nginx 版本号。

-V:显示 nginx 的版本号以及编译环境信息以及编译时的参数。

例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令

sbin/nginx – t – c conf/nginx2.conf

通过信号对 Nginx 进行控制

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 重新加载配置。

配置 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;
}
}
}

Nginx 监控

上面是一个实际网站的配置实例,其中灰色文字为配置说明。上述配置中,首先我们定义了一个 location ~ ^/NginxStatus/,这样通过 http://localhost/NginxStatus/ 就可以监控到 Nginx 的运行信息,显示的内容如下:

Active connections: 70
server accepts handled requests
14553819 14553819 19239266
Reading: 0 Writing: 3 Waiting: 67

NginxStatus 显示的内容意思如下:

  • active connections – 当前 Nginx 正处理的活动连接数。
  • server accepts handled requests -- 总共处理了 14553819 个连接 , 成功创建 14553819 次握手 ( 证明中间没有失败的 ), 总共处理了 19239266 个请求 ( 平均每次握手处理了 1.3 个数据请求 )。
  • reading -- nginx 读取到客户端的 Header 信息数。
  • writing -- nginx 返回给客户端的 Header 信息数。
  • waiting -- 开启 keep-alive 的情况下,这个值等于 active - (reading + writing),意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接。

静态文件处理

通过正则表达式,我们可让 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

51cto

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 的版本号以及编译情况信息以及编译时的参数。

比方我们要测试某个设置装备摆设文件是否誊写准确,我们可以利用以下号令

sbin/nginx – t – c conf/nginx2.conf

经由过程旌旗灯号对 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 从头加载设置装备摆设。

设置装备摆设 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; } } }

Nginx 监控

上 面是一个现实网站的设置装备摆设实例,此中灰色笔墨为设置装备摆设申明。上述设置装备摆设中,起首我们界说了一个 location ~ ^/NginxStatus/,如许经由过程 http://localhost/NginxStatus/ 就可以监控到 Nginx 的运行信息,表现的内容如下:

Active connections: 70 server accepts handled requests 14553819 14553819 19239266 Reading: 0 Writing: 3 Waiting: 67

NginxStatus 表现的内容意思如下:

  • active connections – 当前 Nginx 正处置的勾当毗连数。
  • server accepts handled requests — 统共处置了 14553819 个毗连 , 乐成建立 14553819 次握手 ( 证实中心没有失败的 ), 统共处置了 19239266 个恳求 ( 均匀每次握手处置了 1.3 个数据恳求 )。
  • reading — nginx 读取到客户真个 Header 信息数。
  • writing — nginx 返回给客户真个 Header 信息数。
  • waiting — 开启 keep-alive 的环境下,这个值即是 active – (reading + writing),意思便是 Nginx 已经处置完正在等待下一次恳求指令的驻留毗连。

静态文件处置

经由过程正则表达式,我们可让 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 。

 
 
 
 

如果你关注过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=""/>
<!--<addaddress="localhost"port=""/>
<addaddress="localhost"port=""/>
<addaddress="localhost"port=""/>-->
</servers>
<socketPoolminPoolSize=""maxPoolSize=""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 = , 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 = ; i < ; 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 业务场景图从上图可以看出,就是一个电子商务网站常见的支付、支付的后续处理,这样一个业务场景。支持多种支付方式,目前包括银联、支付宝,还有平台账户。平台Read More
 
 
 
 

这两天和一朋友讨论这样一个问题:你认为公司的架构怎样,有哪些缺点?           其实在回答这个问题之前,有一些概念需要搞清楚,那就是什么是架构?           目前对于架构还并未有一个统一的标准及定义,所以架构的概念就会因为每个人不同而不同,如果尝试问一百人关于架构的理解,可能有一百个答案。           我开始做基础架构到现在已经有两年时间了,但对架构的理解也并不深,有时感觉无从说起,总觉的是一个无形的东西。下面我就总结下我个人对架构的理解,下面纯属个人理解。           第一:架构分层,这里我将架构分为以下两层:                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:场景视图,它联系以上四个视图,是系统活动的重要抽象,它用来解决在特定场景上分析一个特定的视图。

下面是它们的关系图           

总结:架构是一个大概念,不会有统一的定义,每个公司每个项目都会对架构产生影响,只有根据实际情况出发,才有可能开发出最适合自己公司项目的架构模式。

--

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 = ; 

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

最新文章

  1. 2014 UESTC暑前集训图论专题解题报告
  2. ios UITextView 计算文字内容大小
  3. Mishka and Divisors[CodeForces Round #365 Div.2]
  4. android view holder 优化
  5. iOS - Threads 多线程
  6. ueditor:原谅我这一生不羁放纵爱独特
  7. ASP.NET CompareValidator 控件在VS2012中出错的问题
  8. Javascript进阶篇——(流程控制语句)笔记整理
  9. poj 2965
  10. 最新 Spring 4.2.2 集成 Quartz Scheduler 2.2.2 任务调度示例
  11. redis中键的生存时间(expire)
  12. Dynamics CRM2016 使用web api来创建注释时的注意事项
  13. 利用java反射机制实现读取excel表格中的数据
  14. IE兼容事件绑定V1.0
  15. 【GIT】git 删除本地分支和远程分支、本地代码回滚和远程代码库回滚
  16. 【RL-TCPnet网络教程】第18章 BSD Sockets基础知识
  17. 【DFS】困难的串
  18. css学习_div+css布局
  19. python中定义的颜色
  20. NYOJ 一笔画

热门文章

  1. 微信公众号开发不能使用session原因
  2. C语言 - sizeof和strlen的区别
  3. MySQL-5.6.13解压版(zip版)安装配置教程
  4. Comet OJ - Contest #3 D 可爱的菜菜子 线段树+线性基
  5. jeecg中自定义dialog,实现窗体的弹出
  6. jQuery动画之停止动画
  7. PTA 重构二叉树
  8. Work Queues(工作队列)
  9. 19.Python转义字符及用法
  10. Chrome 神器,神奇的技巧