ubuntu snmpwalk error

Ansible 回复了问题 • 2 人关注 • 2 个回复 • 1176 次浏览 • 2015-09-09 16:06 • 来自相关话题

有关于ffmpeg和ffmpeg-PHP的相关安装问题

mark 发表了文章 • 1 个评论 • 797 次浏览 • 2015-09-06 14:50 • 来自相关话题

在安装ffmpeg的时候是用yum装的,而在安装ffmpeg-php是在官网下载的最新的源码包,在./configure是发生了报错报错内容:ffmpeg headers not found.**** 

在我进行排查处理时发现是由于两个软件包的版本对应不一致
 
个人感觉yum装的老版本他的配置文件放置在其他的A目录,而在官网下载的ffmpeg-php他会去B目录找配置文件找不到就会报错
 
我的解决方法就是在下载一个新的ffmpeg软件包再重新安装代码如下:yum install -y svn
svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
cd ffmpeg
./configure --enbale-shared
make && make install然后在安装ffmpeg-php时make是报错,报错内容:make: [b][i] [ffmpeg_frame.lo] Error 1解决方法mv ffmpeg_frame.loT ffmpeg_frame.lo在解决完这个时候make有报错了:make: [/b][/i] [ffmpeg_frame.lo] Error 1解决方法则修改ffmpeg_frame.c,将3处的PIX_FMT_RGBA32 更改为PIX_FMT_RGB32即可。sed -i 's/PIX_FMT_RGBA32/PIX_FMT_RGB32/g' ffmpeg_frame.c我的运气可能比较差在我以为可以安装完成时第三个报错也出现了:make: *** [ffmpeg_movie.lo] Error 1解决方法:vim ffmpeg_movie.c
row 311: list_entry [i]le; 改为zend_rsrc_list_entry [/i]le;
row 346: list_entry new_le;改为 zend_rsrc_list_entry new_le;
row 360: hashkey_length+1, (void [i])&new_le, sizeof(list_entry),改为hashkey_length+1, (void [/i])&new_le,sizeof(zend_rsrc_list_entry),最后安装完成。
 
 
  查看全部
在安装ffmpeg的时候是用yum装的,而在安装ffmpeg-php是在官网下载的最新的源码包,在./configure是发生了报错报错内容:ffmpeg headers not found.**** 

在我进行排查处理时发现是由于两个软件包的版本对应不一致
 
个人感觉yum装的老版本他的配置文件放置在其他的A目录,而在官网下载的ffmpeg-php他会去B目录找配置文件找不到就会报错
 
我的解决方法就是在下载一个新的ffmpeg软件包再重新安装代码如下:
yum install -y svn
svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
cd ffmpeg
./configure --enbale-shared
make && make install
然后在安装ffmpeg-php时make是报错,报错内容:
make: [b][i] [ffmpeg_frame.lo] Error 1
解决方法
mv ffmpeg_frame.loT ffmpeg_frame.lo
在解决完这个时候make有报错了:
make: [/b][/i] [ffmpeg_frame.lo] Error 1
解决方法则修改ffmpeg_frame.c,将3处的PIX_FMT_RGBA32 更改为PIX_FMT_RGB32即可。
sed -i 's/PIX_FMT_RGBA32/PIX_FMT_RGB32/g' ffmpeg_frame.c
我的运气可能比较差在我以为可以安装完成时第三个报错也出现了:
make: *** [ffmpeg_movie.lo] Error 1
解决方法:
vim ffmpeg_movie.c
row 311: list_entry [i]le; 改为zend_rsrc_list_entry [/i]le;
row 346: list_entry new_le;改为 zend_rsrc_list_entry new_le;
row 360: hashkey_length+1, (void [i])&new_le, sizeof(list_entry),改为hashkey_length+1, (void [/i])&new_le,sizeof(zend_rsrc_list_entry),
最后安装完成。
 
 
 

基础拾遗-Apache Options指令详解

采菊篱下 发表了文章 • 0 个评论 • 636 次浏览 • 2015-09-04 19:44 • 来自相关话题

Options指令是Apache配置文件中一个比较常见也比较重要的指令,Options指令可以在Apache服务器核心配置(server config)、虚拟主机配置(virtual host)、特定目录配置(directory)以及.htaccess文件中使用。Options指令的主要作用是控制特定目录将启用哪些服务器特性。
 
