亿级Web系统搭建——单机到分布式集群

openpoker源码
erlang写的网游服务器源码,OpenPoker是一个重型多总人口扑克网游,内建支持了容错能力,负载平衡和任性的范围大小。本文是openpoker源码文件功能的一个清单式说明:

亿级Web系统搭建——单机到分布式集群

作者: 徐汉彬  来源: CSDN  发布时间: 2014-11-26
18:19  阅读: 39721 次  推荐:
93   初稿链接   [收藏]  

  当一个Web系统由日访问量10万渐渐增长及1000万,甚至超1亿底经过被,Web系统接受的下压力会越加大,在是进程遭到,我们见面碰到多底问题。为了解决这些性压力带来问题,我们需要在Web系统架构层面搭建多只层次的缓存机制。在不同的压力等,我们会遇到不同的问题,通过搭建不同的劳动与架构来解决。

  Web负载均衡

  Web负载均衡(Load
Balancing),简单地说就算是叫咱们的服务器集群分配“工作职责”,而用恰当的分配办法,对于保障处后端的Web服务器来说,非常主要。

图片 1

  负载均衡的方针有不少,我们于简单的道起哈。

  1. HTTP重定向

  当用户发来求的早晚,Web服务器通过改HTTP响应头中的Location标记来回到一个初的url,然后浏览器还累呼吁是新url,实际上就是页面重定向。通过重新定向,来上“负载均衡”的目标。例如,我们以下载PHP源码包的时候,点击下充斥链接时,为了解决不同国度同地段下载速度的题目,它见面回去一个相差我们走近之下载地址。重定向的HTTP返回码是302,如下图:

图片 2

  如果采取PHP代码来兑现这职能,方式如下:

图片 3

  这个重定向非常容易实现,并且可以从定义各种政策。但是,它以大面积访问量下,性能不帅。而且,给用户的体会吧不好,实际请求发生再次定向,增加了网络延时。

  2. 反而为代理负载均衡

  反朝代理服务之核心工作至关紧要是转发HTTP请求,扮演了浏览器端和后台Web服务器中转的角色。因为其工作在HTTP层(应用层),也就是网络七层结构面临的第七交汇,因此也深受名“七层负载均衡”。可以举行反而往代理的软件很多,比较常见的平等栽是Nginx。

图片 4

  Nginx是均等种植非常灵活的反向代理软件,可以随心所欲定制化转发策略,分配服务器流量之权重等。反向代理中,常见的一个题材,就是Web服务器存储的session数据,因为相似负载均衡的政策都是随便分配要的。同一个记名用户的恳求,无法确保得分配至均等之Web机器上,会导致无法找到session的题材。

  解决方案要出星星点点栽:

  1.
配备反向代理的转发规则,让与一个用户的恳求一定取得到同样台机械及(通过分析cookie),复杂的转速规则以见面消耗又多之CPU,也长了代理服务器的担当。

  2.
将session这类的音信,专门为此有独立服务来囤,例如redis/memchache,这个方案是较推荐的。

  反朝代理服务,也是可打开缓存的,如果开了,会多反向代理的承担,需要小心采用。这种负荷均衡策略实现同配备非常简单,而且性能表现为于好。但是,它有“单点故障”的题材,如果挂了,会带多之累。而且,到了晚期Web服务器继续增多,它自己也许变为系统的瓶颈。

  3. IP负载均衡

  IP负载均衡服务是办事于网络层(修改IP)和传输层(修改端口,第四重叠),比打工作在应用层(第七叠)性能要大有深多。原理是,他是对IP层的数据包的IP地址和端口信息进行改动,达到负载均衡的目的。这种方法,也让称“四层负载均衡”。常见的载荷均衡方式,是LVS(Linux
Virtual Server,Linux虚拟服务),通过IPVS(IP Virtual
Server,IP虚拟服务)来促成。

图片 5

  以负载均衡服务器收到客户端的IP包的时段,会修改IP包的目标IP地址或端口,然后原封不动地送到个中网络中,数据包会流入到实际Web服务器。实际服务器处理完后,又会用数据包投递回为负载均衡服务器,它再修改目标IP地址也用户IP地址,最终回客户端。

