关于微服务的那点事儿
前言
传统的单体项目有什么问题?
想想看,当你的项目源码达到几十M时,开个新功能启动一次项目需要20分钟,稍微修改一下bug也要20分钟,团队的效率得有多么低
再想想看这么大的项目,必定伴随着复杂的业务,对于新人来说直接接触这么多复杂的业务,没有半年时间难以融入团队进行输出
最主要的是,每次稍微改动一点bug,就要发版整个单体项目,出问题影响的是全部功能,这个是不能忍的
如何拆分微服务?
微服务的拆分思想可以说是基于DDD模型(传统的MVC模型已经逐步落后,新一代的领域驱动设计模型)的思想,需要完整的业务把控能力,
确认服务边界上下文,所谓边界上下文就是服务自身的职责的划分,每个服务都是个高內聚的个体,各个服务之间不发生耦合,我们需要脱离表的束缚,从业务上梳理出模块之间的边界
拆分微服务以后会有哪些问题?
1.服务之间如何调用?
单体项目里无非就是方法调用,微服务之间调用需要走网络通讯,是一个序列化与反序列化的数据传输过程,对于spring cloud,使用http传输协议,由feign进行声明式调用
2.如何保证服务的高可用?
为了保证服务的可用性,微服务模块不可能是单点跑的,一定是集群部署的,对于调用方客户端来说,我们需要知道目前已经注册的服务都有哪些,并且还需要对服务有着动态的上下线感知,除了这些,客户端还需要一个负载均衡的机制吧?这个就是ribbon做的事。
引入一句忘了在哪看到的话,计算机的所有问题都可以通过引入中间层来解决。这个中间件就是注册中心。注册中心维护了所有的注册的微服务,客户端依赖注册中心来找到真实的微服务地址。这块细节比较多,比如注册中心挂了怎么办,微服务内部是不是应该有个缓存的注册列表?如果出现了网络分区,分区内的注册中心应该仍然可以正常使用(zookeeper别到处看了。。。说的就是你。。。)
3.容错机制
想想这样的一个场景,某个后端微服务接口出现异常,客户端的请求发生超时。用户一般有个习惯,哪里出问题了会一直点,那么每一个请求都对应了后台的某一个线程,这个线程还是一直在runing直到超时的,系统资源是有限的,次数多了,系统必然由一个接口的问题导致大面积的雪崩。
传统做法是http请求设置sessionTimeout与connectTimeout,但这不是解决问题的根本。
我们需要有个类似家里保险丝的熔断机制,当服务出现问题时,断路器自动熔断。除了这个,断路器还要有自我修复能力,比如过段时间放出一个请求,如果成功了就自我修复。再一个比较重要的是资源隔离,各个微服务接口调用不同的线程池或者信号灯。springcloud hystrix
4.链路追踪
对于单体项目,都是单个jvm内的方法调用,日志的上下文很容易查看。对于微服务就不太一样了,服务都在不同的jvm通过网络进行通信,如何能拿到完整的调用链路日志?我们需要在微服务调用时传递traceID,使用traceID追踪调用链路,这个就是sleuth做的事
5.微服务网关
还是对比传统单体项目,项目的controller接口都在一起,统一管理很容易,但是到微服务就不太一样了,各个项目都会提供rest服务,我们需要一个统一的网关来做权限验证、统一跨域处理、路由跳转等等。。。这个就是zuul负责的功能。
6.配置中心
单体项目的配置都是放在一个项目内,如果要改的配置的话,比如改mysql地址,直接改一次就想了,微服的配置分散在各个服务内部,我们需要一个集中式的配置管理 ,这个就是配置中心springcloud config,配置中心除了集中管理配置,还应该有修改配置实时同步到各个服务内的功能,做的好一点的配置中心,还有灰度发布,父子配置继承的概念。
7.日志落地
单体项目的日志都是落在服务器的某个固定磁盘上,微服务的日志分散在各个机器的各个角落,而且微服务都是集群部署的,查一个完整的调用日志特别痛苦,我们需要一个日志收集机制,集中统一管理日志。
日志收集:logbak → kafka→ logstash → elasticsearch,kabana负责图形化展示
8.服务上线
这么多微服务,如果靠人工运维手动copy jar包java -jar启动,恐怕要累死运维,不像传统项目就一个包直接发就行了。这个时候就聊到容器化技术了,这里需要感谢docker与k8s解放了生产力。
传统的虚拟机比如vmvare,他在宿主机上完全虚拟了一套操作系统,而docker与他最大的不同就是他直接运行于宿主机内核bootfs,没有硬件虚拟,依托于linux的资源隔离。这样使单机可以跑大量的docker服务,性能甚至与原始方式相差无二。
光靠docker肯定是不行的,还是没有解决我们需要挨个轮流运维各个微服务,这个时候就轮到k8s登场了,k8s负责对容器的编排,所谓编排,就是对容器的管理,可以配置我们在集群内要启动哪个服务,这个服务在集群内要有几个副本,k8s会自动帮忙我们完成这个工作,如果服务某段时间挂掉了,k8s还会帮我们自动重新拉起来。服务上线时,他还会有个平缓的上线过度,比如服务x有A、B、C三个节点,他会先中断A节点,启动个新服务,启动成功之后再中断B节点。。。。k8s还有很多强大的功能,是个未来的趋势,是DevOps的重要环节。可以说,不会k8s,就谈不上懂DevOps。
现在有个docker容器跟k8s编排,最后一个工作是如果把这套流程动起来,从拉代码到maven打包再到构建容器发布到k8s集群,这个流水线就是jenkins。
微服务架构写在最后
微服务除了上面的难题,还有许多其他的难题,比如分布式事务等等。。。但是技术不能因为这些难题而放弃复杂业务项目的微服务,作为技术也不能盲目追新,微服务并不适合小项目。还是那句话,微服务好是好,但不是适合所有项目,看自身项目情况来决定微服务是否引入。