文档章节

无状态服务

商者
 商者
发布于 2017/07/25 20:21
字数 2734
阅读 11
收藏 1
点赞 0
评论 0

数据服务,正如其名,可以向应用提供数据存储与访问的服务。

比如一个游戏场景服务器,可以在玩家进入的时候,向数据服务请求该玩家的数据。逻辑中处理不同玩家的数据交互,修改不同玩家的数据,然后以一定策略再将数据存回数据服务。

同理如一个web应用服务器, client 发一个请求,应用向数据服务请求数据,修改数据,应用向数据服务存回数据。

换言之,如果把服务端看作一个整体,数据服务维护的是client在服务端的状态。

但是,我们之前实现的数据服务可以提供更强大的抽象能力。

我们的数据服务的API结构可以任意定制,基于ORM和代码自动化生成实现了code-first,而且数据服务依赖的基础设施——redis又被证明非常强大:不仅仅是性能极佳,而且提供了多种数据结构抽象。

那么,数据服务是否能在维护client状态之外仍有用武之地?

在web开发中,用缓存维护服务状态是一种很常规的开发思路。 而在游戏服务端开发中,由于场景服务的存在,这种思路通常并不靠谱。

为什么要用数据服务维护其他服务状态?

考虑这样一个问题:

如果服务的状态维护在服务进程中,那么服务进程挂掉,状态就不存在了。但是对于我们来说,服务的状态是比服务进程本身更加重要的——因为进程挂了可以立刻重启,哪怕耽误个1、2s,但是状态没了却意味着这个服务在整个分布式服务端中所提供的语义已经不正确了,即使瞬间就重启好了也没用。

那么为了让服务进程挂掉时不会导致服务状态丢掉,只要分离服务进程的生命周期和服务状态的生命周期就可以了。

这种服务其实就是无状态服务(stateless service)。

贴一下wiki:

Service statelessness is a design principle that is applied within the service-orientation design paradigm, in order to design scalable services by separating them from their state data whenever possible. 

好处:

This results in reduction of the resources consumed by a service as the actual state data management is delegated to an external component or to an architectural extension.

两个关键点: design scalable services, reduction of the resources consumed。

其实描述的是同一个意思,以无状态为原则设计服务可以让服务的横向扩展成本降到最低。

对于web开发程序员来说,无状态服务并不是什么新鲜事,甚至因为无状态服务的一些弊端而改用有状态服务(stateful service)。不过,我们今天并不讨论哪一种更好,只讨论 无状态服务 更适合 什么情景。

无状态服务的实现方式有很多种,在一些C++主导的互联网公司,通常是借助共享内存实现——通过将 服务状态维护在共享内存里,实现服务进程与服务状态的分离。 但是这种做法扩展性不强,很难跨物理机,而且共享内存就这样一个文件安全性很难保障。

很多只接触过游戏服务端的同学并不了解无状态服务,毕竟一直写的是交互性极强的场景服务,而且遇事首先想到的是热更新,不知道其他的hotfix方式。

之前小说君跟有些同事讨论无状态服务,发现对方还会产生相当程度的误解,把「无状态服务」与「无状态客户端」混为一谈。 无状态的游戏客户端意味着网络通信的成本跟内存数据访问的成本一样低——这当然是不可能实现的。

无状态服务就是为了scalability而出现的,无状态服务横向扩展的能力相比于有状态服务大大增强,同时实现负载均衡的成本又远低于有状态服务。

设计分布式系统时,我们无法兼顾一致性C、响应性能A,以及分区容错P。无状态服务更倾向于CP,有状态服务更倾向于AP。但是,即使是现在(比如借助各种一致性协调组件,或者gossip protocol),有状态服务的P与无状态服务的P所能达到的程度是不一样的,后者是真的容错,前者只能做到不把鸡蛋放在一个篮子里。

游戏中可以拆分为无状态服务的业务情景其实有很多,基本上所有服务间交互需求都可以实现为无状态服务。比如切场景服务,因为切场景的请求是有限的,对时延的要求也不会特别高,同理的还有分配房间服务;或者是面向客户端的IM服务、拍卖行服务等等。

回到一开始的问题, 我们可以将服务状态存放在外部设施中,比如数据服务。

数据服务,可以转移无状态服务的状态维护成本,让无状态服务横向扩展的能力更强大。因为状态维护在数据服务中,所以无状态服务开多少个都无所谓。因此无状态服务非常适合计算密集的业务需求。

实际上,我们讲面向微服务,讲服务划分,要解决的根本问题就是让程序员能清楚自己定义每种服务的意图是什么,请求响应式服务、数据同步式服务、流处理式服务,消息流与业务对CAP的需求决定了服务更适合做成无状态还是有状态。

举个游戏开发的例子,假设业务情景是比较常见的全球同服类游戏,那游戏的每种服务理应是由分布式的多个节点共同提供服务,如果服务的消息流是典型的请求响应式,那么实现为无状态服务就更合适:

  • 请求上来,取相关数据,处理,直接返回。整个状态的生命周期保持在一次RPC调用过程中,这描述的就是请求响应的工作方式。

  • 不论是自己开发load balancer,还是用现成的消息broker(比如前篇文章说的RabbitMQ),对无状态服务做 round-robin work distribution都非常简单。

  • 而且,无状态服务本质上是没有扩容成本的,波峰就多开,波谷就少开。