图片 6

  上述的不二法门受LVS-NAT,除此之外,还有LVS-RD(直接路由),LVS-TUN(IP隧道),三者之间还属于LVS的法子,但是生自然之分别,篇幅问题,不赘叙。

  IP负载均衡的习性要大有Nginx的反向代理很多,它仅处理到招输层为止的数据包,并无举行更加的组包,然后直接转接让实际服务器。不过,它的布置和搭建比较复杂。

  4. DNS负载均衡

  DNS(Domain Name
System)负责域名解析的服务,域名url实际上是服务器的号,实际映射是一个IP地址,解析过程,就是DNS完成域名及IP的映照。而一个域名是可以配备成对许多只IP的。因此,DNS也便得用作负载均衡服务。

图片 7

  这种负荷均衡策略,配置简单,性能最漂亮。但是,不可知随便定义规则,而且,变更为射的IP或者机器故障时死辛苦,还设有DNS生效延迟的题材。

  5. DNS/GSLB负载均衡

  我们常常因此之CDN(Content Delivery
Network,内容分发网络)实现方式,其实就算是在和一个域名映射为多IP的基础及再度进一步,通过GSLB(Global
Server Load
Balance,全局负载均衡)按照指定规则映射域名之IP。一般情形下还是准地理位置,将离用户近的IP返回给用户,减少网络传输中之行程由于节点内的踊跃消耗。

图片 8

  图中的“向达搜索”,实际过程是LDNS(Local DNS)先向根域名服务(Root
Name Server)获取到五星级根之Name
Server(例如.com的),然后拿走指定域名之授权DNS,然后再度赢得实际服务器IP。

图片 9

  CDN在Web系统受,一般情形下是为此来缓解大小比较充分的静态资源(html/Js/Css/图片等)的加载问题,让这些比靠网络下载的始末,尽可能离开用户还靠近,提升用户体验。

  例如,我访问了同一张imgcache.gtimg.cn上的图纸(腾讯的自建CDN,不以qq.com域名之缘由是防备http请求的时,带齐了剩下的cookie信息),我抱的IP是183.60.217.90。

图片 10

  这种办法,和眼前的DNS负载均衡一样,不仅性能最漂亮,而且支持配置多种国策。但是,搭建筑及护卫本大强。互联网一丝公司,会起建CDN服务,中小型企业一般以第三正值提供的CDN。

  Web系统的缓存机制的树与优化

  刚刚我们谈得了了Web系统的表网络环境,现在我们开始关心我们Web系统本身之习性问题。我们的Web站点随着访问量的升高,会遇见重重的挑战,解决这些题目不光是扩容机器这么简单,建立及采用方便的缓存机制才是历来。

  最初步,我们的Web系统架构可能是这么的,每个环节,都或不过发1令机械。

图片 11

  我们于最根本的数量存储开始看哈。

  如出一辙、 MySQL数据库里缓存使用

  MySQL的缓存机制,就从先由MySQL内部开始,下面的情节将因无限普遍的InnoDB存储引擎为主。

  1. 起家合适的目录

  最简便的是建目录,索引在表数据较大之时节,起及高速搜索数据的意,但是本为是有些。首先,占用了迟早的磁盘空间,其中组合索引最突出,使用要严谨,它产生的目录甚至会见比源数据还可怜。其次,建立目录之后的多少insert/update/delete等操作,因为待更新原来的目,耗时会大增。当然,实际上我们的系统从完整来说,是为select查询操作多,因此,索引的用还是对系统性能有大幅升级的意图。

  2. 数据库连接线程池缓存

  如果,每一个数据库操作请求都得创造和销毁连接的话,对数据库来说,无疑也是同种植巨大的付出。为了削减当下列的开发,可以以MySQL中配置thread_cache_size来代表保留多少线程用于复用。线程不够的当儿,再创,空闲了多之时光,则销毁。

图片 12

  其实,还有更为激进一点底做法,使用pconnect(数据库长连接),线程一旦创立以那个丰富日子内都保持在。但是,在访问量比较坏,机器比较多的状态下,这种用法很可能会见导致“数据库连接数耗尽”,因为起连接并无回收,最终落得数据库的max_connections(最大连接数)。因此,长连接的用法通常要以CGI和MySQL之间实现一个“连接池”服务,控制CGI机器“盲目”创建连接数。

