引言
故事的起因是这样的,我们是一个算法工程团队,主要做的是将算法流程工程化,大多只有python基础,并未接触过微服务。目前面临一些问题,如:
- 我们的主服务越来越大,团队的人也流动了一波又一波,没人能完全了解全部代码
- 业务流程,算法框架以及hdfs等依赖都集中在主服务中,相互关联难以分离。每次启动主服务,还要保障算法框架的依赖和大数据平台的可用
- 配置文件繁多,不同的功能有不同的配置文件,相同的中间件(如:S3、ES等)有多出配置引用。
- 目前还是python2技术,官方已经宣布不再维护了,我们尝试升级python3,工程量很是巨大。
- 平台越大,我们的主服务约臃肿已经到了不破不立的时刻。
于是,我们考虑,将这个庞大的单体服务,一点点的做拆解替换,用一个个小服务来取代单体服务中的各个功能块。我们就想到了微服务的架构方式,准备尝试用其来解决我们当前的窘境。(注意:由于我们团队以python为主,并不像java、go那样拥有成熟的解决方案。)
单体服务
既然想改造,还是要直面我们的服务框架—单体服务,简单画了图示,方便更直观的说明。
结构图
优劣
- 优点
- 易于部署:只有一个server的软件包,很方便发布到服务器。
- 易于测试:一个服务启动就可系统测试。
- 缺点
- 维护成本大:服务过于庞大,任何一个bug都可能需要全组协调排障(没有人全面了解这个server了)。
- 交付周期长:任何小的迭代(极端情况,只修改了一行注释)要触发整个部署流水线,我们不得不先停止所有线上业务来完成上线操作。
- 技术选型成本高:功能依赖某一语言(这里是python)或框架,后期引入新语言、框架、技术成本高风险大。如:python2→python3 、flask → fastapi 要重构整个项目。
- 扩展性差:垂直扩展(加机器整体再启动个服务做负载)随着功能增加,成本越来越高。水平扩展(某一功能的性能扩展),由于单体服务全部功能位于一个进程,无法实现水平扩展。
微服务
为了解决单体服务所面临的窘境,我们决定尝试微服务方案,将功能拆分为一个个微服务,使用网关、注册中心、配置中心等,构建聚合服务,也就是实现原来单体服务的全部功能。以便在后续的开发中,每个功能点都能快速迭代,新的技术也能快速融入到我们的平台。
那么什么是微服务呢?
定义
wiki定义微服务: 微服务(英语:Microservices)是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic)的API集相互通信。
关键词:软件架构风格,小型功能区块,语言无关。
优劣
- 优点
- 拆分系统,降低单个服务复杂性:每个小团队(3-5人)可以独立完成的一个服务为一个小服务,根据功能、业务、领域等需求划分,团队内达成一致即可。这样再出现bug时,只需单个服务排查就好,无需整个团队配合。
- 独立进程:可独立部署,实现快速迭代和水平扩展。
- 轻量级通信,API隔离:不同服务间通过接口通信(http、tcp等),所以微服务可不采用统一语言或框架。
- 缺点
- 拆分力度把控:微服务只是结果,不是目的。我们的目的是有效的拆分应用,实现敏捷开发和部署。
- 增加代码复杂性:原本的查库操作,类间调用,可能要改为API调用。
- 增加数据存储难度:不同服务所使用的不同的数据库,需要处理好分布式事务。
- 增加测试复杂性:单体服务启动一个服务能解决的事,现在要启动一堆微服务。
- 性能受网络影响增大:服务间通过API调用。网络请求大大增加。
架构图
- 接入层:负载均衡作用
- 网关层:反向路由,安全验证,限流等
- 业务服务层:基础服务和聚合服务(业务服务、领域服务)
- 撑服务层
- 支撑服务层提供非业务功能,以支撑业务服务层和网关层软件的正常运行。
- 核心模块有服务注册发现、集中配置、容错限流、认证授权、日志聚合、监控告警、后台中间件(异步队列、缓存、数据库、任务调度)
- 平台服务
- 平台服务层站在系统平台的角度上,处理系统发布、资源调度整合等功能。
- 核心模块有发布系统、资源调度、容器镜像治理、资源治理。
- 基础设施层
- 包括计算、网络、存储、监控、安全、IDC等。(云计算服务)
网关(对应k8s的ingress):路由转发 + 过滤器
为什么需要?
这么思考,由于单体服务的拆分成了多个微服务,那么,一些验证功能如:鉴权认证功能、Session处理、安全检查、日志处理,要在每个微服务节点上实现一遍。为了解耦这些功能服务,我们可以把他们独立出来,放在请求的入口处,也就是网关处来处理。在网关处集中处理请求,分发请求,实现对外请求的统一处理。
功能:
- 路由转发:接收一切外界请求,转发到后端的微服务上去
- 过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)
- 负责均衡:
- 安全认证:校验参数合法性,用户合法性
- 日志监控:记录请求的出参、入参,响应时长等
- 数据转换:对不同客户端请求数据加工等
架构图
服务注册发现:服务提供者(生产者)+服务消费者+服务注册中心
- 为什么需要?
- 消费者需要调用生产者的API完成服务
- 生产者的实例多且变动频繁
- 生产者每次变动时将服务地址等信息注册至服务注册中心
- 消费者使用时从服务注册中心去取
- 一个不成熟的想法,如果用服务部署在k8s上,那么用k8s的service来替代注册中心是否可行。
- 每个微服务都在 k8s 中创建一个 Service,名起名比如: user.micro-service.host
- 在其他微服务中引用user.micro-service.host
- 只要这些服务都运行在同一个k8s下,便可省去注册中心
- 查询服务的两种模式
a. 客户端模式:注册中心需要暴露给客户端
b. 代理模式:网关需要承载负载均衡
配置中心
- 为什么需要?
- 静态配置无法动态更新,需要重启服务
- 无法区分环境
- 配置文件过于分散,内容分散
- 无法追溯回滚
- 配置中心特点
- 集中管理、统一标准。(如:中间件的唯一配置,配置的审核)
- 配置和应用分离。(如:私有化时,只需修改配置,不用重新打包代码。)
- 动态更新。(如:修改配置时,无需重启服务)
- 版本管理,利于回滚。
总体架构
![在这里插入图片描述](https://img-blog.csdnimg.cn/971b8f37f2dc4f22971ad7ce9bffe1ee.png
结语
方案的调研,到此也就结束了,整体架构如上图,配置中心和注册中心暂定consul,网关目前还没想好,等之后搞定了再分享。
后续我会更新下,我们对网关、注册中心、配置中心的选型以及使用,希望对python微服务改造有需求的人提供些帮助。
其实除了微服务,还有服务网格值得考虑,由于我们k8s权限受限,目前暂不考虑服务网格。那么今天的故事就到这里,我们下次再见。
哦,对了,再次强调我们的目的是有效地拆分应用,实现敏捷开发和部署,微服务只是结果。
引用
- 单体服务、微服务、网关、服务注册、发现、配置中心简介