Options指令常见的配置示例代码如下:<Directory />
#指定根目录"/"启用Indexes、FollowSymLinks两种特性。
Options Indexes FollowSymLinks
AllowOverride all
Order allow,deny
Allow from all
</Directory>Options指令的完整语法为:Options [+|-]option [[+|-]option] ...。简而言之,Options指令后可以附加指定多种服务器特性,特性选项之间以空格分隔。下面我们来看看Options指令后可以附加的特性选项的具体作用及含义(Apache配置中的内容均不区分大小写):All
表示除MultiViews之外的所有特性。这也是Options指令的默认设置。

None
表示不启用任何的服务器特性。

FollowSymLinks
服务器允许在此目录中使用符号连接。如果该配置选项位于<Location>配置段中,将会被忽略。

Indexes
如果输入的网址对应服务器上的一个文件目录,而此目录中又没有DirectoryIndex指令(例如:DirectoryIndex index.html index.php),那么服务器会返回由mod_autoindex模块生成的一个格式化后的目录列表,并列出该目录下的所有文件(如下图)。


MultiViews
允许使用mod_negotiation模块提供内容协商的"多重视图"。简而言之,如果客户端请求的路径可能对应多种类型的文件,那么服务器将根据客户端请求的具体情况自动选择一个最匹配客户端要求的文件。例如,在服务器站点的file文件夹下中存在名为hello.jpg和hello.html的两个文件,此时用户输入Http://localhost/file/hello,如果在file文件夹下并没有hello子目录,那么服务器将会尝试在file文件夹下查找形如hello.*的文件,然后根据用户请求的具体情况返回最匹配要求的hello.jpg或者hello.html。

SymLinksIfOwnerMatch
服务器仅在符号连接与目标文件或目录的所有者具有相同的用户ID时才使用它。简而言之,只有当符号连接和符号连接指向的目标文件或目录的所有者是同一用户时,才会使用符号连接。如果该配置选项位于<Location>配置段中,将会被忽略。

ExecCGI
允许使用mod_cgi模块执行CGI脚本。

Includes
允许使用mod_include模块提供的服务器端包含功能。

IncludesNOEXEC
允许服务器端包含,但禁用"#exec cmd"和"#exec cgi"。但仍可以从ScriptAlias目录使用"#include virtual"虚拟CGI脚本。此外,比较细心的读者应该注意到,Options指令语法允许在配置选项前加上符号"+"或者"-",那么这到底是什么意思呢。

实际上,Apache允许在一个目录配置中设置多个Options指令。不过,一般来说,如果一个目录被多次设置了Options,则指定特性数量最多的一个Options指令会被完全接受(其它的被忽略),而各个Options指令之间并不会合并。但是如果我们在可选配置项前加上了符号"+"或"-",那么表示该可选项将会被合并。所有前面加有"+"号的可选项将强制覆盖当前的可选项设置,而所有前面有"-"号的可选项将强制从当前可选项设置中去除。你可以参考下面的例子:#示例1
<Directory /web/file>
Options Indexes FollowSymLinks
</Directory>

<Directory /web/file/image>
Options Includes
</Directory>
#目录/web/file/image只会被设置Includes特性#示例2
<Directory /web/file>
Options Indexes FollowSymLinks
</Directory>

<Directory /web/file/image>
Options +Includes -Indexes
</Directory>
#目录/web/file/image将会被设置Includes、FollowSymLinks两种特性

备注1:混合使用前面带"+"/"-"和前面不带"+"/"-"的同一可选项,可能会导致出现意料之外的结果。


备注2:使用-IncludesNOEXEC或-Includes时,不论前面如何设置,都会完全禁用服务器端包含。

转载出处:原文地址
  查看全部
Options指令是Apache配置文件中一个比较常见也比较重要的指令,Options指令可以在Apache服务器核心配置(server config)、虚拟主机配置(virtual host)、特定目录配置(directory)以及.htaccess文件中使用。Options指令的主要作用是控制特定目录将启用哪些服务器特性。
 
Options指令常见的配置示例代码如下:
<Directory />
#指定根目录"/"启用Indexes、FollowSymLinks两种特性。
Options Indexes FollowSymLinks
AllowOverride all
Order allow,deny
Allow from all
</Directory>
Options指令的完整语法为:Options [+|-]option [[+|-]option] ...。简而言之,Options指令后可以附加指定多种服务器特性,特性选项之间以空格分隔。下面我们来看看Options指令后可以附加的特性选项的具体作用及含义(Apache配置中的内容均不区分大小写):
All
表示除MultiViews之外的所有特性。这也是Options指令的默认设置。

None
表示不启用任何的服务器特性。

