微服务容器化时应该注意哪些坑

运维就要无所不能,无所不会

[TOC]

大家好,我是史丹利「stanley」,今天來聊聊微服务做容器化时应该规避哪些坑。

在上上篇文章里,我们有提到容器化时成本控制。

运维职业的第一职业敏感是成本。这毫无异议。

曾经有架构师推荐老板容器化的一个理由也是容器化可以大范围节约公司资金成本,我也一度很认可,但后来发现凡事是有前提的

微服务天生适合容器化,这也毫无异议,但也是有前提的,前提就是做了合理的微服务拆分

太过粗糙的微服务拆分,顶多影响开发工作版本迭代,提升版控难度,但过于细分的微服务拆分,则会增大容器化后的成本。

安全起见,Java 进程启动时都分显示声明的内存分配

-javaagent:/usr/local/skywalking_agent/skywalking-agent.jar -Dskywalking_config=/usr/local/skywalking_agent/config/app.config --eureka.client.serviceUrl.defaultZone=http://eureka.example.com/eureka/ -XX:PermSize=128m -XX:MaxPermSize=128m

k8s 也一样,官方建议对所有的pod做限额配置。

        resources:
          requests:
            cpu: 2
            memory: 2048Mi
          limits:
            cpu: 2
            memory: 2Gi

如上的方式为资源硬设置,即固定分配2c2G的资源,如果觉得这样的方式,太浪费资源,k8s 同样提供了如下比较人性人的设置,

limits:
- default:
    cpu: 800m
  defaultRequest:
    cpu: 800m
  max:
    cpu: 800m
  min:
    cpu: 200m
  type: Container

软资源限制对资源浪费有缓存,但并不能实质性解决资源浪费的情况,因为没人知道什么时间pod的资源占用会达到峰值,即使知道,这部分资源也需要一直为其预留,与其这样,反倒硬资源限制更安全。

所以,问题就回到了,如何微服务的切割原则。

一、微服务常见的坑

单体应用运行一段时间后,随着业务的增长,对系统性能和并发性要求越来越高,这个时候就面临着微服务重构的选择,但在重构前,我们必须反复权衡并且做好必要的基础设施准备以应对新架构下面临的新问题,而不是觉得微服务现在火脑袋一热就开始着手微服务重构。

结合实际项目回顾下微服务可能存在的坑,主要包含以下几点:

  • 过分强调’微‘,致使服务拆分过细,服务数量太多,导致服务间关系复杂,系统复杂度上升,人力和维护成本变高;
  • 原本的单体同进程间服务调用变成远程不同进程间服务调用,调用模式从内存调用变成网络调用,如果调用链路过长,反而会导致性能下降,响应时间变长,同时问题定位变得愈发困难;
  • 基础设施不健全,没有必要的服务监控和治理,导致服务管理混乱,原本设想的轻量级微服务变成一堆乱麻,此外,自动化测试和部署支持也要更上,否则服务间有依赖的话无法实现快速交付。

我们分几方面介绍:

  • 服务拆分前提
  • 服务拆分时机
  • 服务拆分方法
  • 服务拆分规范

二、服务拆分前提

  • 公司的CICD平台较完善

服务拆分后,同步带来的验证、测试、上线等工作量是有增无减,微服务的过程其实是人力换质量的过程 。如果配套工具不成熟,同步带来的复杂度会远胜便利性。

  • RESTFUL API 接口和前后端分离

[图片上传失败...(image-27f485-1610636671284)]

新一代开发开发框架,基本上已经有很好的前后端分离。这样的好处是,无论后端如何变化,对前端都是透明的。而且可以实现拆分过程中的灰度发布,路由分发,流量切分,从而保证拆分的平滑进行

  • 数据库表设计

各功能模块间没有大量的复杂联合查询,优秀的库表设计应该能达到绝大多数的功能查询只是 k/v 的O(n) 查询。否则,微服务的拆分会有很大难度,和代码重构无异

  • 无状态化

[图片上传失败...(image-91cb7a-1610636671284)]

新一代的开发框架和开源流行工具都在强调的功能特性,去中心化,无状态化。无状态化同样是k8s的核心思想之一。

三、服务拆分时机

新业务通常使用springcloud全家桶,在某些程度或者完全实现微服务化。

旧业务的微服务化改造的拆分并非自上而下一步到位的重构改造,通常是由痛点驱动,是业务真正遇到了快速迭代和高并发的问题,如果不拆分,将对于业务的发展带来影响,只有这个时候,微服务的拆分是有确定收益的,增加的运维成本才是值得的。

比如如下的情况之一:

  • 提交代码频繁冲突
  • 无法快速版本迭代,小功能要积累到大版本才能上线,每次上线各种问题,不蜕三层皮上线不成功
  • 业务有高并发需求
  • 熔断全断if-else

如上情况,可考虑服务拆分

四、服务拆分方法

[图片上传失败...(image-62efa9-1610636671284)]

[AKF扩展立方体](参考《The Art of Scalability》),是一个叫AKF的公司的技术专家抽象总结的应用扩展的三个维度。理论上按照这三个扩展模式,可以将一个单体系统,进行无限扩展。

  • X 轴 :指的是水平复制,很好理解,就是讲单体系统多运行几个实例,做个集群加负载均衡的模式。

  • Z 轴 :是基于类似的数据分区,比如一个互联网打车应用突然或了,用户量激增,集群模式撑不住了,那就按照用户请求的地区进行数据分区,北京、上海、四川等多建几个集群。

Y 轴 :就是我们所说的微服务的拆分模式,就是基于不同的业务拆分。

场景说明:比如京东商城,一个集群撑不住时,分了多个集群,后来用户激增还是不够用,经过分析发现是6.18访问量很大,就将商城页面流量大功能再做拆分,每个拆分出来的功能,独立维护,各自都可以再次按需扩展。

反面教材:

我们公司的内部应用系统,使用人数不超过100人,但系统却拆分成30多个模块,造成容器化时大量资源浪费。

五、服务拆分规范

服务拆分规范并不是运维强项,或者运维并没有太多的机会和话语权参与到开发的实际开发工作中。

在实际工作中,微服务对运维工作造成比较大的影响,比如工作量陡增,资源成本消耗更多,但服务质量并没有实际提升,那么优先考虑

  • 运维工具是否成熟健全
  • CICD流程是否成熟可靠

如果均没有,再考虑微服务拆分问题,这里仅做入门,建议深入学习后再和开发同学一起改进优化。

  • 服务拆分的规范一:服务拆分最多三层,两次调用
  • 服务拆分的规范二:仅仅单向调用,严禁循环调用
  • 服务拆分的规范三:将串行调用改为并行调用,或者异步化
  • 服务拆分的规范四:接口应该实现幂等
  • 服务拆分的规范五:接口数据定义严禁内嵌,透传
  • 服务拆分的规范六:规范化工程名

微服务规范参考: http://dockone.io/article/8241

你可能感兴趣的:(微服务容器化时应该注意哪些坑)