2019独角兽企业重金招聘Python工程师标准>>>

2016年伊始Docker无比兴盛,如今Kubernetes万人瞩目。在这个无比需要创新与速度的时代,由容器、微服务、DevOps构成的云原生席卷整个IT界。个推针对Web服务场景,基于OpenResty和Node.js搭建了微服务框架,提高了开发效率。在微服务的基础上,我们结合Docker实现了容器化,并采用Consul进行服务注册及发现。同时,面对日渐增多的微服务和配置,我们采用了Kubernetes来实现容器编排。

一、微服务化

01 微服务架构

-微服务框架-

微服务是将单一的应用程序拆分成多个微小的服务,各个小服务之间松耦合,高内聚,每个小的服务可以单独进行开发,不依赖于具体的编程语言,也可以使用不同的数据存储技术,各个服务可以独立部署,拥有各自的进程,相互之间通过轻量化的机制进行通信(如基于http的API接口),所有的服务共同实现具体的业务功能。

-微服务客户端与服务端通信方式-

客户端与服务端通信有2种方式,第一种是客户端直接与各个微服务进行通信,这样的架构有4个缺点:

(1)多次服务请求,效率低;

(2)对外暴露服务接口;

(3)接口协议无法统一;

(4)客户端代码复杂,服务端升级困难。

第二种方式是由API网关统一代理各个服务,对外提供统一的接口协议,该架构有3个优势:

(1)封装服务接口细节,减少通信次数;

(2)统一通信协议,减少客户端代码耦合;

(3)统一鉴权,流控,防攻击。

但在该架构下,网关也有可能成为系统瓶颈

-服务注册与发现方式-

相应地,这2种架构也带来了2种服务注册发现的方式,第一种是客户端通过向服务的注册中心查询微服务的地址与其通信,第二种是增加统一的API网关来查询。前者会增加客户端的复杂度,开发成本高,后者操作会更加简洁,因此我们在实践的时候选择了第二种架构方式。

微服务数量增加以后,服务之间的调用关系易产生耦合,甚至出现循环调用的情况,最好的应对方法是对服务进行分层,即将相互依赖的服务通过消息队列等技术进行异步解耦,减少服务间的依赖。

-服务分层-

02 微服务的具体实践

技术选型

在实践中,我们的API Gateway使用的是OpenResty。OpenResty基于Nginx并扩展了对Lua的支持,可构建高并发的Web服务。我们通过HTTP接口实现客户端通信,数据基本封装成JSON格式,服务间的通信接口也是基于HTTP,并利用消息队列进行异步解耦;至于服务注册发现,我们使用的是Consul;我们选择了Lua(扩展API Gateway的功能),Node.js(用于开发后端服务),Java(用于密集计算和与大数据通信的场景)作为主要的开发语言。

具体实现过程

下图为个推统一的服务框架,每个微服务都是运行于这个框架之下,WebLua集成在OpenResty上,对流量进行代理,WebNode和Javams分别是Node和Java服务的微服务架构。

-统一的服务框架-

首先是WebLua

-WebLua微服务框架-

在实践过程中,个推使用Lua开发了Lua APP运行的微服务框架-WebLua,其封装服务之间的通信协议和访问外部资源(如MySql、Redis等)的方法和依赖,同时提供了应用插槽。我们可以将每一个APP看成一个功能模块,每个APP都需要插到WebLua中才能运行。WebLua可以方便地将模块进行组合,既可以一个APP运行一个微服务,也可以多个APP一起对外提供服务。如此,开发者只需关注业务APP开发,很大程度上提高了开发效率。上图右侧是具体的代码目录结构,每个APP可分为Actions,Page,Data三层,Action层在请求处理前后进行拦截,可做某些特殊处理,如请求前进行权限校验等;Page层主要对请求的参数进行解析和校验;Data层负责具体业务处理,同时提供了Shell脚本,可实现APP打包和部署安装。

-WebNode微服务框架-

上图是我们Node服务的微服务框架-WebNode,最早基于Express和co实现,近期个推完成了基于Koa2.0升级的框架。我们的业务主要是由Node.js和TypeScript进行开发,我们对业务进行拆分,独立出一个个功能模块,每个独立的功能模块单独开发成一个APP,一个或多个APP一起安装于WebNode框架之下,作为一个微服务统一对外服务。WebNode框架的实现和WebLua类似,也提供了插槽,方便APP进行安装和组合。

Javams 是个推为了针对高并发场景下快速构建微服务而研发的框架,在 Spring Boot 的基础上,包含了RPC框架、Trace、缓存、健康检查等组件,提供一站式服务。

二、API网关

在微服务架构中一个重要角色就是API网关,下面来做介绍。

-使用API网关前后对比-