FollowSymLinks
服务器允许在此目录中使用符号连接。如果该配置选项位于<Location>配置段中,将会被忽略。

Indexes
如果输入的网址对应服务器上的一个文件目录,而此目录中又没有DirectoryIndex指令(例如:DirectoryIndex index.html index.php),那么服务器会返回由mod_autoindex模块生成的一个格式化后的目录列表,并列出该目录下的所有文件(如下图)。
options1.png
MultiViews
允许使用mod_negotiation模块提供内容协商的"多重视图"。简而言之,如果客户端请求的路径可能对应多种类型的文件,那么服务器将根据客户端请求的具体情况自动选择一个最匹配客户端要求的文件。例如,在服务器站点的file文件夹下中存在名为hello.jpg和hello.html的两个文件,此时用户输入Http://localhost/file/hello,如果在file文件夹下并没有hello子目录,那么服务器将会尝试在file文件夹下查找形如hello.*的文件,然后根据用户请求的具体情况返回最匹配要求的hello.jpg或者hello.html。

SymLinksIfOwnerMatch
服务器仅在符号连接与目标文件或目录的所有者具有相同的用户ID时才使用它。简而言之,只有当符号连接和符号连接指向的目标文件或目录的所有者是同一用户时,才会使用符号连接。如果该配置选项位于<Location>配置段中,将会被忽略。

ExecCGI
允许使用mod_cgi模块执行CGI脚本。

Includes
允许使用mod_include模块提供的服务器端包含功能。

IncludesNOEXEC
允许服务器端包含,但禁用"#exec cmd"和"#exec cgi"。但仍可以从ScriptAlias目录使用"#include virtual"虚拟CGI脚本。
此外,比较细心的读者应该注意到,Options指令语法允许在配置选项前加上符号"+"或者"-",那么这到底是什么意思呢。

实际上,Apache允许在一个目录配置中设置多个Options指令。不过,一般来说,如果一个目录被多次设置了Options,则指定特性数量最多的一个Options指令会被完全接受(其它的被忽略),而各个Options指令之间并不会合并。但是如果我们在可选配置项前加上了符号"+"或"-",那么表示该可选项将会被合并。所有前面加有"+"号的可选项将强制覆盖当前的可选项设置,而所有前面有"-"号的可选项将强制从当前可选项设置中去除。你可以参考下面的例子:
#示例1
<Directory /web/file>
Options Indexes FollowSymLinks
</Directory>

<Directory /web/file/image>
Options Includes
</Directory>
#目录/web/file/image只会被设置Includes特性
#示例2
<Directory /web/file>
Options Indexes FollowSymLinks
</Directory>

<Directory /web/file/image>
Options +Includes -Indexes
</Directory>
#目录/web/file/image将会被设置Includes、FollowSymLinks两种特性


备注1:混合使用前面带"+"/"-"和前面不带"+"/"-"的同一可选项,可能会导致出现意料之外的结果。



备注2:使用-IncludesNOEXEC或-Includes时,不论前面如何设置,都会完全禁用服务器端包含。


转载出处:原文地址
 

Directory index forbidden by Options directive

采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 1293 次浏览 • 2015-09-04 19:30 • 来自相关话题

mod_include: Options +Includes (or IncludesNoExec) wasn't set, INCLUDES filter removed

OpenSkill 回复了问题 • 2 人关注 • 1 个回复 • 1264 次浏览 • 2015-09-04 19:11 • 来自相关话题

Ubuntu怎么处理开机自启动

Kevin 回复了问题 • 2 人关注 • 2 个回复 • 1400 次浏览 • 2015-08-31 09:05 • 来自相关话题

Zabbix监控之Mysql

Ansible 发表了文章 • 3 个评论 • 1055 次浏览 • 2015-08-25 00:28 • 来自相关话题

      使用go语言写了一个采集mysql性能的小程序,通过SDK连接mysql数据库,采集数据库性能指标,同时采集远程数据库的性能,大家可试用一下,欢迎提出修改意见和建议

被监控端设置

监控下载:
   Linux:
                mymon_x86.tar.gz
                mymon_x64.tar.gz
   Windows:
                mymon_windows_amd64.zip
 
Windows:
      下载解压后放在c盘,修改agentd.conf文件,执行脚本路径为:c:\mymon\mymon.exe


      重启agentd即可

Linux:
      修改zabbix agentd配置文件(具体位置根据自身情况设置),添加keyvi /usr/local/zabbix/etc/zabbix_agentd.conf      添加如下:




      添加好之后执行mkdir -p /usr/local/zabbix/bin/mysql/
