引言

故事的起因是这样的,我们是一个算法工程团队,主要做的是将算法流程工程化,大多只有python基础,并未接触过微服务。目前面临一些问题,如:

  1. 我们的主服务越来越大,团队的人也流动了一波又一波,没人能完全了解全部代码
  2. 业务流程,算法框架以及hdfs等依赖都集中在主服务中,相互关联难以分离。每次启动主服务,还要保障算法框架的依赖和大数据平台的可用
  3. 配置文件繁多,不同的功能有不同的配置文件,相同的中间件(如:S3、ES等)有多出配置引用。
  4. 目前还是python2技术,官方已经宣布不再维护了,我们尝试升级python3,工程量很是巨大。
  5. 平台越大,我们的主服务约臃肿已经到了不破不立的时刻。

于是,我们考虑,将这个庞大的单体服务,一点点的做拆解替换,用一个个小服务来取代单体服务中的各个功能块。我们就想到了微服务的架构方式,准备尝试用其来解决我们当前的窘境。(注意:由于我们团队以python为主,并不像java、go那样拥有成熟的解决方案。)

单体服务

既然想改造,还是要直面我们的服务框架—单体服务,简单画了图示,方便更直观的说明。

结构图

优劣

  1. 优点
    1. 易于部署:只有一个server的软件包,很方便发布到服务器。
    2. 易于测试:一个服务启动就可系统测试。
  2. 缺点
    1. 维护成本大:服务过于庞大,任何一个bug都可能需要全组协调排障(没有人全面了解这个server了)。
    2. 交付周期长:任何小的迭代(极端情况,只修改了一行注释)要触发整个部署流水线,我们不得不先停止所有线上业务来完成上线操作。
    3. 技术选型成本高:功能依赖某一语言(这里是python)或框架,后期引入新语言、框架、技术成本高风险大。如:python2→python3 、flask → fastapi 要重构整个项目。
    4. 扩展性差:垂直扩展(加机器整体再启动个服务做负载)随着功能增加,成本越来越高。水平扩展(某一功能的性能扩展),由于单体服务全部功能位于一个进程,无法实现水平扩展。

微服务

为了解决单体服务所面临的窘境,我们决定尝试微服务方案,将功能拆分为一个个微服务,使用网关、注册中心、配置中心等,构建聚合服务,也就是实现原来单体服务的全部功能。以便在后续的开发中,每个功能点都能快速迭代,新的技术也能快速融入到我们的平台。

那么什么是微服务呢?

定义

wiki定义微服务: 微服务(英语:Microservices)是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic)的API集相互通信。

关键词:软件架构风格,小型功能区块,语言无关。

优劣

  1. 优点
    1. 拆分系统,降低单个服务复杂性:每个小团队(3-5人)可以独立完成的一个服务为一个小服务,根据功能、业务、领域等需求划分,团队内达成一致即可。这样再出现bug时,只需单个服务排查就好,无需整个团队配合。
    2. 独立进程:可独立部署,实现快速迭代和水平扩展。
    3. 轻量级通信,API隔离:不同服务间通过接口通信(http、tcp等),所以微服务可不采用统一语言或框架。
  2. 缺点
    1. 拆分力度把控:微服务只是结果,不是目的。我们的目的是有效的拆分应用,实现敏捷开发和部署。
    2. 增加代码复杂性:原本的查库操作,类间调用,可能要改为API调用。
    3. 增加数据存储难度:不同服务所使用的不同的数据库,需要处理好分布式事务。
    4. 增加测试复杂性:单体服务启动一个服务能解决的事,现在要启动一堆微服务。
    5. 性能受网络影响增大:服务间通过API调用。网络请求大大增加。

架构图

  1. 接入层:负载均衡作用
  2. 网关层:反向路由,安全验证,限流等
  3. 业务服务层:基础服务和聚合服务(业务服务、领域服务)
  4. 撑服务层
    • 支撑服务层提供非业务功能,以支撑业务服务层和网关层软件的正常运行。
    • 核心模块有服务注册发现、集中配置、容错限流、认证授权、日志聚合、监控告警、后台中间件(异步队列、缓存、数据库、任务调度)
  5. 平台服务
    • 平台服务层站在系统平台的角度上,处理系统发布、资源调度整合等功能。
    • 核心模块有发布系统、资源调度、容器镜像治理、资源治理。
  6. 基础设施层
    • 包括计算、网络、存储、监控、安全、IDC等。(云计算服务)

网关(对应k8s的ingress):路由转发 + 过滤器

  1. 为什么需要?

    这么思考,由于单体服务的拆分成了多个微服务,那么,一些验证功能如:鉴权认证功能、Session处理、安全检查、日志处理,要在每个微服务节点上实现一遍。为了解耦这些功能服务,我们可以把他们独立出来,放在请求的入口处,也就是网关处来处理。在网关处集中处理请求,分发请求,实现对外请求的统一处理。

  2. 功能:

    1. 路由转发:接收一切外界请求,转发到后端的微服务上去
    2. 过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)
    3. 负责均衡:
    4. 安全认证:校验参数合法性,用户合法性
    5. 日志监控:记录请求的出参、入参,响应时长等
    6. 数据转换:对不同客户端请求数据加工等
  3. 架构图

服务注册发现:服务提供者(生产者)+服务消费者+服务注册中心

  1. 为什么需要?
    1. 消费者需要调用生产者的API完成服务
    2. 生产者的实例多且变动频繁
    3. 生产者每次变动时将服务地址等信息注册至服务注册中心
    4. 消费者使用时从服务注册中心去取
  2. 一个不成熟的想法,如果用服务部署在k8s上,那么用k8s的service来替代注册中心是否可行。
    1. 每个微服务都在 k8s 中创建一个 Service,名起名比如: user.micro-service.host
    2. 在其他微服务中引用user.micro-service.host
    3. 只要这些服务都运行在同一个k8s下,便可省去注册中心
  3. 查询服务的两种模式
    1. a. 客户端模式:注册中心需要暴露给客户端

    2. b. 代理模式:网关需要承载负载均衡

配置中心

  1. 为什么需要?
    1. 静态配置无法动态更新,需要重启服务
    2. 无法区分环境
    3. 配置文件过于分散,内容分散
    4. 无法追溯回滚
  2. 配置中心特点
    1. 集中管理、统一标准。(如:中间件的唯一配置,配置的审核
    2. 配置和应用分离。(如:私有化时,只需修改配置,不用重新打包代码。)
    3. 动态更新。(如:修改配置时,无需重启服务)
    4. 版本管理,利于回滚。

总体架构

![在这里插入图片描述](https://img-blog.csdnimg.cn/971b8f37f2dc4f22971ad7ce9bffe1ee.png

结语

方案的调研,到此也就结束了,整体架构如上图,配置中心和注册中心暂定consul,网关目前还没想好,等之后搞定了再分享。

后续我会更新下,我们对网关、注册中心、配置中心的选型以及使用,希望对python微服务改造有需求的人提供些帮助。

其实除了微服务,还有服务网格值得考虑,由于我们k8s权限受限,目前暂不考虑服务网格。那么今天的故事就到这里,我们下次再见。

哦,对了,再次强调我们的目的是有效地拆分应用,实现敏捷开发和部署,微服务只是结果

引用

  1. 单体服务、微服务、网关、服务注册、发现、配置中心简介