程序员架构学习—互联网公司分布式集群架构(小型→中型→大型)
喜欢的朋友可以关注下专栏:Java架构技术进阶。里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦。
一、小型公司网络架构
狗子是某大学计算机专业本科应届毕业生,由于自己的技术不错,再加上互联网产业的巨大利润的驱使,狗子决定走上创业这条路,于是,狗子联合了同学二黑,鸡子,狗蛋等人花费了几个月的时间写出了一套网站,是关于足球资讯的pc端网站加上手机APP客户端。现在产品测试成功了,准备发布了,狗子想到了两个问题:
1.网站需要服务器
狗子之前所有的代码测试都是在本地服务器或者局域网上进行的,现在需要把产品发布到外网上,让所有的人都能访问,因此再用自己的电脑当服务器显然很不现实,于是,狗子去买了一台服务器,在上面装了jdk,tomcat,mysql等必备环境,把网站搭了起来,又经过了很多测试,运行毫无问题了,通过网站的ip可以访问并且实现功能了,而且app的后台也在服务器上测试成功了,目前公司的架构如图所示:
那么问题又来了:
2.网站需要的域名
显然,如果让各地的用户需要记住你服务器的ip地址才能访问你的网站的话,那是会被用户拿刀追着砍的。因此,狗子需要一个便于记住的域名,以后在浏览器输入这个域名就能够访问这个网站,所以,狗子拿着申请下来的各种资质,找到了域名贩卖商,一般是腾讯阿里巴巴这种代理贩卖商,花了一笔钱,从它们的手上购买了域名,彻底实现了网站通过域名就能访问的功能。这里需要讲解一下通过域名访问的原理:
域名访问原理
通过ip访问相当于用户直接访问输入的ip所指向的服务器,而通过域名访问,是用户输入域名之后,请求先被发送到域名管理者所控制的DNS服务器中,DNS服务器中有一个数据库,数据库中存有这个域名所对相应的ip地址,DNS服务器当了一个中间人,将请求转发到这个ip地址对应的服务器,就实现了通过域名访问,因此,通过域名访问本质上还是通过ip访问。那么,狗子公司的架构图就应该是下面这样:
解决了这两个问题,狗子的产品顺利的发布了,经过一两个月的运营,慢慢地发掘了一小批用户,实现了小幅盈利,狗子开始沾沾自喜了,原来,挣钱就这么容易啊。然而很快,现实给了初出茅庐的狗子当头一棒:一个连黑客都算不上的恶意用户,通过自己写的一个小小的程序,居然把狗子的服务器搞崩了,这是怎么一回事呢?
服务器防火墙的概念
读者可能也了解一些,用户通过网站向服务器发送请求,服务器处理请求再对用户进行响应对服务器的内存是有开销的,但是,读者可能不清楚的是,这种开销有多么大。每当一个用户向服务器发送请求,服务器都要启动一个线程去处理这个请求并且响应给用户。这之中耗费的服务器内存差不多是1mb以上级别的,更别说是再加上其中的服务器处理数据进行的各种操作了。也就是说,用户发送一个东西,服务器会损失1mb以上的内存,多发几个,服务器就该受不了了。
攻击狗子服务器的人就是写了一个简简单单的小程序,重复多次地向服务器发送请求,服务器在短时间之内没有这么多内存去处理这么多请求,自然就宕机了,就崩了。
搞懂了这些,狗子自然就想出了应对策略,于是,他给自己的服务器开启了防火墙,通过配置防火墙,实现了禁止同一个用户在短时间内重复多次频繁发送请求,他的服务器也可以安心地工作了。
当然,有的读者可能会问了,那么,防火墙禁止了单一用户短时间内多次重复发送请求,那么如果我是一个黑客,通过种木马等黑客手段控制了数以千计甚至更多的其他用户的电脑,让这些不同的电脑去短时间内攻击服务器,可不可以攻击成功呢?答案是确实可以,这些被控制的电脑就是DDOS攻击中的肉鸡,这里有些跑题了,在本文不再赘述。注意,配置这种拦截单一ip防火墙只是基本操作,甚至买来的服务器会自带。之所以狗子的服务器没有是因为只有他足够的“初出茅庐”,才能给读者解释清楚:)。
那么,我们现在的架构图就应该是这样:
二、中型公司网络架构
狗子的公司越办越大,越来越多的用户开始使用他的软件看各种足球咨询,而且,用于用户的基数变大了,每天增长的用户数量都在变多,以前可能是每天有十个新用户,那么现在就是每天有了一百个新用户。在一个晚上的服务器宕机事故出现之后,狗子终于意识到,自己的单台服务器应对日益庞大的用户群已经开始体力不支了。于是,他用了之前积攒下来的收益,又购入了三台服务器,并且用其中一台服务器单独运行数据库,作为数据库服务器。
那么现在问题来了,这四台服务器怎么一起使用,同时服务于一个网站的运营呢?
解决方案有两个:
1.三个服务器同时运行相同的代码,在代码页设置三个用户入口,如果用户进入一个入口发现进不去,就选择另一个入口,每个入口对应一台服务器
这样做的好处是简单方便,直接把代码往另外两个服务器一拷贝 然后更改一些其中的设置,再设置三个入口就行了。但是缺点也是很明显的,显然用户的第一反应都是点击第一个入口,只有当第一个入口进不去的时候才会选择另外两个服务器,而且等到以后用户数量越来越大,难道我们要设置几十几百个入口让用户一个一个去试吗?这显然又是一个被用户追着拿刀砍的行为。(当程序员可以体验死亡如风,常伴吾身的感觉)所以,这个方法显然不太现实,不过这个方法也是有它的应用场景的,比如说在一些学校的官网的在校生入口,由于在校生是毕业一批又新来一批,所以用户体量不会有太大的增长,因此才可以使用这个方法。这种方法的架构图是这样的:
2.负载均衡
狗子咨询了一些在中大型互联网公司的学长,终于找到了一种解决这个问题还不像第一种方法那样容易有生命危险的办法,那就是nginx。
nginx是个什么东西呢?是用来做服务器负载均衡的,说白了就是当用户发送请求的时候,先经过nginx这个中间人,nginx会去感受哪个服务器比较闲,就会把请求发送到这个比较闲的服务器上去,这样运行多了,就可以做到每个服务器相对的负担比较平衡,这就是负载均衡。nginx可以放在服务器本机,也可以放在单独的一个服务器中,nginx这个中间人会向各个服务器分发请求,并且nginx的性能十分高超,每秒百万级以下数量的请求都可以处理。你可能要问了,如果狗子把nginx单独放在一个服务器上,那么他的三台服务器怎么对应到同一个域名上呢?他是否需要给每个nginx分发的服务器也就是那三台购买三个域名呢?当然不用,事实上,现在我们对外的公共ip已经变成了安装nginx的服务器的ip了,也就是说,我们只要把域名映射到这个nginx服务器就可以了,然后nginx中会有配置,我们只要在配置中写下三个服务器的ip,nginx以后就能把请求分发过去了。那么,我们现在的架构图就变成了下图这样:
狗子还想对服务器做做优化,像是session这种东西,只是简简单单的一个session请求,却要耗费服务器那么多的性能,有没有一种方法,能够对这方面做一些改进呢?
当然有,解决方案就是redis。
redis的作用
redis是一种数据库,我们比较熟知的数据库有mysql,sqlServer,oracle等,那么这个redis又是个什么玩意?
redis和上述几种数据库不同,它是缓存数据库,也就是说,redis是致力于短时存储的,redis并不是从硬盘中拿取和处理数据,它对数据的处理都是在内存中,由于内存的数据处理速度不知道比磁盘高到哪里去了,所以redis的性能也是碾压mysql,sqlServer,oracle这种数据库的,这无关于软件优劣,纯粹是因为硬件层面的因素。不过redis因为是在内存中,因此只要机器一关闭,内存中redis存储的东西就会消失了,不过redis也可以将数据持久化存储到mysql这些数据库中,但是一涉及到对硬盘的操作,redis的性能就下来了。因此,我们的redis常常是用来存储像是用户的登录状态这种短时需要的数据,而去把用户登录注册的时间备份到硬盘上的数据库。那么,我们现在的架构图就变成了如下这样:
又过了一段时间,随着用户体量越来越大,数量级达到了上万上十万的时候,狗子发现一直以来,自己都忽略了一个问题,尽管自己增加了服务器,加了负载均衡,还启用了redis缓存数据库,为了使用户访问的速度增加还有让服务器的负载不那么大,但是,网站处理数据的方式本质上是对数据库进行增删改查,而现在我们的数据库服务器只有一台,数据库处理数据本身就是一项复杂耗费内存的工作,现在的一台数据库服务器更是杯水车薪,因此,在中小型公司的网站架构中,最先撑不住的往往是数据库服务器。
当然,狗子又有了解决办法。他又购入了两台服务器当作数据库服务器,然后把数据库进行了分库分表的操作,分别把数据存在三台数据库服务器上。当然狗子觉得这还不够,因此,他又使用了一种技术,将数据库进行了读写分离。
读写分离理解起来很简单,和它的字面意思一样,就是把从数据库中写入数据和从数据库中拿取数据进行分离,以此来达到减少数据库服务器负担的作用。用来读取数据的服务器和用来写入数据的服务器会在用户进行操作之后延迟一段时间进行数据同步,一般来说延迟时间不会太长,很可能用户都不会觉察到。那么,我们现在的架构图就变成了下图这样:
可以看到,我们的图上新出现了“集群”这个词,不错,互联网经常提及的xxx集群终于在我们眼前解开了神秘面纱,也就是多台服务器同时协同处理事务,就可以称作一个服务器集群。
三、 大型公司网络架构
时光飞逝,转眼间五年的时间过去了,狗子已经从一个中小型互联网公司的小老板摇身一变成了一个上市公司总裁,和马云马化腾等it行业巨佬互动成了他的日常,他的一句话可以动摇it界,他的网站也拥有了上亿的用户。。。。。
到了这种程度,狗子的公司网络架构已经变成了下图这样:
(内容比较多,看不清记得放大哦)
能支持上亿人访问的服务器肯定不止这么几个,只是象征性地画了几个。同时,我们把redis服务器与mysql服务器进行了连线,是因为我们前面说过redis可以将数据存入持久性数据库,这里我们可以用来记录登录时间之类的信息。同时,图中的mysql服务器是重叠在一起的,不要以为仅仅只有两台服务器。
随着公司变为巨头,狗子的经验不断累积,他发现自己的公司虽然体量很大,开发的产品越来越多,功能越来越全面,但是总是有那么一部分的功能是重复的。假如在一个新的页面或者产品中,刚开始开发时有那么10%是和以前开发过的页面或者产品的功能是重复的,那么,等到这个新东西的功能开发接近完善的时候,就可能会有70%的功能和从前开发的一样。仔细想想这是一件很可怕的事情,狗子居然画了70%的开发时间和开发成本在做以前早就做过的事情。
这狗子就不能忍了,于是他想到了一个好办法,既然面向对象编程语言中有封装的这种概念,把代码的重复部分封装起来便于重复使用,那么产品和产品之间为何不能封装相同的东西便于使用呢?
于是,他开始实现微服务的概念,解释起来可能一上来比较难于接受,我们先来看,刚刚我们的架构图中的产品实际上可以看成一整个系统,假设这个系统叫做系统A。那么,我们现在开发出来了其它的各种产品或者各种页面,也可以看作是新的系统B和系统C。现在,系统ABC之间有很多重复的部分,于是,我们想到了将这些重复的部分放到一起,供三个系统同时调用。那么实际上,这个重复的部分就是被封装起来的微服务,微服务是一种模块化开发,把产品的功能提炼成多个模块,在开发时把模块拼接起来,就可以省去大量的工作。为了实现一个模块,模块中也需要带有服务器集群等东西。听了这些,我们下面的架构图看起来应该没有那么难懂了:
这些与技术无关,而是一种开发理念,一种思想,有了这种思想,才能在成千上万的用户需求之间找到共通,提升开发效率,节省成本。
狗子有了这种思想,并实现了他,终于打败了所有竞争对手,迎娶白富美,走上了人生巅峰。
。
。
。
。
。
。
。
。
。
。
。
后来,他梦醒了。。。
喜欢的朋友可以关注下专栏:Java架构技术进阶。里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦。
写在后面
对于很多初级Java工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
下文整理的这些架构技术希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。同时我经过多年的收藏目前也算收集到了一套完整的学习资料,希望对想成为架构师的朋友有一定的参考和帮助。
下面是资料部分截图,诚意满满:特别适合有3-5年开发经验的Java程序员们学习。
领取方式:转发文章,一定记得转发文章,然后加入合作Java架构交流Qqun:908676731,管理员处免费领取所有资料。
而针对以上面试技术点,我在这里也做一些技术知识面试专题资料分享,希望能更好的帮助到大家。
领取方式:转发文章,一定记得转发文章,然后加入合作Java进阶之路Qqun:908676731,管理员处免费领取所有资料。