图片 13

  建立数据库连接池服务,有为数不少落实之法门,PHP的说话,我推荐应用swoole(PHP的一个网络通讯拓展)来贯彻。

  3. Innodb缓存设置(innodb_buffer_pool_size)

  innodb_buffer_pool_size这是只用来保存索引和数码的内存缓存区,如果机器是MySQL独占的机,一般推荐呢机物理内存的80%。在取表数据的景象中,它好减磁盘IO。一般的话,这个价值设置更怪,cache命中率会愈发强。

  4. 分库/分表/分区。

  MySQL数据库表一般受数据量在百万级别,再向上增强,各项性能将会晤油然而生大下降,因此,当我们预见数据量会越此量级的上,建议开展分库/分表/分区等操作。最好的做法,是劳务以搭建之初即计划呢分库分表的囤积模式,从根本上杜绝中后期的高风险。不过,会牺牲局部便利性,例如列表式的询问,同时,也搭了保护的复杂度。不过,到了数据量千万级别或以上之时光,我们见面发觉,它们还是值得的。

  次、 MySQL数据库多尊服务搭建

  1华MySQL机器,实际上是风险的一味点,因为要是她挂了,我们Web服务就是无可用了。而且,随着Web系统访问量继续添,终于产生同龙,我们发现1光MySQL服务器无法支撑下去,我们开始需要以还多之MySQL机器。当引入多雅MySQL机器的时候,很多新的题材而用产生。

  1. 起家MySQL主从,从仓库用作备份

  这种做法纯粹为了化解“单点故障”的问题,在主库出故障的上,切换至从库。不过,这种做法实在有点浪费资源,因为从库实际上为闲在了。

图片 14

  2. MySQL念写分离,主库写,从库读。

  两华数据库做读写分离,主库负责写入类的操作,从仓库负责读的操作。并且,如果主库发生故障,仍然未影响读的操作,同时为足以拿通朗诵写都临时切换至打库中(需要注意流量,可能会见盖流量过特别,把从库也拖垮)。

图片 15

  3. 主主互备。

  两华MySQL之间互相为彼此的从库,同时以是主库。这种方案,既做到了访问量的压力分流,同时为解决了“单点故障”问题。任何一样宝故障,都还有另外一模仿可供使用的劳务。

图片 16

  不过,这种方案,只能用当少雅机械的状况。如果工作展开还是很快的话,可以挑选用业务分别,建立多单主主互备。

  其三、 MySQL数据库机器中的多寡并

  每当我们缓解一个题材,新的题材肯定诞生在旧的化解方案及。当我们发出差不多玉MySQL,在业务高峰期,很可能出现零星个仓库中的数量发生延期的面貌。并且,网络与机器负载等,也会影响数并的延。我们早已碰到了,在日访问量接近1亿底奇现象下,出现,从仓库数据要广大龙才会一起追上主库的多寡。这种景象下,从仓库基本失去功效了。

  于是,解决并问题,就是咱们下同样步要关怀的触发。

  1. MySQL自带多线程同步

  MySQL5.6从头支持主库和从库数据并,走多线程。但是,限制为是较显然的,只能为库为单位。MySQL数据并是透过binlog日志,主库写副到binlog日志的操作,是怀有顺序的,尤其当SQL操作中包含对表结构的改动等操作,对于继往开来的SQL语句操作是来震慑之。因此,从仓库同步数据,必须动只进程。

  2. 好实现解析binlog,多线程写入。

  因数据库的表为单位,解析binlog多张表同时举行多少并。这样做吧,的确会加速数据并的频率,但是,如果表和表之间有结构关系还是数额据之说话,则一律存在写入顺序的题材。这种方法,可用于一些比较稳定并且相对独立的数据表。

图片 17

  国内一线互联网企业,大部分还是经过这种办法,来加快数据并效率。还有更加激进的做法,是直解析binlog,忽小以表明也单位,直接写入。但是这种做法,实现复杂,使用范围就重受限制,只能用于一些景象特殊之数据库中(没有说明结构改变,表和发明中从来不数据据等特殊表)。

  季、 在Web服务器和数据库里成立缓存

  实际上,解决大访问量的问题,不能够就着眼于数据库层面。根据“二八定律”,80%之呼吁单关心在20%底紧俏数据达。因此,我们当建立Web服务器和数据库中的缓存机制。这种机制,可以就此磁盘作为缓存,也可以用外存缓存的艺术。通过她,将大部分之热数据查询,阻挡在数据库之前。