程序员可以为不同服务规划不同的横向扩展方式。对于无状态服务,横向扩展的触发条件就是现在请求数量级或者是节点压力;对于有状态服务,横向扩展就需要借助第三方的服务作为仲裁者,而这个仲裁者可以实现为无状态服务。

当然,无状态服务并不是万能的。 画图解释,有状态服务A与B:

最常见的组织形式,每个有状态服务都是一个进程。

无状态服务A:

其中,节点A与节点B都是无状态服务A的一个实例。

从这两张图就能简单看出, 无状态服务只是把无状态性( statelessness )从服务中独立出来。

好处自然是如前面所说,将进程的生命周期与状态的生命周期解耦,而且我们现在把共享状态寄存在数据服务,那只需要保证数据服务高可用,所有的无状态服务都能高可用。相反,如果是有状态服务想提供高可用保证,就需要各自实现高可用机制。

但是,无状态服务还有两点弊端:

  1. 节点访问状态从进程内变为进程外,没了locality,造成了资源浪费。

  2. 由于操作同一client的数据的不再是唯一的节点,有可能形成数据的不一致(这点下篇文章再聊)。

这也是程序员的日常抉择之一:trade-off。

哪些服务需要设计为无状态服务,哪些服务需要设计为有状态服务,完全是业务需求决定的。两者的设计范式(design paradigm)完全不同。

  • 无状态服务描述的是数据流,Data Shipping。后果就是所有状态的访问与修改都增加了内网时延,因此对于游戏场景服务这种性能优先的服务是不可忍受的。

  • 有状态服务描述的是功能流,Function Shipping。数据具有强局部性,因此有状态服务非常适合场景同步这种交互密集的情景,交互的延迟仅仅是进程内方法调用的开销。

借助无状态服务,我们在架构中就可以逐步干掉类似切场景管理这种单点进程。无状态服务是天然高可用的——任意挂掉一个,仍然能持续提供服务。

整个服务端理论上应该具有整体持续提供服务的能力。也就是说,随便挂掉一个节点,不需要停服。游戏的场景服务挂掉一个节点,不会影响其他任何服务,只是该场景中的玩家短期内无法进行场景相关操作了而已。

而我们见过的大多数游戏服务端架构,处处皆单点,完全不能叫可用的架构。分布式系统中最忌增加额外的、不必要的单点。判断一整个游戏服务端是否具有可用性很简单,随便kill掉一个节点,如果服务端仍然能持续提供服务,即使是部分client受到了影响,也能称为是可用的。

小说君第一次尝试在MMO中应用无状态服务的时候,陷入沉思:游戏服务端的热更新,正确姿势应该是脚本语言reload(虚拟机语言通过改虚拟机实现函数级别的替换),还是web开发常用的进程重启?

现在能放文章跳转链接了,简单列一下服务端系列文章的链接,以及后续的主题(按顺序阅读更佳):

从零手写服务端框架

面向中间件的开发模式

如何快速搭建数据服务

面向微服务的服务端架构

以消息队列为中心的服务端架构

聊聊无状态服务(本篇)

转 http://www.tuicool.com/articles/reeMBbf

© 著作权归作者所有

共有 人打赏支持
商者

商者

粉丝 39
博文 141
码字总数 43255
作品 0
海淀
架构师
Linux--system的命令 服务状态

一、systemd 系统初始化程序,系统开始的第一个进程,pid为1 图示:systemd系统初始程序 二、systemctl 命令 systemctl list-units ##列出当前系统服务的状态,具体祥解见三服务状态 图示:当...

無緣 ⋅ 2017/10/23 ⋅ 0

端口号的分类

端口的分类 通俗地讲,端口(Port)就是电脑向网络开放的信息出入“门户”。和小区大门不同的是,在电脑上这种“门户”有个256×256(65535)个,而且它们还有多种状态。 1.端口的分类 根据端...

木木侠 ⋅ 2016/08/09 ⋅ 0

Hystrix熔断机制原理剖析

一、前言 在分布式系统架构中多个系统之间通常是通过远程RPC调用进行通信,也就是 A 系统调用 B 系统服务,B 系统调用 C 系统的服务。当尾部应用 C 发生故障而系统 B 没有服务降级时候可能会...

阿里加多 ⋅ 05/18 ⋅ 0

集群管理和容器编排工具--SwarmKit

SwarmKit是Docker公司开源的Docker集群管理和容器编排工具,其主要功能包括节点发现、基于raft算法的一致性和任务调度等。 基本概念 服务器上运行SwarmKit工具的swarmd命令后,即可将其加入到...

匿名 ⋅ 2016/06/20 ⋅ 0

领域驱动之无状态操作

这段时间一直在看DDD的东西,对domain层说到: domain service领域服务里是无状态stateless的操作 所有的状态stateful应该都在聚合根aggregate里 一个经典的带状态的类/服务是一个可以增加近...

