【技术·真相】微服务的状态管理

我们都被告知,并且倾向于认为,失败是一件不好的事情。

本次我们来开一个新坑,聊聊服务器分布式架构的那点事 。首先看看微服务管理中的服务依赖管理。

微服务

经典的分布式架构是典型三层架构

各层各司其职:

  1. 负载均衡服务器接受大量客户端的连接
  2. 应用服务器集群处理客户端的逻辑请求
  3. 存储层在最后,供应用服务器存储数据,存储层往往又分为缓存和数据库,需要一定的缓存策略保证数据的写入性能和一致性

随着项目规模的提升和理念发展,原有经典架构遇到了问题

  • 项目规模提升,一个大团队可能几十、几百甚至上千人,不太可能将所有业务放在一个应用服务中处理,怎么合作开发,提高开发效率是个大问题
  • 不同团队熟悉的技术栈和语言不同,需要有区分又要能合作
  • 产品面对的用户数量庞大,业务众多,客观上需要从业务上进行拆分,出问题时不能影响所有业务及所有用户

于是,满足这些需求的微服务出现。

有了微服务:

  • 大的团队可以各自负责一部分服务,互相之间没有耦合
  • 不同团队可以使用不同的语言或技术栈,通过网络来互相通信
  • 部分服务出现问题,不影响其他服务,也只影响一部分用户

游戏服务器在做架构设计的时候也大量应用了微服务的思想。

服务器可以将很多功能拆成了一个个微服务,各个微服务组合给玩家提供服务,典型的有 game、battle、guild、social、rank、name、mail 等,分别提供基础游戏逻辑、战斗、工会、社交、排行、名字、邮件服务。

微服务架构解决了我们上面提到的问题,但是其本身也新增了一堆问题,而对于这些新增的问题,还会衍生出更多的子问题,这就需要我们不断地用各式各样的技术和手段来解决这些问题。所谓任何技术方案都不会是银弹,都是处理问题的 trade-off:权衡。

本文要讨论的依赖管理就是其中的一个问题:

在之前的经典分层分布式架构中,应用服务器内部的状态由其构成的多个模块来做协调,都是在服务内部;

到了微服务架构中,服务之间是相互独立的,微服务之间需要通过网络通信来等待或者通知自身的状态,可能会有互相依赖的情况,这就需要依赖管理。

微服务状态

一个微服务进程对外服务之前,需要做一些事情,在这些事情做完之后才可以正常服务。在做每件事情时,就会处于不同的状态。

一个典型的微服务在其整个生命周期内的状态可能有:

  1. 初始状态
  2. 等待服务状态。因为有个进程涉及主备,备进程通常处于等待状态。
  3. 组网状态
  4. 等待依赖的服务状态
  5. 加载数据状态
  6. 可服务状态
  7. 热更新状态
  8. 准备下线状态
  9. 停止服务状态

为什么要设计不同状态呢?

  • 比如微服务之间 TCP 连接组网还未完成,如果要去 DB 微服务加载需要的数据,必然失败;

  • 某微服务还未进入可对外服务状态,其他服的请求就过来了,很可能发生异常;

  • 某 A 微服务依赖的 B、C 微服务还未启动或未准备好,从 A 到 B、C 的请求,必然失败或异常;

  • 整个服务器系统还未进入可对外服务状态,玩家进来了,很可能发生异常;

依赖管理

微服务之间是存在依赖关系的。

举个很简单的例子,gateserver 是网关服务器,在对玩家开放之前,必须等待 gameserver 处于可服务状态。因此我们可以配置其依赖关系:

类似的,gameserver 上承担主逻辑,其上的玩法依赖于其他微服务,如战斗服务、工会服务、邮件服务、数据存储服务等。

如何查询以及标记依赖关系呢?

比较直观的想法是直接通过消息来发起查询及同步。

但是,很多服务不是直连的,可能通过 proxy 转发,发消息及互相同步(如 gossip 协议)会比较繁琐。

一个比较合理的方式是借助公用的第三方组件来做同步。我们可以借助服务发现组件(之后的文章会讨论),不管什么服务及互相之间的连接关系,都统一向服务发现写入自己及定时查询所依赖的服务的状态:

状态切换流程

单个微服务内部状态的切换流程如下:

业务钩子

进程状态的流程切换是统一的,不可更改。

很多情况下,上层的业务也需要依赖该微服务当前的状态:例如,一个模块可能需要知道什么时间适合去发起该模块的数据拉取请求。

为了方便业务使用,各个状态在进入前,会提供业务钩子(hook) 给各个业务订阅自己要做的逻辑。例如:

Data 订阅自己的表格同步逻辑:

Go 复制代码
commonfsm.SubscribeLoad(func() error {
    // load data logic
    ...
})

Game 订阅对外服务时的逻辑:

C++ 复制代码
CCommonFsm::Instance()->SubscribeInService([] {
    // logic business, timer logic
    // ...
})

好了,有关微服务中的服务依赖管理,我们就说这么多,希望能为你提供一点参考。希望你方便的话点个免费的赞,感谢!

作者:我是码财小子,会点编程代码,懂些投资理财;期待你的关注,不要错过我后续的文章更新。

相关推荐
monkey_meng19 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马22 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng25 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
Gemini19951 小时前
分布式和微服务的区别
分布式·微服务·架构
paopaokaka_luck5 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
码农小旋风6 小时前
详解K8S--声明式API
后端
Peter_chq6 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml47 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~7 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616887 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端