图片 18

  1. 页面静态化

  用户访问网站的某页面,页面及之多数情在怪丰富一段时间内,可能都是没有转的。例如一首新闻报道,一旦发布几乎是免会见窜内容之。这样的话,通过CGI生成的静态html页面缓存到Web服务器的磁盘本地。除了第一次于,是经过动态CGI查询数据库获取之外,之后都一直将地面磁盘文件返回给用户。

图片 19

  以Web系统规模比小之早晚,这种做法看似完美。但是,一旦Web系统规模变死,例如当我发生100令的Web服务器的时。那样这些磁盘文件,将会见来100卖,这个是资源浪费,也不好维护。这个时有人会怀念,可以集中一致光服务器存起来,呵呵,不如看看下面一种植缓存方式吧,它就是是这般做的。

  2. 单纯台内存缓存

  通过页面静态化的例证中,我们好清楚用“缓存”搭建在Web机器本机是坏维护的,会带来双重多问题(实际上,通过PHP的apc拓展,可经过Key/value操作Web服务器的本机内存)。因此,我们捎搭建之内存缓存服务,也非得是一个独自的劳动。

  内存缓存的选取,主要发生redis/memcache。从性能达到说,两者反差不充分,从功能丰富程度及说,Redis更胜一筹。

图片 20

  3. 舅存缓存集群

  当我们搭建单台内存缓存了,我们还要见面面临单点故障的问题,因此,我们亟须以其成一个集群。简单的做法,是叫他充实一个slave作为备份机器。但是,如果请求量真的多,我们发现cache命中率不强,需要再次多的机内存为?因此,我们更建议将它们配备成一个集群。例如,类似redis
cluster。

  Redis
cluster集群内之Redis互为多组基本,同时每个节点都可领请求,在展开集群的下比较有利。客户端可望自由一个节点发送请求,如果是它的“负责”的情节,则直接归内容。否则,查找实际负担Redis节点,然后将地方告知客户端,客户端重新请。

图片 21

  对于使用缓存服务之客户端的话,这总体是晶莹剔透的。

图片 22

  内存缓存服务在切换的时节,是出自然风险的。从A集群切换到B集群的经过遭到,必须保证B集群提前做好“预热”(B集群的内存中的热数据,应该尽可能与A集群相同,否则,切换的转大方央内容,在B集群的内存缓存中找寻无交,流量直接冲击后端的数据库服务,很可能造成数据库宕机)。

  4. 削减数据库“写”

  上面的体制,都实现减少数据库的“读”的操作,但是,写的操作为是一个好之压力。写的操作,虽然无法回落,但是好透过合并请求,来起及减轻压力的功能。这个时刻,我们就是需以内存缓存集群和数据库集群内,建立一个修改并机制。

  先将改要生效在cache中,让外界查询显示正常,然后用这些sql修改放入到一个阵中存储起来,队列满或者各级隔一段时间,合并为一个求到数据库被更新数据库。

图片 23

  除了上述通过改变系统架构的办法提升写的属性外,MySQL本身吗得由此配备参数innodb_flush_log_at_trx_commit来调动写副磁盘的方针。如果机器成本允许,从硬件层面解决问题,可以择老一点的RAID(Redundant
Arrays of independent Disks,磁盘列阵)或者比较新的SSD(Solid State
Drives,固态硬盘)。

  5. NoSQL存储

  不管数据库的读或写,当流量再进一步上涨,终会达到“人力来穷时”的观。继续加机器的老本比强,并且不自然得真正化解问题之时段。这个时刻,部分骨干数据,就足以考虑下NoSQL的数据库。NoSQL存储,大部分都是行使key-value的方,这里比较推荐以方面介绍过Redis,Redis本身是一个内存cache,同时也得以用作一个储存来以,让其直接拿数据落地到磁盘。

  这样的话,我们就是拿数据库被一些被反复读写的数码,分离出来,放在我们新搭建的Redis存储集众多中,又更减轻原来MySQL数据库的下压力,同时为Redis本身是独内存级别之Cache,读写的性都见面大提升。