cd /usr/local/zabbix/bin/mysql/
wget http://dl.cactifans.org/tools/mymon_x64.tar.gz
tar zxvf mymon_x64.tar.gz
chmod a+x mymon      同时编辑cfg.json配置文件,设置要监控数据库的连接参数vi /usr/local/zabbix/bin/mysql/cfg.json      文件内容如下{
"mysql": {
"username": "root",
"password": "123456",
"host": "localhost",
"port": 3306
},
"sever": {
"log": "/tmp/mon.log"
}
}      登录数据库的账号,密码等信息,log项目不用设置,默认即可
      设置好之后重启zabixx agentservice zabbix-agent restart

zabbix服务端设置

      测试agent是否工作正常/usr/local/bin/zabbix_get -s 192.168.7.186 -k mysql.status[GlobalStatus,Uptime]      如果有一下回显,表示工作正常[root@vm153 ~]# /usr/local/bin/zabbix_get -s 192.168.7.186 -k mysql.status[GlobalStatus,Uptime]
12364726
[root@vm153 ~]#      导入模版:zabbix_mysql_templates.xml
      并关联到主机
      效果:




      参数:




      PS:可自行添加对应key可监控项目,模版自带了几种,脚本包括800多项目



具体更具key定义,括号内第一项为key类型,分GlobalStatus和GlobalVariables二种,后面的数值为在mysql里执行“SHOW /!50001 GLOBAL / STATUS”和“SHOW /!50001 GLOBAL / VARIABLES”,对应的key,注意有些数值为固定数值,有些key的类型为每秒速差,自行添加.原文地址 查看全部
      使用go语言写了一个采集mysql性能的小程序,通过SDK连接mysql数据库,采集数据库性能指标,同时采集远程数据库的性能,大家可试用一下,欢迎提出修改意见和建议


被监控端设置


监控下载:
   Linux:
                mymon_x86.tar.gz
                mymon_x64.tar.gz
   Windows:
                mymon_windows_amd64.zip
 
Windows:
      下载解压后放在c盘,修改agentd.conf文件,执行脚本路径为:
c:\mymon\mymon.exe


      重启agentd即可

Linux:
      修改zabbix agentd配置文件(具体位置根据自身情况设置),添加key
vi /usr/local/zabbix/etc/zabbix_agentd.conf
      添加如下:
zmy4.png

      添加好之后执行
mkdir -p /usr/local/zabbix/bin/mysql/
cd /usr/local/zabbix/bin/mysql/
wget http://dl.cactifans.org/tools/mymon_x64.tar.gz
tar zxvf mymon_x64.tar.gz
chmod a+x mymon
      同时编辑cfg.json配置文件,设置要监控数据库的连接参数
vi /usr/local/zabbix/bin/mysql/cfg.json
      文件内容如下
{
"mysql": {
"username": "root",
"password": "123456",
"host": "localhost",
"port": 3306
},
"sever": {
"log": "/tmp/mon.log"
}
}
      登录数据库的账号,密码等信息,log项目不用设置,默认即可
      设置好之后重启zabixx agent
service zabbix-agent restart


zabbix服务端设置


      测试agent是否工作正常
/usr/local/bin/zabbix_get -s 192.168.7.186 -k mysql.status[GlobalStatus,Uptime]
      如果有一下回显,表示工作正常
[root@vm153 ~]#  /usr/local/bin/zabbix_get -s 192.168.7.186 -k mysql.status[GlobalStatus,Uptime]
12364726
[root@vm153 ~]#
      导入模版:zabbix_mysql_templates.xml
      并关联到主机
      效果:
zmy1.png

      参数:
zmy2.png

      PS:可自行添加对应key可监控项目,模版自带了几种,脚本包括800多项目
zmy3.png
具体更具key定义,括号内第一项为key类型,分GlobalStatus和GlobalVariables二种,后面的数值为在mysql里执行“SHOW /!50001 GLOBAL / STATUS”和“SHOW /!50001 GLOBAL / VARIABLES”,对应的key,注意有些数值为固定数值,有些key的类型为每秒速差,自行添加.
原文地址

PDO Exception could not find driver

Ansible 回复了问题 • 2 人关注 • 1 个回复 • 1000 次浏览 • 2015-08-24 16:01 • 来自相关话题

CentOS部署 salt报错

Ansible 回复了问题 • 2 人关注 • 1 个回复 • 1155 次浏览 • 2015-08-21 21:05 • 来自相关话题

