中间件middleware
内容管理
本文主要intro服务化中间件的探讨
去年cfeng写了一篇博客走马观花般阐述了Spring Cloud下面的各种中间件,连深入使用都谈不上,只能说intro,在实际work中,我们不能浅尝辄止
intro
服务化(微服务)是分布式架构下后台的趋势,应对更大的流量和复杂的场景,后台服务化,而服务化带来的一些问题,也就是采用相关中间件来解决,所以Spring cloud是服务化的解决方案,和原本的开发框架SpringBoot没有什么冲突。
服务化也只是一种措施,流量小的情况下大可不必微服务直接单体架构搞定。所以不管是微服务、还是云原生都是架构演变过程带来的新的解决方案,而深入到每一个节点的开发,还是和传统java开发一样。学习新的方案同时夯实开发基础以不变应万变。
why 服务化
服务化就是将原本的一个整体拆分成一个个服务,每一个应用针对特定的业务场景和需求进行构建,能够进行独立的开发测试发布升级。分治思想当然带来的好处就是更好的独立性和扩展性。
每一个服务相互隔离,可以采用不同的技术栈(比如订单业务采用java开发,用户符采用go开发...),故障隔离,系统的可维护性提升,同时也会带来额外的通信成本。原本在一个应用内进行简单调用的逻辑可能就需要转变为远程过程调用RPC
,应用调用关系形成复杂关系网。
how to ensure 服务化
服务化主要就是将原本一体的服务拆分成了不同的部分,每一个部分相当于一个独立的服务。问题的关键就是保证各个部分能够良好协作实现一体化的效果。
而服务间要能够正常协作,关键就是通信,也就是RPC。对于RPC,需要考虑哪些关键的问题呢?
- 如何将业务数据转为为RPC过程中传播的数据,也就是如何进行序列化,以及后面的反序列化?
- 像网络分层一样,一个应用如何知道自己调用的服务的地址以及传输数据的格式?
- 如何保证自己依赖的服务(下游服务)是可靠的?【高可用】应用应该怎么管理自己的工作状态?
- 应用若采用中间件进行通信,那么怎么保证使用这个中间件嵌入的代码最少?
- RPC过程具体怎么实现,如何进行应用的认证授权,流量控制和服务降级?
java
这个RPC就是一个信息的传播过程,和其他的信息传播的考虑因素一样,首先就是我们的信息的传播目的地怎么获得,还有就是我们遵循什么样的传播规范(协议);下游没有接收怎么办 --- 下游挂了?, 信息的安全怎么保证,信息传播过程的安全怎么保证,怎么保证各个服务的状态正常?.....
解决上述问题就需要提供相关的解决方案:
- 序列化解决方案,常规的准确高效之外,还有就是不同的服务完全独立带来的跨平台、语言复杂性
- 服务注册中心, 能够注册所有的服务的地址,能够进行服务发现
- 服务检测中心,能够实时监控服务的工作状态
- 高度封装的中间件,应用通过暴露的接口即可发起通信
- 服务治理系统,能够实现服务的管理
服务化middleware架构
服务化不是一个狭义的,给出的解决方案也是广义的整个生态的解决方案。从客户端-> 服务端 -> 支持系统,服务化中间件也就需要包含: 服务端框架、客户端框架、服务注册中心、服务治理中心。
之前单独的一个service可能配置很好管理,但是现在的多个service要配置一体化,所以我们也需要便捷的配置中心来实现配置的管理【服务化治理系统】,配置推送到注册中心,然后客户端service发起RPC时,首先到配置中心获取调用地址,之后发起访问。
客户端框架工作在客户端Service中(每一个service可能有着多种角色),其他服务的接口映射本地成本地的方法调用【封装了中间复杂的数据传输序列化、注册中心的交互发现、不同服务之间的负载均衡流量控制、错误处理和熔断降级】
服务端框架工作在服务端Service中,所谓框架就是服务端作为中间件的用户需要植入的相关代码。
服务注册中心,主要就是进行服务的注册发现,在企业级开发中,可能同时存在数个服务,数个实例,注册中心可能需要承受极大的请求量。因此注册中心需要应对复杂多变的场景,需要能够稳定运行并且高可用。
服务治理系统,需要提供服务信息管理、实例管理、配置管理等综合的治理功能,内部需要双向进行消息交互,推送服务配置信息等...
整体上看,服务化最关键的便是服务注册和服务治理,关于这两个问题当然业内也有很多的解决方案,包括Spring Cloud提供的以及其他的厂商开源的解决方案
注册中心intro
之前的blog中已经走马观花般介绍过两个注册中心: Spring Cloud下的Eureka和Ali的Nacos,这里先简单从宏观角度intro注册中心。
注册中心的关键功能就是服务注册发现,how?
java
在单体项目中,涉及其他service的访问可能就是在配置文件中配置一下service的地址,比如Redis的服务地址....
if 我们知道服务的地址,那可能注册中心就是起一个转发的作用,直接从配置中心拉地址,然后将请求转发过去
cfeng work中遇到一个通信场景,不允许使用注册中心,当时采用的想法就是二级缓存,在redis中存储服务地址并有有效期,同时服务实例通过心跳请求维护数据的有效性,这个时间尽管设置的短,但是在评判时还是有诸多风险.....
注册中心集群化需要考虑的问题?
在当前分布式架构的情况下,为了应对复杂的生产环境,避免单点故障,一般服务都是集群部署的,这里先不谈具体的注册中心如何发挥作用,先探讨注册中心集群化应该考虑哪些问题
注册中心集群化,多个节点地位相同,注册信息不持久化到后端,而是保存在各个节点的内存。服务注册心跳由接收节点分发到其他节点,保证数据一致性。---- 基于内存读写效率更高,而服务实例的配置数据就持久化。
之前已经介绍过Eureka,刚好又看到携程基于Eureka开发的Artemis,Artemis提供的服务主要就是分别基于域名和IP的服务注册发现,这里就先看一下Artemis的架构,之后再去分析Eureka的源码。
对于服务端框架而言,它要进行服务注册,首先就是和Artemis节点进行信息交互,通过配置管理,服务端可以获得当前可用的全部的Artemis节点列表,然后选择其中一个进行交互【各个节点地位平等】,后续的服务注册和心跳检测都发送到这个节点, 对客户端来说一样的,也是获取所有的Artemis节点列表,随机选择一个与之交互。
为了避免单点故障,实现高可用,所以注册中心是集群部署的,集群情况下这里Artemis就需要① 正确的管理所有的Artemis节点列表维护状态🎄,同时要② 能够正确进行服务实例数据的分发【一致性】🎄 --- 这也是所有集群都需要参考的problem
首先为了保证整个能够正确分发,那就解决第一个problem ----- 每个节点都需要知道集群所有节点以及其状态。
这里也可以将每一个Artemis当作一个应用,放到动态配置系统中,动态配置系统中会保存所有节点的访问地址
在获取到集群的工作地址之后,那么如何监控工作状态呢? ---- 健康检测,工作状态数据应当包含:节点是否可用、注册发现功能是否开放。节点通过获取的信息更新自己内部的可用节点列表。 这个列表也是会提供给客户端以及服务端供其选择一个进行交互。
server和注册中心的交互
server和Artemis的交互包含: 注册、反注册、心跳几种。
- 注册: 新增服务实例
- 反注册: 删除服务实例
- 心跳: 确保实例数据的有效性
注册的实例Server存在一个固定的TTL,如果没有收到心跳或者新的注册,那么这个实例就会自动删除。
因为Artemis是集群部署的,当和服务端交互的Artemis节点收到注册请求时,首先更新自己内存中的实例数据,之后需要将数据分发到其他的Artemis节点完成数据的同步。 【这个同步过程可能会因为意外失败,推送信息放入一个队列中,后台开一个线程定期从队列中取失败的数据进行重试, 直到数据推送成功或数据超过有效期】
可以看到注册中心集群主要就是要正确持有所有的实例信息并且进行数据同步,后续会就源码进行问题分析。
服务治理系统intro
服务注册发现和服务治理是服务化需要着重考虑的问题。用户可以通过服务治理系统进行服务管理 ---- 包括数据的元数据以及相关配置。 服务治理系统需要将数据推送
给相应的组件,使之生效。
就像Nacos或其他中间件一样,服务治理系统可以分为两个部分: 一部分是可视化操作的web页面(元数据管理、服务运维、服务配置管理、服务运行监控),另一部分是嵌入到代码中的核心API
javascript
服务元数据管理 ----- 服务基本信息的创建、编辑、删除
服务基本信息 --- 服务ID、类型、关联应用、归属部门、负责人、访问方式、当前状态...
服务运维 ---- 服务运行时的各项管理,服务实例管理、路由管理...
服务实例管理 --- 实例信息、状态、流量控制....
服务路由管理 --- 常规的均衡策略就是轮询,当数据中心故障,蓝绿发布、应用迁移,需要定制请求分配规则。 全局路由、操作路由、请求路由
服务配置管理 ---- 各个功能的开关和参数,限流熔断认证授权等功能
嵌入到代码中的API同样也包含服务元数据API、服务实例管理API、服务路由管理API、服务配置管理API..., 客户端和服务端通过API拉取配置信息,获取服务
服务化中间件在分布式系统中起着关键作用,这里只是从理论上简单分析了一下服务化中间件。后续cfeng会着手阅读源码同时尝试编写独立的服务注册中心和服务治理系统以及其他的中间件。【中间件和框架最终都是为了解决问题,如何更高效的解决问题远比随意引入中间件更加重要】🌳