图片 24

  国内一线互联网公司,架构上运用的化解方案很多凡接近于上述方案,不过,使用的cache服务却无必然是Redis,他们会产生重复丰富的别选择,甚至根据我工作特色开发出好之NoSQL服务。

  6. 空节点查询问题

  当我们搭建了前面所说的任何劳务,认为Web系统现已好强的当儿。我们还是那么句话,新的题目或者会来的。空节点查询,是凭借那些数据库中向不有的多寡请求。例如,我要查询一个请勿设有人口信息,系统会从各个缓存逐级查找,最后查及到数据库本身,然后才得出查找无交的结论,返回给前端。因为各级cache对它不行,这个要是可怜耗系统资源的,而如大气的空节点查询,是足以拍到网服务之。

图片 25

  在本人一度的劳作经验中,曾受其害。因此,为了维护Web系统的安定,设计适合的空节点过滤机制,非常有必不可少。

  我们及时应用的法子,就是规划同样摆简略的笔录映射表。将是的记录存储起来,放入到同样台内存cache中,这样的话,如果还有空节点查询,则在缓存这等同叠就被挡了。

图片 26

  异乡部署(地理分布式)

  完成了上述架构建设后,我们的系是否就已够强劲了邪?答案当然是否认的哈,优化是凭极端的。Web系统虽然表面上看,似乎比强了,但是给用户的感受也不肯定是极端好的。因为东北的校友,访问深圳之一个网站服务,他还是碰头感觉到有些大网距离及之冉冉。这个时,我们即便需要开异地部署,让Web系统去用户还贴近。

  同等、 核心集中与节点分散

  有娱乐过大型网游的同班都见面知晓,网游是发出过多独区的,一般都是据地面来划分,例如广东专区,北京专区。如果一个以广东底玩家,去都专区玩,那么他会晤感觉明显比较在广东专区卡。实际上,这些大区的名称即使已证实了,它的服务器所在地,所以,广东底玩家去老是处北京的服务器,网络自会比较缓慢。

  当一个体系与劳动足够好的上,就亟须从头考虑外地部署的问题了。让您的劳动,尽可能离开用户更靠近。我们眼前早已关系了Web的静态资源,可以存放于CDN上,然后通过DNS/GSLB的不二法门,让静态资源的疏散“全国各地”。但是,CDN只解决之静态资源的题材,没有解决后端庞大的系服务还独自集中在某某固定城市的题材。

  这个时刻,异地部署就开始了。异地部署一般遵循:核心集中,节点分散。

  1.
主导集中:实际部署过程遭到,总有一部分的数据以及服务存在不可部署多效,或者安排多拟成本巨大。而于这些劳动和数量,就依旧维持一效仿,而部署地点选择一个域比较基本的地方,通过网络里专线来与一一节点通讯。

  2.
节点分散:将部分劳动配置为多套,分布在逐一邑节点,让用户要尽可能选择贴近的节点访问服务。

  例如,我们选择以上海布局为主导节点,北京,深圳,武汉,上海啊分流节点(上海团结我为是一个分流节点)。我们的劳务架构使图:

图片 27

  需要补充一下底凡,上图备受上海节点和主导节点是与处一个机房的,其他分散节点各自独立机房。

  国内产生那么些巨型网游,都是约遵循上述架构。它们会管数据量不甚之用户基本账号等位居核心节点,而多数的网游数据,例如装备、任务等数码与劳务在地面节点里。当然,核心节点和所在节点内,也时有发生缓存机制。

  老二、 节点容灾和过载保护

  节点容灾是负,某个节点如果起故障时,我们需要建立一个体制去包服务还是可用。毫无疑问,这里比普遍的容灾方式,是切换至邻近都市节点。假如系统的天津节点发生故障,那么我们就算用网络流量切换至相邻的京城节点上。考虑到负载均衡,可能得而将流量切换到邻近的几只地区节点。另一方面,核心节点自身为是待自己做好容灾和备份的,核心节点一旦故障,就见面影响全国服务。

  过载保护,指的是一个节点都达到最深容量,无法持续接接受又多要了,系统必须来一个保安之建制。一个劳动业已满负载,还累接受新的呼吁,结果大可能就是宕机,影响所有节点的劳动,为了至少保持大部分用户之健康下,过载保护是少不了的。

  解决过载保护,一般2单方向:

  1.