浅谈可伸缩系统的架构

Ansible 发表了文章 • 0 个评论 • 674 次浏览 • 2015-08-21 00:18 • 来自相关话题

      最近,阅读了Will Larson的文章Introduction to Architecting System for Scale,感觉很有价值。作者分享了他在Yahoo!与Digg收获的设计可伸缩系统的架构经验。在我过往的架构经验中,由于主要参与开发企业软件系统,这种面向企业内部的软件系统通常不会有太大的负载量,太多的并发量,因而对于系统的可伸缩性考虑较少。大体而言,只要在系统部署上考虑集群以及负载均衡即可。本文给了我很多启发,现把本文的主要内容摘译出来,并结合自己对此的理解。

     Larson首先认为,一个理想的系统,对于容量(Capacity)的增长应该与添加的硬件数是线性的关系。换言之,如果系统只有一台服务器,在增加了另一台同样的机器后,容量应该翻倍。以此类推。这种线性的容量伸缩方式,通常被称之为水平伸缩"Horizontal Scalability"。

     在设计一个健壮的系统时,自然必须首要考虑失败的情况。Larson认为,一个理想的系统是当失去其中一台服务器的时候,系统不会崩溃。当然,对应而言,失去一台服务器也会导致容量的响应线性减少。这种情况通常被称为冗余"Redundancy"。

负载均衡

     无论是水平伸缩还是冗余,都可以通过负载均衡来实现。负载均衡就好似一个协调请求的调停者,它会根据集群中机器的当前负载,合理的分配发往Web服务器的请求,以达到有效利用集群中各台机器资源的目的。显然,这种均衡器应该介于客户端与Web服务器之间,如下图所示:




      本文提到了实现负载均衡的几种方法。其一是Smart Client,即将负载均衡的功能添加到数据库(以及缓存或服务)的客户端中。这是一种通过软件来实现负载均衡的方式,它的缺点是方案会比较复杂,不够健壮,也很难被重用(因为协调请求的逻辑会混杂在业务系统中)。对此,Larson在文章以排比的方式连续提出问题,以强化自己对此方案的不认可态度:Is it attractive because it is the simplest solution? Usually, no. Is it seductive because it is the most robust? Sadly, no. Is it alluring because it’ll be easy to reuse? Tragically, no.      第二种方式是采用硬件负载均衡器,例如Citrix NetScaler。不过,购买硬件的费用不菲,通常是一些大型公司才会考虑此方案。

     如果既不愿意承受Smart Client的痛苦,又不希望花费太多费用去购买硬件,那就可以采用一种混合(Hybird)的方式,称之为软件负载均衡器(Software Load Balancer)。Larson提到了HAProxy。它会运行在本地,需要负载均衡的服务都会在本地中得到均衡和协调。

缓存 

     为了减轻服务器的负载,还需要引入缓存。文章给出了常见的对缓存的分类,分别包括:预先计算结果(precalculating result,例如针对相关逻辑的前一天的访问量)、预先生成昂贵的索引(pre-generating expensive indexes,例如用户点击历史的推荐)以及在更快的后端存储频繁访问的数据的副本(例如Memcached、Redis、Mongodb)。

应用缓存

      提供缓存的方式可以分为应用缓存和数据库缓存。此二者各擅胜场。应用缓存通常需要将处理缓存的代码显式地集成到应用代码中。这就有点像使用代理模式来为真实对象提供缓存。首先检查缓存中是否有需要的数据,如果有,就从缓存直接返回,否则再查询数据库。至于哪些值需要放到缓存中呢?有诸多算法,例如根据最近访问的,或者根据访问频率。使用Memcached的代码如下所示:key = "user.%s" % user_id
user_blob = memcache.get(key)
if user_blob is None:
user = mysql.query("SELECT * FROM users WHERE user_id=\"%s\"", user_id)
if user:
memcache.set(key, json.dumps(user))
return user
else:
return json.loads(user_blob)

数据库缓存

     数据库缓存对于应用代码没有污染,一些天才的DBA甚至可以在不修改任何代码的情况下,通过数据库调优来改进系统性能。例如通过配置Cassandra行缓存。

内存缓存

      为了提高性能,缓存通常是存储在内存中。常见的内存缓存包括Memcached和Redis。不过采用这种方式仍然需要合理的权衡。我们不可能一股脑儿的将所有数据都存放在内存中,虽然这会极大地改善性能,但比较起磁盘存储而言,RAM的代价更昂贵,同时还会影响系统的健壮性,因为内存中的数据没有持久化,容易丢失。正如之前提到的,我们应该将需要的数据放入缓存,通常的算法是least recently used,即LRU。

