游戏服务器架构和web服务器架构的区别?
1-技术有什么区别
首先通信上目前的主流是HTTP协议和SOCKET这两种(HTML5提供了一种新的协议,WebScoket,对此了解并不多,因此不做评论,以免误导)。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
(注:在HTTP 11中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。)
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
以J2SDK-13为例,Socket和ServerSocket类库位于http://javanet包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。(摘自百科)
在WEB服务器中,一般情况是只需要使用HTTP协议的。因为它不太需要去与浏览器进行主动推送,只需要响应浏览器的访问就足够了
而在游戏服务器,这样的连接方式肯定是不够用的。很多时候游戏服务器是需要主动推送消息,如系统广播。
2-思维有什么区别
WEB服务器并不需要高频即时通讯,对响应速度要求不高。而游戏服务器,大多数是需要很及时的响应速度(暂不讨论弱联网游戏)。如DOTA,这种竞技类型的游戏,1秒就能发生很多事。
因此,在思考方向上,WEB服务器应该考虑是的多平台的兼容,大量用户访问的高并发。
而游戏服务器应该考虑的是高频通讯,高并发。
3-架构的侧重点有什么区别
在架构上面,一般访问量不是很大的网站是只有一台服务器的,访问量高的才会进行分布式设计或者集群设计。
而大部分游戏服务器都是需要分布式设计的。
在现有的网络游戏服务器端架构中,多是以功能和场景来划分服务器结构的。具体的划分是根据项目的需求进行的,并没有一个十分通用的架构。
以上是比较常见的结构,客户端登录的时候,连接GateServer,然后由GateServer去连接LoginServer进行登录。登录后通过CenterServer转发到GameServer(GameServer即是服务器大区)。
而其中的DCServer,主要的功能是缓存玩家角色数据,保证角色数据能快速的读取和保存。
LogServer便是保存日志的了。
4-本质有无区别
本质上,两者并无区别,只是需求不同,侧重点不同罢了。
本文主要介绍了架构技术选型与设计-微服务选型,Spring cloud 实现采用的技术,希望对您的学习有所帮助。
架构技术选型与设计-DUBBODubbo,是阿里巴巴服务化治理的核心框架,并被广泛应用于阿里巴巴集团的各成员站点(阿里巴巴现在使用架构为HSF)。 于2012-10-24最后版本253成为最后一版本,由当当接手维护,命名为dubbox;2017年突然继续dubbo进行维护,最后更新版本时间为 2017-10-11 22:21
Dubbo 核心部件:Provider: 暴露服务的提供方。Consumer:调用远程服务的服务消费方。Registry: 服务注册中心和发现中心。Monitor: 统计服务和调用次数,调用时间监控中心。(dubbo的控制台页面中可以显示)Container:服务运行的容器。Dubbo服务集群-集群容错模式
架构技术选型与设计-微服务选型
架构技术选型与设计-DUBBO
架构技术选型与设计-DUBBO
架构技术选型与设计-微服务选型Spring Cloud,从命名我们就可以知道,它是Spring Source的产物,Spring社区的强大背书可以说是Java企业界最有影响力的组织了,除了Spring Source之外,还有Pivotal和Netfix是其强大的后盾与技术输出。其中Netflix开源的整套微服务架构套件是Spring Cloud的核心。如果拿Dubbo与Netflix套件做对比,前者在国内影响力较大,后者在国外影响力较大,在背景上可以打个平手;但是若要与Spring Cloud做对比,由于Spring Source的加入,在背书上,Spring Cloud略胜一筹,但是在高并发上dubbo曾经在阿里的运营中实际承载过过亿用户同时在线的,而Netflix 并没有实际的上线应用中体现过。Spring Cloud下面有19个子项目(可能还会新增)分别覆盖了微服务架构下的方方面面,服务治理只是其中的一个方面,一定程度来说,Dubbo只是Spring Cloud Netflix中的一个子集。但是在选择框架上,方案完整度恰恰是一个需要重点关注的内容,当然从高可用和高并发一起考虑,Spring Cloud 无疑是最佳选择。
1、Spring Cloud Config 配置中心,利用git集中管理程序的配置。
2、Spring Cloud Netflix 集成众多Netflix的开源软件
3、Spring Cloud Bus 消息总线,利用分布式消息将服务和服务实例连接在一起,用于在一个集群中传播状态的变化
4、Spring Cloud for Cloud Foundry 利用Pivotal Cloudfoundry集成你的应用程序
5、Spring Cloud Cloud Foundry Service Broker 为建立管理云托管服务的服务代理提供了一个起点。
6、Spring Cloud Cluster 基于Zookeeper, Redis, Hazelcast, Consul实现的领导选举和平民状态模式的抽象和实现。
7、Spring Cloud Consul 基于Hashicorp Consul实现的服务发现和配置管理。
8、Spring Cloud Security 在Zuul代理中为OAuth2 rest客户端和认证头转发提供负载均衡
9、Spring Cloud Sleuth SpringCloud应用的分布式追踪系统,和Zipkin,HTrace,ELK兼容。
10、Spring Cloud Data Flow 一个云本地程序和操作模型,组成数据微服务在一个结构化的平台上。
11、Spring Cloud Stream 基于Redis,Rabbit,Kafka实现的消息微服务,简单声明模型用以在Spring Cloud应用中收发消息。
12、Spring Cloud Stream App Starters 基于Spring Boot为外部系统提供spring的集成
14、Spring Cloud Task App Starters
15、Spring Cloud Zookeeper 服务发现和配置管理基于Apache Zookeeper。
16、Spring Cloud for Amazon Web Services 快速和亚马逊网络服务集成。
17、Spring Cloud Connectors 便于PaaS应用在各种平台上连接到后端像数据库和消息经纪服务。
18、Spring Cloud Starters (项目已经终止并且在AngelSR2后的版本和其他项目合并
)19、Spring Cloud CLI 插件用Groovy快速的创建Spring Cloud组件应用。Spring Cloud共集成了19个子项目,里面都包含一个或者多个第三方的组件或者框架!
1、spring cloud : 一个云应用工具,为云应用开发的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁定、决策竞选、分布式会话和集群状态管理等操作
2、spring cloud config :配置管理开发工具包
3、 spring cloud Bus :事件消息总线用于集群(例如:配置变化时间)中传播状态变化,与spring cloud config 联合实现热部署
4、 spring cloud Netflix Eureka : 云端负载均衡基础,一个基于Rest的服务,用于定位服务,以实现云端的负载均衡和中间层服务器的故障转移
5、 spring cloud Netflix Hystrix : 容错管理工具,旨在通过控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力
6 、 Netflix ZUUL: 边缘服务工具,提供动态路由、监控、弹性、安全等边缘服务
7、 spring cloud sleuth :日志收集工具包、封装Purpose 、Zipkin和Trace
8、 Spring Cloud Security : 安全工具包,为应用程序添加安全控制,主要是OAuth2
9、 spring cloud turbine :聚合服务器发送时间流,监控集群下Netflix 和 metrics 情况
Spring cloud 配置中心
Spring cloud 注册中心
Spring cloud 网关: 服务路由、安全认证、会话共享、客户端负载均衡、统一异常处理、跨域请求
Spring cloud 断路由
SAE从架构上采用分层设计,从上往下分别为反向代理层、路由逻辑层、Web计算服务池。而从Web计算服务层延伸出SAE附属的分布式计算型服务和分布式存储型服务,具体又分成同步计算型服务、异步计算型服务、持久化存储服务、非持久化存储服务。各种服务统一向日志和统计中心汇报,参考下图:
Level7 Reverse Proxy(7层反向代理层):HTTP反向代理,在最外层,负责响应用户的HTTP请求,分析请求,并转发到后端的Web服务池上,并提供负载均衡、健康检查等功能。
Service Router(服务路由层):逻辑层,负责根据请求的唯一标识,快速的映射(O(1)时间复杂度)到相应的Web服务池,并映射到相应的硬件路径。如果发现映射关系不存在或者错误,则给出相应的错误提示。该层对用户隐藏了很多具体地址信息,使开发者无需关心服务的内部实际分配情况。
Web Service Pools(Web服务池):由一些不同特性的Web服务池组成。每个Web服务池实际是由一组Apache(PHP)组成的,这些池按照不同的SLA提供不同级别的服务。每个Web服务进程实际处理用户的HTTP请求,进程运行在HTTP服务沙盒内,同时还内嵌同样运行在SAE沙盒内的PHP解析引擎。用户的代码最终通过接口调用各种服务。
Statistics Center & Log Center(日志和统计中心):负责对用户所使用的所有服务进行统计和资源计费,并设定的分钟配额,来判定是否有非正常的使用。分钟配额描述了资源消耗的速度,当资源消耗的速度到达一个预警阈值时,SAE通知系统会提前向用户发出一个警告,提醒用户应用在某个服务上的使用可能存在问题,需要介入关注或处理,配额系统是SAE用来保证整个平台稳定的措施之一;日志中心负责将用户所有服务的日志汇总并备份,并提供检索查询服务。
各种分布式服务:SAE提供覆盖Web应用开发主要方面的多种服务,用户可以通过StdLib(可以理解为SAE PHP版的STL)很方便的调用它们。同时因为Web服务的多样性,SAE的标准服务不可能满足所有场景的需求,所以SAE通过服务总线来对接第三方服务(如分词、全文检索等),SAE也欢迎第三方服务商选择SAE来为开发者提供服务。
真正的用户代码是跑在SAE提供的Web运行环境下的,为了提供公有云计算特有的安全性,SAE设计多层沙盒来保证用户应用之间的隔离性。参考下图:
最内层的就是用户代码,大部分PHP代码不需要做任何修改就可以跑在SAE平台上。小部分代码需要做一些修改以适应SAE的平台特性。这主要有,SAE因为安全性禁用了本地IO,所以fwrite等函数需要修改为使用TmpFD读写本地临时文件或者直接通过Storage服务读写我们的分布式文件存储。
PHP Zend为标准的PHP官方解释器。
SAE Zend Sandbox为一个逻辑概念,为用户的代码运行提供良好的隔离性。这里有两个层面:
1、是通过标准的phpini,我们设定了一些特殊配置和禁用函数;
2、为了达到一些phpini无法实现的沙盒功能,我们对Zend解释器核做了一些改进,以便通过用户标识将资源进行隔离。另外我们还把一些SAE的特定服务也在Zend层做了融合。
Apache为标准的Apache Web Server。不过我们禁用了htaccess,并提供了自己实现的替换方案AppConfig。用户可以通过类自然语言的方式编写AppConfig,如- compress: if(out_header[Content-Length] >= 500) compress 表示按条件启动页面压缩。AppConfig提供的功能有:目录默认页面、自定义错误页面、压缩、页面重定向、页面过期、设置响应头的content-type、设置页面访问权限。我们选择自行实现AppConfig还有一个考虑,就是因为传统Apache的htaccess因为要按目录递归方式合并配置文件,效率不能满足SAE的需求。
HTTP Server沙盒为Apache的安全可靠运行提供了多种保护功能,比如防止某个用户恶意占用连接数从而导致整个Web服务不正常。
最外层的是标准POSIX环境,我们的服务跑在Linux上。
接着将详细讨论我们架构设计的特点。
·扩展性
扩展性是分布式系统的两个主要目的之一,SAE作为公有云计算,同样把服务的扩展性作为架构设计的重要指标,要求在用户增长、压力提升的情况下,可以实现自动的服务扩展,同样的当压力降低时,可以将服务收缩,以节约资源,整个过程无需人工参与。SAE人工只需做好容量规划和管理。国外的公有云计算架构的扩展性主要有两个思路:
静态扩展,用户和资源有强绑定关系。最典型的例子为亚马逊的EC2和Ruby云计算平台Heroku,用户申请的资源和用户有严格的一对一关系,换句话说,A用户申请的虚拟机在A退还资源前,B用户不能使用,哪怕A用户的虚拟机处于闲置状态。
动态扩展,用户和资源没有强绑定关系。最典型的例子为Google App Engine,用户申请的资源和用户没有严格的一对一关系,换句话说,处理A用户请求的进程在处理完之后,可以马上处理B用户的请求。
两种扩展性各有利弊,静态扩展的长处是为平台提供了良好的隔离性,资源可以固定的映射在某个用户下,但缺点是资源利用率不高;动态扩展的长处是资源利用率高,这样整个云计算平台的成本会很低,但缺点是对隔离性有更高的要求,因为资源可以在很短的时间被多个用户使用。相比较,在安全性上,动态扩展要比静态扩展的技术门槛更高。
在SAE平台上,我们采用以动态扩展为主,静态扩展为辅的兼而有之的设计。在Web计算池层,是典型的动态扩展,没有一个用户独占Web服务进程,而是所有用户以共享的方式使用Web服务进程,通过Cache,热的用户自然在缓存层占据更多的位置。而在SAE的某些服务中,扩展性又是以静态扩展的方式展现,如RDC(Relational DB Cluster)分布式数据库集群,当用户申请了MySQL服务,我们就会在RDC后端根据SLA的级别创建一主多从的DB给用户,在用户显式的删除该DB前,该DB都不会被别人使用。当然,通过RDC,任何一个用户也无需知道后端DB的实际地址,只需访问RDC统一的host和port即可。
·高可靠性
HA是分布式系统的另一个主要目的,SAE同样以提供服务的高可靠性为架构设计的重要指标。HA的实现途径主要有两个,一个是硬件保证,一个是架构的冗余设计。
在SAE平台上,所有服务器都是新浪标准采购的硬件设备,运行在国内最好机房内,并进行多机房容灾,网络资源方面则享用门户网站所使用的带宽环境。另外,所有的硬件设备都有专门的运维部门负责,故障的响应速度和新浪内部服务一样。
在架构设计上,SAE通过对所有服务都进行冗余设计来提供服务的高可靠性。这里的服务可以分成计算型和数据型两种类别讨论:
针对计算型程序,冗余设计就是程序在多节点运行。但这样会带来一致性问题,最主要的困扰就是选举问题,如何在多个节点中选出一个主节点来执行。比如SAE上的分布式定时服务Cron,采用多点部署方式,多个计算节点相互隔离,通过时钟同步服务同时触发用户设定的定时任务,但要求只能有一个节点负责执行。为了解决这个问题,SAE设计出了一套分布式锁算法来提供选举服务。该算法可以在牺牲某些特定条件下的一致性来提供比Paxos算法更高的可靠性(3台机器在最高任意2台机器发生故障的情况下整个选举过程仍然正常,而Paxos算法最多容忍1台)。截止至2012年12月该算法正在申请专利,并广泛应用在SAE内部。
针对数据型服务,SAE主要是通过复制来保证服务的高可靠性。SAE上的数据存储服务普遍采用被动复制和主动复制两种方式。如SAE上MySQL之间的主从Binlog同步就是典型的被动复制,TaskQueue、DeferredJob等服务也采用被动复制的方式,用户的任务描述会写到到主内存级队列中,主队列利用后台线程将写操作同步到从队列上,一旦主队列发生故障,从队列会快速的切换为主队列。另外SAE上也有部分服务采用主动复制(双写复制)的方式来保证HA,比如Cron,当用户通过App的工程配置文件appconfigyaml设定定时任务时,任务信息会以双写的方式写到多个持久化DB中,以供后续的到时触发。
另外,SAE在整体架构设计时,充分考虑服务之间的“优雅降级”,尽量降低服务之间的耦合度,我们要求任何一个服务都不要假设其他服务是可靠的。SAE平台上的所有服务均不存在单点设计,服务的平均HA在9995%,即年平均服务不可用时间在4到5个小时之间。
线路特性
·平台出口IP:
220181129126
220181129121
220181136229
220181136230
http接口方需要IP授权可以进行相应的设置。
微服务¹架构的目标是帮助工程团队更快,更安全,更高质量地交付产品。解耦服务允许团队快速迭代,对系统的其余部分影响最小。
在Medium,我们的技术堆栈始于2012年的单片Nodejs应用程序。我们已经构建了几个卫星服务,但我们还没有制定一个系统地采用微服务架构的策略。随着系统变得越来越复杂并且团队不断发展,我们在2018年初转向了微服务架构。在这篇文章中,我们希望分享我们有效地做到这一点并避免微服务综合症的经验。
首先,让我们花一点时间来思考微服务架构是什么,不是什么。 “微服务”是那些过载和混乱的软件工程趋势之一。这就是我们在Medium认为它是什么:
该定义包括三个微服务设计原则:
Three Principles of Modeling Microservices
当我们对微服务进行建模时,我们应该遵守所有三个设计原则。这是实现微服务架构全部潜力的唯一途径。错过任何一个都会成为反模式。
没有一个目的,每个微服务最终会做太多事情,成长为多个“单片”服务。我们不会从微服务架构中获得全部好处,我们也会支付运营成本。
如果没有松散耦合,对一个服务的更改会影响其他服务,因此我们无法快速安全地发布更改,这是微服务架构的核心优势。更重要的是,紧密耦合引起的问题可能是灾难性的,例如数据不一致甚至数据丢失。
如果没有高凝聚力,我们将最终得到一个分布式单片系统 - 一组混乱的服务,必须同时进行更改和部署才能构建单一功能。由于多个服务协调的复杂性和成本(有时跨多个团队),分布式单片系统通常比集中式单片系统差得多。
与此同时,了解 微服务不是什么 很重要:
在Medium,我们总是在做出重大产品或工程决策时会问“为什么现在?”这个问题。 “为什么?”是一个显而易见的问题,但它假设我们拥有无限的人,时间和资源,这是一个危险的假设。当你想到“为什么现在?”时,你突然有了更多的限制 - 对当前工作的影响,机会成本,分心的开销等等。这个问题有助于我们更好地优先考虑。
我们现在需要采用微服务的原因是我们的Nodejs单片应用程序已经成为多个方面的瓶颈。
首先,最紧迫和最重要的瓶颈是其性能。
某些计算量很大且I / O很重的任务不适合Nodejs我们一直在逐步改进整体应用程序,但事实证明它是无效的。它的低劣性能使我们无法提供更好的产品而不会使已经非常慢的应用程序变慢。
其次,整体应用程序的一个重要且有点紧迫的瓶颈是它会减慢产品开发速度。
由于所有工程师都在单个应用程序中构建功能,因此它们通常紧密耦合。我们无法灵活地改变系统的一部分,因为它也可能影响其他部分。我们也害怕做出重大改变,因为影响太大,有时难以预测。整个应用程序作为一个整体进行部署,因此如果由于一次错误提交导致部署停滞,那么所有其他更改(即使它们完全正常工作)也无法完成。相比之下,微服务架构允许团队更快地发货,学习和迭代。他们可以专注于他们正在构建的功能,这些功能与复杂系统的其余部分分离。更改可以更快地进入生产。他们可以灵活地安全地尝试重大变革。
在我们新的微服务架构中,更改会在一小时内完成生产,工程师不必担心它会如何影响系统的其他部分。该团队还 探索 了在开发中安全使用生产数据的方法²多年来一直是白日梦。随着我们的工程团队的发展,所有这些都非常重要。
第三,单一应用程序使得难以为特定任务扩展系统或隔离不同类型任务的资源问题。
使用单一的单一应用程序,我们必须扩展和缩小整个系统,以满足更多资源需求的任务,即使这意味着系统过度配置用于其他更简单的任务。为了缓解这些问题,我们对不同类型的请求进行分片,以分离Nodejs进程。它们在一定程度上起作用,但不会扩展,因为这些微单一版本的单片服务是紧密耦合的。
最后但同样重要的是,一个重要且即将成为紧迫的瓶颈是它阻止我们尝试新技术。微服务架构的一个主要优点是每个服务都可以使用不同的技术堆栈构建,并与不同的技术集成。这使我们能够选择最适合工作的工具,更重要的是,我们可以快速安全地完成工作。
采用微服务架构并非易事。它可能会出错,实际上会损害工程生产力。在本节中,我们将分享七个在采用早期阶段帮助我们的策略:
有人可能会认为采用新的服务器架构意味着产品开发的长时间停顿以及对所有内容的大量重写。这是错误的做法。我们永远不应该为了建立新的服务而建立新的服务。每次我们建立新服务或采用新技术时,都必须具有明确的产品价值和/或工程价值。
产品价值应以我们可以为用户提供的利益为代表。与在单片Nodejs应用程序中构建值相比,需要一项新服务来提供值或使其更快地交付值。工程价值应该使工程团队更好,更快。
如果构建新服务没有产品价值或工程价值,我们将其留在单一的应用程序中。如果十年内Medium仍然有一个支持某些表面的单片Nodejs应用程序,那就完全没了问题。从单一应用程序开始实际上有助于我们战略性地对微服务进行建模。
建立具有明确价值的新服务
有人可能会认为采用新的服务器架构意味着产品开发的长时间停顿以及对所有内容的大量重写。这是错误的做法。我们永远不应该为了建立新的服务而建立新的服务。每次我们建立新服务或采用新技术时,都必须具有明确的产品价值和/或工程价值。
产品价值应以我们可以为用户提供的利益为代表。与在单片Nodejs应用程序中构建值相比,需要一项新服务来提供值或使其更快地交付值。工程价值应该使工程团队更好,更快。
如果构建新服务没有产品价值或工程价值,我们将其留在单一的应用程序中。如果十年内Medium仍然有一个支持某些表面的单片Nodejs应用程序,那就完全没了问题。从单一应用程序开始实际上有助于我们战略性地对微服务进行建模。
单片持久存储被认为是有害的
建模微服务的很大一部分是对其持久数据存储(例如,数据库)进行建模。跨服务共享持久数据存储通常似乎是将微服务集成在一起的最简单方法,然而,它实际上是有害的,我们应该不惜一切代价避免它。这就是原因。
首先,持久数据存储是关于实现细节的。 跨服务共享数据存储会将一个服务的实现细节暴露给整个系统。如果该服务更改了数据的格式,或者添加了缓存层,或者切换到不同类型的数据库,则还必须相应地更改许多其他服务。 这违反了松散耦合的原则。
其次,持久数据存储不是服务行为,即如何修改,解释和使用数据 。如果我们跨服务共享数据存储,则意味着其他服务也必须复制服务行为。 这违反了高内聚的原则 - 给定域中的行为泄露给多个服务。如果我们修改一个行为,我们将不得不一起修改所有这些服务。
在微服务架构中,只有一个服务应该负责特定类型的数据。所有其他服务应该通过负责服务的API请求数据,或者保留数据的 只读非规范(可能具体化)副本 。
这可能听起来很抽象,所以这是一个具体的例子。假设我们正在构建一个新的推荐服务,它需要来自规范帖子表的一些数据,目前在AWS DynamoDB中。我们可以通过两种方式之一为新推荐服务提供发布数据。
在单片存储模型中,推荐服务可以直接访问单片应用程序所执行的相同持久存储。这是一个坏主意,因为:
缓存可能很棘手。 如果推荐服务与单一应用程序共享相同的缓存,我们也必须在推荐服务中复制缓存实现细节;如果推荐服务使用自己的缓存,当单片应用更新帖子数据时,我们将不知道何时使其缓存无效。
如果单片应用程序决定更改为使用RDS而不是DynamoDB来存储帖子数据,我们将不得不重新实现推荐服务中的逻辑以及访问帖子数据的所有其他服务。
单片应用程序具有解释帖子数据的复杂逻辑 ,例如,如何确定帖子是否应该对给定用户不可见。我们必须在推荐服务中重新实现这些逻辑。一旦整体应用程序更改或添加新逻辑,我们也需要在任何地方进行相同的更改。
即使推荐服务是自己的数据访问模式的错误选项,推荐服务仍然停留在DynamoDB上。
在解耦存储模型中,推荐服务不能直接访问发布数据,也不能直接访问任何其他新服务。发布数据的实现细节仅保留在一个服务中。有不同的方法来实现这一目标。
Option A 理想情况下,应该有一个拥有帖子数据的Post服务,其他服务只能通过Post服务的API访问邮政数据。但是,为所有核心数据模型构建新服务可能是一项昂贵的前期投资。
当人员配置有限时,还有一些更实用的方法。根据数据访问模式,它们实际上可能是更好的方式。
在 选项B 中,单一应用程序可让推荐服务知道何时更新相关的帖子数据。通常,这不必立即发生,因此我们可以将其卸载到排队系统。
在 选项C 中,ETL管道生成推荐服务的发布数据的只读副本,以及可能对推荐有用的其他数据。在这两个选项中,推荐服务完全拥有其数据,因此它可以灵活地缓存数据或使用最适合的数据库技术。
解耦“建立服务”和“运行服务”
如果构建微服务很难,那么运行服务往往更难。 当运行服务与构建每个服务相结合时,它会减慢工程团队的速度,团队必须不断重新发明这样做。我们希望让每项服务都专注于自己的工作而不用担心如何运行服务的复杂问题,包括网络,通信协议,部署,可观察性等。服务管理应该与每个服务的实现完全分离。
由于最近在 容器化,容器编排,服务网格,应用程序性能监 控等方面的技术进步,“运行服务”的解耦变得比以往更容易实现。
网络。 网络(例如,服务发现,路由,负载平衡,流量路由等)是运行服务的关键部分。传统方法是为每种平台/语言提供库。它工作但不理想,因为应用程序仍然需要非常繁琐的工作来集成和维护库。通常,应用程序仍然需要单独实现某些逻辑。现代解决方案是在Service Mesh中运行服务。在Medium,我们使用 Istio和Envoy作为边车代理 。构建服务的应用工程师根本不需要担心网络问题。
通信协议 。无论您选择哪种技术堆栈或语言来构建微服务,从一个高效,类型化,跨平台且需要最少开发开销的成熟RPC解决方案开始是非常重要的。支持向后兼容性的RPC解决方案也使部署服务更加安全,即使它们之间存在依赖关系。在Medium,我们选择了gRPC。
一种常见的替代方案是基于HTTP的REST + JSON,它长期以来一直是服务器通信的福音解决方案。但是,尽管该堆栈非常适合浏览器与服务器通信,但它对于服务器到服务器的 通信效率很低 ,尤其是当我们需要发送大量请求时。如果没有自动生成的 存根和样板代码 ,我们将不得不手动实现服务器/客户端代码。可靠的RPC实现不仅仅包装网络客户端。另外,REST是“自以为是”,但总是让每个人都对每个细节都达成一致很困难,例如,这个调用真的是REST,还是只是一个RPC?这是一种资源还是一种操作?等等
部署。 拥有一致的方法来构建,测试,打包,部署和管理服务非常重要。所有Medium的微服务都在容器中运行。目前,我们的编排系统是AWS ECS和Kubernetes的混合体,但仅限于Kubernetes。
我们构建了自己的系统来 构建,测试,打包和部署 服务,称为BBFD。它在一致地跨服务工作和为个人服务提供采用不同技术堆栈的灵活性之间取得平衡。它的工作方式是让每个服务提供基本信息,例如,要监听的端口,构建/测试/启动服务的命令等,BBFD将负责其余的工作。
彻底和一致的可观察性
可观察性包括允许我们了解系统如何工作的过程,约定和工具,以及在不工作时对问题进行分类。可观察性包括日志记录,性能跟踪,指标,仪表板,警报,并且对于微服务架构的成功至关重要。
当我们从单个服务迁移到具有许多服务的分布式系统时,可能会发生两件事:
我们失去了可观察性,因为它变得更难或更容易被忽视。
不同的团队重新发明了轮子,我们最终得到了零碎的可观察性,这实际上是低可观察性 ,因为很难使用碎片数据连接点或分类任何问题。
从一开始就具有良好且一致的可观察性非常重要,因此我们的DevOps团队提出了一致的可观察性策略,并构建了支持实现这一目标的工具。每项服务都会自动获取详细的DataDog仪表板,警报和日志搜索,这些服务在所有服务中也是一致的。我们还大量使用LightStep来了解系统的性能。
并非每一项新服务都需要从零开始构建
在微服务架构中,每个服务都做一件事并且做得非常好。请注意,它与如何构建服务无关。如果您从单一服务迁移,请记住,如果您可以从单片应用程序中剥离微服务并不总是必须从头开始构建。
在这里,我们采取务实的态度。我们是否应该从头开始构建服务取决于两个因素:(1)Nodejs适合该任务的程度如何;(2)在不同的技术堆栈中重新实现的成本是多少。
如果Nodejs是一个很好的技术选项并且现有的实现很好,我们将代码从单片应用程序中删除,并用它创建一个微服务。即使采用相同的实现,我们仍将获得微服务架构的所有好处。
我们的单片Nodejs单片应用程序的架构使我们可以相对轻松地使用现有实现构建单独的服务。我们将在本文稍后讨论如何正确构建单片。
尊重失败,因为他们会发生
在分布式环境中,更多的东西可能会失败,而且它们会失败。如果处理不当,任务关键型服务的失败可能是灾难性的。我们应该始终考虑如何测试故障并优雅地处理故障。
从第一天起避免使用微服务综合症
微服务不是灵丹妙药 - 它解决了一些问题,但创造了一些其他问题,我们将其称为“微服务综合症”。如果我们从第一天开始就不去考虑它们,那么事情会变得很快,如果我们以后再照顾它们会花费更多。以下是一些常见症状。
随着最近的技术创新,采用微服务架构要容易得多。这是否意味着我们都应该停止构建单一服务?
虽然新技术支持得更好,但微服务架构仍然存在高度复杂性和复杂性。 对于小型团队来说,单一的应用程序通常仍然是更好的选择。但是,请花些时间来构建单片应用程序,以便以后在系统和团队成长时更容易迁移到微服务架构。
在Medium,我们在早期的单片应用程序中做出了一些很好的架构决策。
我们的单片应用程序由组件高度模块化,即使它已经发展成为一个非常复杂的应用程序,包括Web服务器,后端服务和离线事件处理器。脱机事件处理器单独运行,但使用完全相同的代码。这使得将一大块业务逻辑剥离到单独的服务相对容易,只要新服务提供与原始实现相同(高级)的接口即可。
我们的整体应用程序在较低级别封装了数据存储详细信息。每种数据类型(例如,数据库表)具有两层实现:数据层和服务层。
这有助于我们采用微服务架构,因为一种类型数据的实现细节完全隐藏在代码库的其余部分。创建新服务来处理某些类型的数据相对容易且安全。
单片应用程序还可以帮助我们对微服务进行建模,并使我们能够灵活地专注于系统中最重要的部分,而不是从头开始为所有微服务建模。
单片Nodejs应用程序为我们服务了好几年,但它开始减慢我们从运送伟大的项目和快速迭代。我们开始系统地和战略性地采用微服务架构。我们仍处于这一旅程的早期阶段,但我们已经看到了它的优势和潜力 - 它大大提高了开发效率,使我们能够大胆地思考并实现大量的产品改进,并解锁了工程团队以安全地测试新技术。
加入Medium的工程团队是一个激动人心的时刻。如果这听起来很有趣,请查看我们的工作页面 - 在Medium工作。如果您对微服务架构特别感兴趣,您可能需要先了解这两个开头:高级全栈工程师和高级平台工程师。
原文 :https://mediumengineering/microservice-architecture-at-medium-9c33805eb74f
讨论: 请加入知识星球首席架构师圈
初始阶段的网站架构
大型网站都是从小型网站发展而来,网站架构也是一样,是从小型网站架构逐步演化而来,小型网站最开始没有太多人访问,只需要一台服务器就绰绰有余,这时的网站架构如图。
应用程序,数据库,文件等所有的资源都在一台服务器上。通常服务器操作系统使用Linux,应用程序使用PHP开发,然后部署在Apache上,数据库使用MySql,汇集各种开源软件及一台廉价服务器就可以开始网站的发展之路了。
应用服务和数据服务分离
随着网站业务的发展,一台服务器逐渐不能满足需求:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足,这时就需要将应用和数据分离,应用和数据分离后整个网站使用三台服务器:应用服务器,文件服务器和数据库服务器,如下图所示,这三台服务器对硬件资源的要求各不相同,应用服务器需要处理大量的业务逻辑,因此需要更快更强大的CPU,数据库服务器需要快速磁盘检索和数据缓存,因此需要更快的硬盘和更大的内存,文件服务器需要储存大量用户上传的文件,因此需要更大的硬盘。
应用和数据分离后,不同特性的服务器承担不同的服务角色,网站的并发处理能力和数据存储空间得到了很大改善,支持网站业务进一步发展,但是随着用户逐渐增多,网站又一次面临挑战:数据库压力太大导致访问延迟,进而影响整个网站的性能,用户体验受到影响,这时需要对网站架构进一步优化。
使用缓存改善网站性能
网站访问特点和现实世界的财富分配一样遵循二八定律:80%的业务访问集中在20%的数据上。淘宝买家浏览的商品集中在少部分成交数多、评价良好的商品上;百度搜索关键词集中在少部分热门词汇上;经常登录的用户才会发微博、看微博,而这部分用户也只占总用户数目的一小部分。
既然大部分的业务访问集中在,那么如果把这一小部分数据缓存在内存中,就可以减少数据库的访问压力。网站使用的缓存分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存。本地缓存的访问速度更快一些,但是受应用服务器内存限制,其缓存数量有限,而且会出现和应用程序争用内存的情况。远程分布式可以使用集群的方式,部署大内存的服务器作为专门的缓存服务器,可以在理论上做到不受内存容量限制的缓存服务。
使用缓存后,数据访问压力得到有效缓解,但是单一应用服务器能够处理的请求连接有限,在网站的访问高峰期,应用服务器会成为整个网站的瓶颈。
使用应用服务器集群改善网站的并发处理能力
使用集群是网站解决高并发,海量问题的常用手段,当一台服务器的处理能力、储存空间不足时,不要企图去换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求,这种情况下,更恰当的做法是增加一台服务器分担原有服务器的访问及存储压力。
对网站而言,只要能通过一台服务器的方式改善负载压力,就可以以同样的方式持续增加服务器不断改善系统性能,从而实现系统的可伸缩性,应用服务器实现集群是网站可伸缩集群架构设计中较为简单成熟的一种。如下图所示。
通过负载均衡调度服务器,可将来自用户浏览器的请求分发到应用服务器集群中的任何一台服务器上,如果有更多的用户,就在集群中加入更多的应用服务器,使应用服务器的负载压力不在成为网站的瓶颈。
数据库读写分离
网站使用缓存后,大部分数据操作访问都可以不通过数据库就能完成,但是仍有一部分读操作,(缓存访问不命中、缓存过期)和全部的写操作,需要访问数据库,在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈。
目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。网站利用数据库的这一功能,实现数据库读写分离,从而改善数据库负载压力。
应用服务器在写数据的时候,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库,这样当应用服务器读数据的时候,就可以通过从数据库或得数据。为了便于应用程序访问读写分离后的数据库,通常在应用服务器端使用专门的数据访问模块,使数据库读写分离时对应用透明。
使用反向代理和CDN加速网站响应
CDN和反向代理的基本原理都是缓存,区别在于CDN部署在网络提供商的机房,是用户在请求网站服务时,可以从距离自己最近的网路提供商机房获取数据;而反向代理则部署在网站的中心机房,当用户请求到达中心机房后,首先访问的服务器是反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接给用户。
使用分布式文件系统和分布式数据库系统
分布式数据库是网站数据库拆分的最后手段,只有在单表数据规模非常庞大的时候才使用,不到万不得以时,网站更常用的数据库拆分手段是业务分库,将不同业务的数据库部署在不同的物理服务器上。
使用NOSQL和搜索引擎
对于海量数据的查询,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb和redis,搜索引擎有lucene。
业务拆分
随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者同享数据库来实现
分布式服务
这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。淘宝的Dubbo是一个不错的选择
0条评论