从上面的对比图中可以看到,左侧是没有API Gateway的,很多的模块如Auth,Logging等,这些代码都需要自己去实现,造成了模块的重复建设,同时侵入了服务,功能扩展比较困难;右侧的图是使用了API Gateway之后的架构图,所有通用模块均在API Gateway实现,维护简单,一处建设,各处受益。在这种情况下,对API Gateway也提出了更高要求——其功能必须可以很方便地扩展

为了实现这样的API网关,我们基于 OpenResty,借鉴了Kong和Orange的插件机制,通过插件来扩展API网关功能

-API网关的整体架构-

从上面的API Gateway架构图中可以看到,网关安装诸多插件,每个插件会在请求的一个或多个阶段发挥作用。插件配置会在Consul上更新,实时生效,插件规则可灵活配置。在操作中,我们为插件开发者提供了更多自由选择,开发者可以自己定义格式

三、容器化

在微服务落地实践时我们选择了Docker,下面将详细介绍个推基于Docker的实践。

首先网络组件选择的是Calico,服务注册发现和配置管理选择的是Consul。Consul-template可实时监测Consul配置和服务的变化。

-个推镜像体系-

个推镜像体系是以Centos为基础系统镜像,安装OpenResty,Node.js,jdk,由此得到环境镜像;在这个基础上安装微服务框架,获得Gorp镜像,再在这个Gorp的基础上安装具体应用服务,得到应用服务镜像。

-API网关中服务注册和配置更新过程-

在API网关中,服务注册通过Consul-agent来实现,配置更新通过Consul-Template实现。Consul-Template主要更新3类配置,包括:

Services:代理的所有微服务的服务地址;

Products:简言之即请求到微服务的映射表,如左上所示,所有请求都有统一个规范,从Host中可以获取Prod,从URI中可以获取APP,这2个信息可将请求动态路由到具体服务;

Nging-Conf:产品的Nginx配置。

-应用服务的服务注册和配置更新过程-

应用服务容器,服务注册的方式跟API网关一致。首先,服务通过容器内部运行的Consul agent将服务注册到Consul上,其次通过Consul-Template来监测观察 Consul上配置的变化,并更新配置文件。

OpenResty或者WebNode配置的更新是直接覆盖相应的配置文件,然后重启对应的服务。

-Docker集群-

上图是个推基于Docker的集群架构,从上面的整体架构图中可看到,Docker集群包括3个节点,整个微服务分为3层,最上层API Gateway,中间是业务层,最下层是一些多产品公用的基础的微服务

四、Kubernetes实践

微服务虽然有很多好处,但也带来了很多问题,其中一个就是运维复杂。以前运维只需要面对一个单体应用即可,现在可能面临的是几十甚至上百的微服务。在这种情况下,我们需要借助Kubernetes来解决问题。Kubernetes是Google开源的一个容器编排工具,可用于协助管理容器。

一开始,我们将容器向Kubernetes集群迁移时,没做任何改变,只是采用Pod将所有的服务体系在Kubernetes集群跑起来。但随着深入使用Kubernetes,我们对微服务做了一些改变。

  1. 首先我们换成用Deployment的方式来部署服务,Deployment会保证服务时刻有一定的副本存活,提高了服务稳定性。

  2. 其次,我们使用了Service,它可以代理Pod实现负载的均衡。

  3. Kube-DNS可以将Service名解析成具体的clusterIP,并且当Service没有删除重建时,其clusterIP不变,如此DNS解析的缓存就不存在失效问题。基于Kube-DNS和Service的特性,后续我们改造了服务注册发现体系。

-服务部署方式-

上图是我们当前的服务部署方式,Pod用Deployment的方式创建,用Service来进行代理。

在实践过程中,我们还遇到了另一个问题,即配置管理问题

(1)微服务化后配置文件多而分散。

(2)不同环境之间有很多不必要的差异,如数据库名。

(3)在很多不同环境中,相同的配置项暴露给测试和运维。

(4)没有版本控制,回滚比较麻烦。

(5)基于Consul的Web UI无法对非法的输入进行校验。

针对这些问题我们做了以下调整

(1)统一不同环境间不必要的差异。

(2)对配置文件进行模板化,只暴露差异部分,同时可实现不同配置文件集中配。

(3)基于Consul开发配置中心,对产品配置集中管理;对输入进行合法性校验;增加版本控制,方便回滚。

-配置中心流程图-

-日志服务框架-

关于日志服务,我们在应用容器中集成了Fluent-Bit,配置了2个输入源,TCP和tail, 输出也有2个,一个是Elasticsearch,所有的日志都会上传到ES通过Kibana展示查询,另一个是日志审计服务,有些需要进行审计的操作日志会发送到日志审计服务进行进一步的分析处理。

微服务数量增加以后,请求链路可能延长,开发者在追踪问题和排查性能瓶颈时会很不方便,因此我们引入了Zipkin,其主要用于分布式链路追踪,在API Gateway实现了一个插件进行Span收集,后端服务则通过开源的中间件来实现。