CDN

      提高性能,降低Web服务器负载的另一种常见做法是将静态媒体放入CDN(Content Distribution Network)中。如下图所示:




      CDN可以有效地分担Web服务器的压力,使得应用服务器可以专心致志地处理动态页面;同时,CDN还可以通过地理分布来提高响应请求的性能。在设置了CDN后,当系统接收到请求时,首先会询问CDN以获得请求中需要的静态媒体(通常会通过HTTP Header来配置CDN能够缓存的内容)。如果请求的内容不可用,CDN会查询服务器以获得该文件,并在CDN本地进行缓存,最后再提供给请求者。如果当前网站并不大,引入CDN的效果不明显时,可以考虑暂不使用CDN,在将来可以通过使用一些轻量级的HTTP服务器如Nginx,为静态媒体分出专门的子域名如static.domain.com来提供服务。

缓存失效

      引入缓存所带来的问题是如何保证真实数据与缓存数据之间的一致性。这一问题通常被称之为缓存失效(Cache Invalidation)。从高屋建瓴的角度来讲,解决这一问题的办法无非即使更新缓存中的数据。一种做法是直接将新值写入缓存中(通常被称为write-through cache);另一种做法是简单地删除缓存中的值,在等到下一次读缓存值的时候再生成。

      整体而言,要避免缓存实效,可以依赖于数据库缓存,或者为缓存数据添加有效期,又或者在实现应用程序逻辑时,尽量考虑避免此问题。例如不直接使用DELETE FROM a WHERE…来删除数据,而是先查询符合条件的数据,再使得缓存中对应的数据失效,继而根据其主键显式地删除这些行。

Off-Line处理

     这篇文章还提到了Off-Line的处理方式,即通过引入消息队列的方式来处理请求。事实上,在大多数企业软件系统中,这种方式也是较为常见的做法。在文章《案例分析:基于消息的分布式架构》中,较为详细地介绍了这种架构。在引入消息队列后,Web服务器会充当消息的发布者,而在消息队列的另一端可以根据需要提供消费者Consumer。如下图所示。对于Off-Line的任务是否执行完毕,通常可以通过轮询或回调的方式来获知。




      为了更好地提高代码可读性,可以在公开的接口定义中明确地标示该任务是On-Line还是Off-Line。
      引入Message Queue,可以极大地缓解Web服务器的压力,因为它可以将耗时较长的任务转到专门的机器上去执行。

     此外,通过引入定时任务,也可以有效地利用Web服务器的空闲时间来处理后台任务。例如,通过Spring Batch Job来执行每日、每周或者每月的定时任务。如果需要多台机器去执行这些定时任务,可以引入Spring提供的Puppet来管理这些服务器。Puppet提供了可读性强的声明性语言来完成对机器的配置。

Map-Reduce

     对于大数据的处理,自然可以引入Map-Reduce。为整个系统专门引入一个Map-Reduce层来处理数据是有必要的。相对于使用SQL数据库作为数据中心的方式,Map-Reduce对可伸缩性的支持更好。Map-Reduce可以与任务的定时机制结合起来。如下图所示:





平台层

      Larson认为,大多数系统都是Web应用直接与数据库通信,但如果能加入一个平台层(Platform Layer),或许会更好。




      首先,将平台与Web应用分离,使得它们可以独立地进行伸缩。例如需要添加一个新的API,就可以添加新的平台服务器,而无需增加Web服务器。要知道,在这样一个独立的物理分层架构中,不同层次对服务器的要求是不一样的。例如,对于数据库服务器而言,由于需要频繁地对磁盘进行I/O操作,因此应保证数据库服务器的IO性能,如尽量使用固态硬盘。而对于Web服务器而言,则对CPU的要求比较高,尽可能采用多核CPU。

     其次,增加一个额外的平台层,可以有效地提高系统的可重用性。例如我们可以将一些与系统共有特性以及横切关注点的内容(如对缓存的支持,对数据库的访问等功能)抽取到平台层中,作为整个系统的基础设施(Infrastructure)。尤其对于产品线系统而言,这种架构可以更好地为多产品提供服务。

     最后,这种架构也可能对跨团队开发带来好处。平台可以抽离出一些与产品无关的接口,从而隐藏其具体实现的细节。如果划分合理,并能设计出相对稳定的接口,就可以使得各个团队可以并行开发。例如可以专门成立平台团队,致力于对平台的实现以及优化。