BuWStudio ⋅ 2016/12/02 ⋅ 0

Docker 开源集群管理和容器编排工具 SwarmKit

最近Docker公司开源了Docker集群管理和容器编排工具SwarmKit,其主要功能包括节点发现、基于raft算法的一致性和任务调度等。 基本概念 服务器上运行SwarmKit工具的swarmd命令后,即可将其加入...

oschina ⋅ 2016/06/20 ⋅ 5

SaltStack实战之配置管理-状态间关系

SaltStack实战之配置管理-状态间关系 SaltStack实战之配置管理-状态间关系 1. 状态相关模块 2. 实际应用 1. 状态相关模块 1.1 pkg 状态模块:pkg 功能:管理软件包状态 常用方法: pkg.inst...

ygqygq2 ⋅ 2017/06/16 ⋅ 0

Oracle启动数据库过程中实例与线程思考

早期用Linux的时候,看Oracle监听状态和端口只是浏览一下,没有认真看过内容也是英文提示,时隔数载重新捡起Oracle,Windos下CMD查看监听状态发现很多有意思的问题,Oracle实例和线程很多不懂...

长路慢 ⋅ 2017/12/26 ⋅ 0

线程池服务程序设计

1)原理分析 线程池的核心设计思想是系统在初始化时,创建一定数量的服务线程,并使他们处于空闲状态,若当前有新用户到来,则系统先查找当前有无空闲线程,若有则立即为其分配服务线程,如没...

长平狐 ⋅ 2012/09/19 ⋅ 0

干货速递 ▎Kubernetes有状态集群服务部署与管理(上)

2016年12月2日-3日,ArchSummit2016全球架构师峰会在北京国际会议中心如期举行。时速云架构师张寿红应邀参加,并在微服务与容器实践专场做了《Kubernetes有状态集群服务部署与管理》的干货分...

时速云 ⋅ 2016/12/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

RabbitMQ学习以及与Spring的集成(三)

本文介绍RabbitMQ与Spring的简单集成以及消息的发送和接收。 在RabbitMQ的Spring配置文件中,首先需要增加命名空间。 xmlns:rabbit="http://www.springframework.org/schema/rabbit" 其次是模...

onedotdot ⋅ 24分钟前 ⋅ 0

JAVA实现仿微信红包分配规则

最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教。 算法介绍 一、红包金额限制 对于微...

小致dad ⋅ 36分钟前 ⋅ 0

Python 数电表格格式化 xlutils xlwt xlrd的使用

需要安装 xlutils xlwt xlrd 格式化前 格式化后 代码 先copy读取的表格,然后按照一定的规则修改,将昵称中的学号提取出来替换昵称即可 from xlrd import open_workbookfrom xlutils.copy ...

阿豪boy ⋅ 今天 ⋅ 0

面试题:使用rand5()生成rand7()

前言 读研究生这3 年,思维与本科相比变化挺大的,这几年除了看论文、设计方案,更重要的是学会注重先思考、再实现,感觉更加成熟吧,不再像个小P孩,人年轻时总会心高气傲。有1 道面试题:给...

初雪之音 ⋅ 今天 ⋅ 0

Docker Toolbox Looks like something went wrong

Docker Toolbox 重新安装后提示错误:Looks like something went wrong in step ´Checking if machine default exists´ 控制面板-->程序与应用-->启用或关闭windows功能:找到Hyper-V,如果处......

随你疯 ⋅ 今天 ⋅ 0

Guacamole 远程桌面

本文将Apache的guacamole服务的部署和应用,http://guacamole.apache.org/doc/gug/ 该链接下有全部相关知识的英文文档,如果水平ok,可以去这里仔细查看。 一、简介 Apache Guacamole 是无客...

千里明月 ⋅ 今天 ⋅ 0

nagios 安装

Nagios简介:监控网络并排除网络故障的工具:nagios,Ntop,OpenVAS,OCS,OSSIM等开源监控工具。 可以实现对网络上的服务器进行全面的监控,包括服务(apache、mysql、ntp、ftp、disk、qmail和h...

寰宇01 ⋅ 今天 ⋅ 0

AngularDart注意事项

默认情况下创建Dart项目应出现以下列表: 有时会因为不知明的原因导致列表项缺失: 此时可以通过以下步骤解决: 1.创建项目涉及到的包:stagehand 2.执行pub global activate stagehand或pub...

scooplol ⋅ 今天 ⋅ 0

Java Web如何操作Cookie的添加修改和删除

创建Cookie对象 Cookie cookie = new Cookie("id", "1"); 修改Cookie值 cookie.setValue("2"); 设置Cookie有效期和删除Cookie cookie.setMaxAge(24*60*60); // Cookie有效时间 co......

二营长意大利炮 ⋅ 今天 ⋅ 0

【每天一个JQuery特效】淡入淡出显示或隐藏窗口

我是JQuery新手爱好者,有时间就练练代码,防止手生,争取每天一个JQuery练习,在这个博客记录下学习的笔记。 本特效主要采用fadeIn()和fadeOut()方法显示淡入淡出的显示效果显示或隐藏元...

Rhymo-Wu ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部