-个推微服务架构-

上图是我们目前的整体架构图,最底层是K8S集群,上面部署了Kube-DNS,Consul用于服务注册发现和配置管理,再者是我们分层的微服务体系,右侧是一些辅助的管理系统。

五、总结

上述是个推基于Docker和Kubernetes的整个微服务实践过程,我们在实践微服务过程中做了九件重要的事情,即设计实现了自己的微服务框架、完成微服务的容器化部署、自研API网关、基于Consul服务注册和配置管理、使用Kubernetes对容器进行编排、基于Service和Kube-DNS对服务注册和发现体系进行改造、搭建了自己的配置中心、优化日志服务和实现了Zipkin链路追踪

转载于:https://my.oschina.net/u/1782938/blog/2907077

个推基于Docker和Kubernetes的微服务实践相关推荐

  1. QCon技术干货:个推基于Docker和Kubernetes的微服务实践

    2019独角兽企业重金招聘Python工程师标准>>> 2016年伊始,Docker无比兴盛,如今Kubernetes万人瞩目.在这个无比需要创新与速度的时代,由容器.微服务.Dev ...

  2. 基于Docker和Kubernetes的企业级DevOps实践训练营

    基于Docker和Kubernetes的企业级DevOps实践训练营 课程准备 离线镜像包 百度:https://pan.baidu.com/s/1N1AYGCYftYGn6L0QPMWIMw 提取码 ...

  3. Docker、kubernetes、微服务、SpringBoot/Cloud...好乱!到底要不要学?

    Docker.微服务日益火热的今天,相信标题上这些名词大家都不陌生.但也相信有很多同学并不够清楚他们的概念,不理解它们的关系,也可能有这样的疑惑:不知道跟我有没有关系?要不要学习?怎么去学习?学哪些东 ...

  4. 基于 Kubernetes 的微服务项目设计与实现

    作者:xiaojiaqi 来源:https://github.com/xiaojiaqi/deploy-microservices-to-a-Kubernetes-cluster 随着互联网的发展,后 ...

  5. 基于 Kubernetes 的微服务部署即代码

    在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...

  6. 微服务开发及部署_基于 Kubernetes 的微服务部署即代码

    在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...

  7. 基于阿里云容器服务的微服务实践 - Part 1. 微服务与Docker

    基于阿里云容器服务的微服务实践 基于阿里云容器服务的微服务实践 - Part 1. 微服务与Docker 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blo ...

  8. 基于Kubernetes的微服务自动化运维

    作者:禅与计算机程序设计艺术 基于Kubernetes的微服务自动化运维 本文将介绍如何使用Kubernetes进行微服务自动化运维,提高团队的工作效率和服务的可靠性.本文将阐述微服务自动化运维的实现 ...

  9. 流量暴增,掌门教育如何基于 Spring Cloud Alibaba 构建微服务体系?

    作者 | 童子龙  掌门教育基础架构部架构师 **导读:**本文整理自作者于 2020 年云原生微服务大会上的分享<掌门教育云原生落地实践>,本文主要介绍了掌门教育云原生落地实践,主要围绕 ...

最新文章

  1. CAP只能三选二,可以选CA吗?
  2. ModuleNotFoundError: No module named 'sklearn.cross_validation'
  3. SAP Connect对inbound邮件接收问题的处理和调试环境搭建
  4. [转载] Java静态绑定与动态绑定
  5. C++/CLI思辨录之再谈继承
  6. 《原力计划【第二季】》第 8 周周榜揭晓!!!
  7. mysql获取某个表的所有字段名
  8. 学习笔记——RuntimeException
  9. 关于代理服务器的原理及用法
  10. VRay无限平面的应用教程
  11. Python面向对象加强1.关于经典类、新式类和property详解
  12. 《史蒂夫·乔布斯传》——童年篇有感
  13. wind10 终端conda切换python环境,pip不存在以及解决easy_install pip报错
  14. 手持无刷云台三轴全角度到底有多少坑
  15. python path包的使用详解
  16. win无法启动资源修复服务器,Win10修复:Windows Defender无法启动两步解决
  17. mysql 大批量数据查询_mysql 处理 多条件 大批量数据 查询
  18. Android 通过外网IP定位城市
  19. C语言程序设计精髓习题总汇
  20. Python小工具——格雷码转换器

热门文章

  1. 微信公众平台开发(150)——从新浪云SAE上传图片到图文消息
  2. 面试题:二叉树中和为某一路径
  3. 计算机科学速成课18:操作系统
  4. maze_travel的隐私声明
  5. Python学习笔记之函数(五)
  6. Mybatis一级缓存、整合第三方缓存ehcache、Mybatis二级缓存
  7. STL(七)——队列queue优先队列priority_queue
  8. 贵州丹寨:庆苗年 迎新春
  9. flask简单登录注册
  10. iOS面试中经常问的点 - RunTime