原文地址 查看全部
jg1.jpg

      最近,阅读了Will Larson的文章Introduction to Architecting System for Scale,感觉很有价值。作者分享了他在Yahoo!与Digg收获的设计可伸缩系统的架构经验。在我过往的架构经验中,由于主要参与开发企业软件系统,这种面向企业内部的软件系统通常不会有太大的负载量,太多的并发量,因而对于系统的可伸缩性考虑较少。大体而言,只要在系统部署上考虑集群以及负载均衡即可。本文给了我很多启发,现把本文的主要内容摘译出来,并结合自己对此的理解。

     Larson首先认为,一个理想的系统,对于容量(Capacity)的增长应该与添加的硬件数是线性的关系。换言之,如果系统只有一台服务器,在增加了另一台同样的机器后,容量应该翻倍。以此类推。这种线性的容量伸缩方式,通常被称之为水平伸缩"Horizontal Scalability"。

     在设计一个健壮的系统时,自然必须首要考虑失败的情况。Larson认为,一个理想的系统是当失去其中一台服务器的时候,系统不会崩溃。当然,对应而言,失去一台服务器也会导致容量的响应线性减少。这种情况通常被称为冗余"Redundancy"。


负载均衡


     无论是水平伸缩还是冗余,都可以通过负载均衡来实现。负载均衡就好似一个协调请求的调停者,它会根据集群中机器的当前负载,合理的分配发往Web服务器的请求,以达到有效利用集群中各台机器资源的目的。显然,这种均衡器应该介于客户端与Web服务器之间,如下图所示:
jg2.png

      本文提到了实现负载均衡的几种方法。其一是Smart Client,即将负载均衡的功能添加到数据库(以及缓存或服务)的客户端中。这是一种通过软件来实现负载均衡的方式,它的缺点是方案会比较复杂,不够健壮,也很难被重用(因为协调请求的逻辑会混杂在业务系统中)。对此,Larson在文章以排比的方式连续提出问题,以强化自己对此方案的不认可态度:
Is it attractive because it is the simplest solution? Usually, no. Is it seductive because it is the most robust? Sadly, no. Is it alluring because it’ll be easy to reuse? Tragically, no.
      第二种方式是采用硬件负载均衡器,例如Citrix NetScaler。不过,购买硬件的费用不菲,通常是一些大型公司才会考虑此方案。

     如果既不愿意承受Smart Client的痛苦,又不希望花费太多费用去购买硬件,那就可以采用一种混合(Hybird)的方式,称之为软件负载均衡器(Software Load Balancer)。Larson提到了HAProxy。它会运行在本地,需要负载均衡的服务都会在本地中得到均衡和协调。


缓存 


     为了减轻服务器的负载,还需要引入缓存。文章给出了常见的对缓存的分类,分别包括:预先计算结果(precalculating result,例如针对相关逻辑的前一天的访问量)、预先生成昂贵的索引(pre-generating expensive indexes,例如用户点击历史的推荐)以及在更快的后端存储频繁访问的数据的副本(例如MemcachedRedisMongodb)。


应用缓存


      提供缓存的方式可以分为应用缓存和数据库缓存。此二者各擅胜场。应用缓存通常需要将处理缓存的代码显式地集成到应用代码中。这就有点像使用代理模式来为真实对象提供缓存。首先检查缓存中是否有需要的数据,如果有,就从缓存直接返回,否则再查询数据库。至于哪些值需要放到缓存中呢?有诸多算法,例如根据最近访问的,或者根据访问频率。使用Memcached的代码如下所示:
key = "user.%s" % user_id
user_blob = memcache.get(key)
if user_blob is None:
user = mysql.query("SELECT * FROM users WHERE user_id=\"%s\"", user_id)
if user:
memcache.set(key, json.dumps(user))
return user
else:
return json.loads(user_blob)


数据库缓存


     数据库缓存对于应用代码没有污染,一些天才的DBA甚至可以在不修改任何代码的情况下,通过数据库调优来改进系统性能。例如通过配置Cassandra行缓存。


内存缓存


      为了提高性能,缓存通常是存储在内存中。常见的内存缓存包括Memcached和Redis。不过采用这种方式仍然需要合理的权衡。我们不可能一股脑儿的将所有数据都存放在内存中,虽然这会极大地改善性能,但比较起磁盘存储而言,RAM的代价更昂贵,同时还会影响系统的健壮性,因为内存中的数据没有持久化,容易丢失。正如之前提到的,我们应该将需要的数据放入缓存,通常的算法是least recently used,即LRU。