拒绝服务,检测到满负载之后,就不再接受新的连要。例如网游登入中的排队。

  2.
散至其它节点。这种的话,系统实现更复杂,又提到到负载均衡的题材。

  小结

  Web系统会就访问规模的滋长,渐渐地起1台服务器可以满足急需,一直成长为“庞然大物”的挺集群。而这Web系统易死的进程,实际上就是咱们缓解问题之经过。在不同的等,解决不同的问题,而初的问题同时出生在初的解决方案之上。

  系统的优化是无终点的,软件和系统架构也直于迅速提高,新的方案解决了直的题目,同时也带新的挑战。

 

原文地址: http://kb.cnblogs.com/page/509402/

模块名称 模块功能说明 备注
ante.erl 仅仅是开始下注的处理,具体的逻辑在betting中  
barrier.erl barrier本意屏障  
bb.erl Bot launcher  
betting.erl Poker betting logic 下注逻辑处理  
bits.erl 位处理相关操作  
blinds.erl 处理小盲注,大盲注  
bot.erl AI,gen_server,用来测试,将来应该能够陪真人玩家来玩  
bot.hrl    
common.hrl    
counter.erl 用于把各种计数器(自增、唯一ID)存入mnesia. 目前有3种: 玩家,游客,Game  
db.erl 数据库操作  
deal_cards.erl 发牌,其中的private与shared,代表公共牌还是私有牌。这已经是与具体玩法有关的了,而与框架无关。  
deck.erl 台面,在其上洗牌  
delay.erl 每一局游戏开始前的倒计时  
delayed_exit.erl 游戏倒计时到正式开始前偷溜走的相关情况处理  
dmb.erl 其中mb=multi bots,机器人。dmb指的是distributed multi bots 分布式  
dumbo.erl 哑巴机器人  
exch.erl 自定义behavior,也是一个gen_server,A stack of game modules:玩家&游客  
fixed_limit.erl 自定义behavior,也是一个gen_server,A stack of game modules:玩家&游客  
g.erl    
game.erl 每一局游戏,本质上是exch.erl。实现了开始,停止,自动计数,Watch the game without joining  
game.hrl 游戏  
game_start.erl 游戏直接开始  
game_wait_players.erl 游戏等待其他玩家到齐后开始  
gateway.erl 网关-负载均衡  
hand.erl 用来计算牌型,例如:full housr 就是3带2.  
id.erl 固定哈希函数的封装,用来产生进程ID与Key的唯一映射关系。目前没有被引用到。  
ircdb.dat.gz 模拟玩家数据  
ircdb.erl 模拟玩家数据  
ircdb.hrl    
lang.erl 多语言处理入口,需要完善,目前只有英语  
limit.erl 各种限制接口,各种limit限制判断主要在game.erl中调用  
login.erl 登录  
mb.erl 机器人,用于测试  
mbu.erl 机器人,用于测试  
no_limit.erl 一局游戏人数上下限  
observer.erl 可以给机器人附加一个观察者职责,用来监视游戏活动状况的  
pickle.erl 序列化  
player.erl 玩家  
pot.erl 貌似是奖池,也就是所有已下的赌注的集合。  
pot_limit.erl 奖池中的加注、盲注限制  
pp.erl 报文编码/解码  
pp.hrl    
restart.erl NO USE  
schema.erl 初始化调度  
server.erl 主服务进程  
showdown.erl 摊牌   
stats.erl 数据统计  
t.erl debug  
tcp_server.erl 通用的tcp服务器程序,主要被gateway和server使用,另外也作为客户端连接用  
test.erl 测试入口函数  
test.hrl    
texas.hrl 游客相关处理机制,下同,可以暂时忽略  
tourney.erl    
tourney.hrl    
tourney_game_start.erl    
tourney_wait_players.erl    
tourney_wait_timer.erl    
util.erl 提供3个公用函数: 1.判断进程死活;2.初始化“从”数据库;3. 返回一个随机的进程组成员进程。  
visitor.erl 游客  

如上文件时对基于Erlang开发之分布式可扩大游戏框架openpoker源码文件清单的证明。主要是对准文本与文书功能进行了验证,正在整理模块调度关系,持续创新中…

图片 28

负载均衡网关节点工作规律示意图

发表评论

电子邮件地址不会被公开。 必填项已用*标注