CDN


      提高性能,降低Web服务器负载的另一种常见做法是将静态媒体放入CDN(Content Distribution Network)中。如下图所示:
jg3.png

      CDN可以有效地分担Web服务器的压力,使得应用服务器可以专心致志地处理动态页面;同时,CDN还可以通过地理分布来提高响应请求的性能。在设置了CDN后,当系统接收到请求时,首先会询问CDN以获得请求中需要的静态媒体(通常会通过HTTP Header来配置CDN能够缓存的内容)。如果请求的内容不可用,CDN会查询服务器以获得该文件,并在CDN本地进行缓存,最后再提供给请求者。如果当前网站并不大,引入CDN的效果不明显时,可以考虑暂不使用CDN,在将来可以通过使用一些轻量级的HTTP服务器如Nginx,为静态媒体分出专门的子域名如static.domain.com来提供服务。


缓存失效


      引入缓存所带来的问题是如何保证真实数据与缓存数据之间的一致性。这一问题通常被称之为缓存失效(Cache Invalidation)。从高屋建瓴的角度来讲,解决这一问题的办法无非即使更新缓存中的数据。一种做法是直接将新值写入缓存中(通常被称为write-through cache);另一种做法是简单地删除缓存中的值,在等到下一次读缓存值的时候再生成。

      整体而言,要避免缓存实效,可以依赖于数据库缓存,或者为缓存数据添加有效期,又或者在实现应用程序逻辑时,尽量考虑避免此问题。例如不直接使用DELETE FROM a WHERE…来删除数据,而是先查询符合条件的数据,再使得缓存中对应的数据失效,继而根据其主键显式地删除这些行。


Off-Line处理


     这篇文章还提到了Off-Line的处理方式,即通过引入消息队列的方式来处理请求。事实上,在大多数企业软件系统中,这种方式也是较为常见的做法。在文章《案例分析:基于消息的分布式架构》中,较为详细地介绍了这种架构。在引入消息队列后,Web服务器会充当消息的发布者,而在消息队列的另一端可以根据需要提供消费者Consumer。如下图所示。对于Off-Line的任务是否执行完毕,通常可以通过轮询或回调的方式来获知。
jg4.png

      为了更好地提高代码可读性,可以在公开的接口定义中明确地标示该任务是On-Line还是Off-Line。
      引入Message Queue,可以极大地缓解Web服务器的压力,因为它可以将耗时较长的任务转到专门的机器上去执行。

     此外,通过引入定时任务,也可以有效地利用Web服务器的空闲时间来处理后台任务。例如,通过Spring Batch Job来执行每日、每周或者每月的定时任务。如果需要多台机器去执行这些定时任务,可以引入Spring提供的Puppet来管理这些服务器。Puppet提供了可读性强的声明性语言来完成对机器的配置。


Map-Reduce


     对于大数据的处理,自然可以引入Map-Reduce。为整个系统专门引入一个Map-Reduce层来处理数据是有必要的。相对于使用SQL数据库作为数据中心的方式,Map-Reduce对可伸缩性的支持更好。Map-Reduce可以与任务的定时机制结合起来。如下图所示:
jg5.png


平台层


      Larson认为,大多数系统都是Web应用直接与数据库通信,但如果能加入一个平台层(Platform Layer),或许会更好。
jg6.png

      首先,将平台与Web应用分离,使得它们可以独立地进行伸缩。例如需要添加一个新的API,就可以添加新的平台服务器,而无需增加Web服务器。要知道,在这样一个独立的物理分层架构中,不同层次对服务器的要求是不一样的。例如,对于数据库服务器而言,由于需要频繁地对磁盘进行I/O操作,因此应保证数据库服务器的IO性能,如尽量使用固态硬盘。而对于Web服务器而言,则对CPU的要求比较高,尽可能采用多核CPU。

     其次,增加一个额外的平台层,可以有效地提高系统的可重用性。例如我们可以将一些与系统共有特性以及横切关注点的内容(如对缓存的支持,对数据库的访问等功能)抽取到平台层中,作为整个系统的基础设施(Infrastructure)。尤其对于产品线系统而言,这种架构可以更好地为多产品提供服务。

     最后,这种架构也可能对跨团队开发带来好处。平台可以抽离出一些与产品无关的接口,从而隐藏其具体实现的细节。如果划分合理,并能设计出相对稳定的接口,就可以使得各个团队可以并行开发。例如可以专门成立平台团队,致力于对平台的实现以及优化。
原文地址