微服务架构和实践

1. 微服务架构特点;

什么是微服务架构:

  • 一系列小服务的组合
  • 每个微服务都是独立的进程,都可以单独的运行
  • 微服务的构建要结合业务的能力,要围绕业务模型建造
  • 都可以进行独立的部署
  • 去中心化的管理

微服务架构特点:

  • 微服务力度:微服务的度量要围绕整个业务、功能做切分。比如说做二手交易平台,有用户体系、商品体系、交易体系、搜索体系、推荐体系,那微服务可以按照这五大体系垂直进行拆分。也就是说,把因为同一个原因而变化的功能聚合在一起做成一个微服务。把不同原因而变化的功能放在不同的微服务里拆分开,变成多个微服务。
  • 独立进程:任何的微服务从开发到测试、上线、运维都可以独立的进行。也就是说,任何的一个环节都不依赖于其它的一些微服务。线上对微服务进行修改上线以后,尽可能的不影响其它微服务。
  • 围绕业务建模:微服务架构一定是围绕业务模型进行打造的,而不能凭空打造(或者按照代码行数越少的标准去造),这都是不科学的。
  • 轻量级通信:微服务架构里,要求通信模式是轻量级的。也就是说,两个模块之间的通讯是和语言没有关系的(C++ 和 Java),通信和平台是没有关系的(Linux 和 Mac)。
  • 去中心化管理:微服务用的平台和语言都没有强行规定。

2. 使用微服务架构原因;

以二手交易平台举例,功能涵盖发布商品、分类搜索、关键词搜索、推荐商品、消息中心(私信、留言)、个人中心(用户体系)、运营功能等等。所以使用微服务架构原因

  • 业务功能多:搜索、推荐、交易、发布等
  • 用户体验好
  • 业务复杂性高
  • 满足业务高速发展需求:业务高速发展就必定对整个架构以及架构模式提出了高要求,使得系统高可用高扩展性快速迭代持续交付。任何一个模块(机器、进程)出问题都不能让整个系统不可用。

3. 微服务演进;

3.1 设计方案;

整体设计:

  • 水平分层(网关层、微服务聚合层、微服务层)。
  • 在每一层上,根据具体的也业务,再做一个垂直业务的拆分

每一层设计:

  • 微服务按照业务单元垂直拆分(商品、用户、交易、搜索、推荐)
  • 每一个微服务都尽可能无状态化
  • 微服务要作为独立进程开发、部署、运维、上线

高可用:

  • 高可用最核心的手段就是冗余。任何的单点(模块、机器)都是不可靠的,所以要部署多份
  • 微服务要求可以自动恢复

3.2 总体架构设计;

在这里插入图片描述

微服务网关层:

  • 作为客户端和服务器的第一层接入,它会维护海量的链接(HTTP 短链接、TCP 长链接等)
  • 对用户的请求、身份进行一些校验(合法性、登录情况校验,SESSION 管理)
  • 对请求做转发(网关层不会做任何业务的处理,只是把请求转发到微服务聚合层)
  • 另:对外提供的接口采用了通用的 HTTP / HTTPS 接口

微服务聚合层:

  • 根据用户的请求,拆分成多个微服务原子层的请求,向微服务原子层发请求,回来以后在微服务聚合层把每一个请求的结果汇集起来,最终提供给微服务网关层,网关层再把响应的请求结果返回给客户端
  • 微服务聚合层就是业务逻辑层。任何业务逻辑处理都在这一层做处理(商品,交易相关业务逻辑)。开发容易产生瓶颈
  • 采用 RPC 接口

微服务原子层:

  • 提供微服务的增删改查接口(商品增加、删除、查询等)
  • 采用 RPC 接口

微服务数据层:

  • 对每一个微服务的数据单独存在一个数据库里

去中心化管理:

  • 在实际操作中为了避免多个语言产生多余的开销,所以所有的微服务尽量用相同的语言开发

微服务注册、发现:

  • 需要一些微服务的注册中心,微服务网关可以发现微服务的聚合层,聚合层就可以发现原子层
  • 用户每一个模块相关的配置信息放在配置中心

3.3 存在的问题;

  • 微服务聚合层:扩展性差、仅一个 Process、多人开发冲突、业务耦合性高、性能瓶颈
  • 演进:单个微服务聚合层变成多个微服务聚合层。业务逻辑拆分变成业务物理拆分
    在这里插入图片描述
  • 拆分后,迭代开发只需修改相关业务聚合层的代码,不相关的业务聚合层不会有任何的干扰,这时候,开发、部署、运维将是非常高效和独立的,可以快速迭代、持续交付
  • 技巧:按照功能拆分,有利于进程的独立以及高效
  • 缺点:模块变多后,怎么样去进行自动化的管理

4. 通讯协议和服务的注册、发现;

4.1 轻量级通信协议;

  • RESTful 协议:基于 HTTP,和开发语言和平台都是没有关系的
  • HAL 协议:基于 RESTful 协议
  • RPC:远程过程调用(开源框架:Apache 的 Thrift,谷歌的 gRpc,阿里的 dubbo,dubbox)
  • 消息队列:任何两个微服务之间引入消息队列,可以把同步调用变成异步调用。上游要传递消息给下游,可以通过消息队列来进行写入,把消息从上游写到消息队列里去,下游就可以从消息队列把消息取出来进行处理,达到解耦的功能

4.2 通信协议选择;

微服务网关层:

  • 维护网关,采用 RESTful API 接口,通信协议采用 HTTP(HTTPS),数据传输协议采用 JSON

维护微服务聚合层,原子层内部:

  • 采用 RPC 协议(数据传输数据量比较小,HTTP 每次传输都要带个头,头的传输量比较大),基于私有协议自定义,传输数据包比较小。
  • RPC 可以基于 TCP 长链接,传输效率比较高。
  • 安全性方面高于 HTTP

4.3 服务注册 、发现;

在这里插入图片描述

微服务注册中心

  • 作为微服务,少不了的就是注册中心。也就是说,很多个微服务,怎么去发现每一个服务?这时候就要把微服务的 IP、端口号、配置信息等放在注册中心
  • 放在注册中心以后,几个微服务发现才能很好的去发现。比如说微服务聚合层要把每一个机器的 IP 信息放到注册中心里,微服务网关层才可以从微服务注册中心去发现这些 IP 并且去调用服务
  • 所以需要一个注册中心去存储 IP 信息、端口等,便于上游发现
    在这里插入图片描述
  • 注册中心的实现机制,分为 client 端和 server 端。server 端采取多个冗余的方式,任何时刻都有一个主的节点,其它节点都是从节点。主节点负责和 client 交互,获取到需要的配置信息
  • 当主节点挂了以后,其它的从节点会自动选取一个主节点并且继续对外提供服务。也就是说,整个注册中心本身具有高可用、高可靠的特性

微服务发现
在这里插入图片描述

  • 微服务网关要发现微服务,当微服务挂掉之后,如何保证微服务网关能够及时发现,把挂掉的微服务踢掉,保证任何一个请求都不丢失?
  • 首先微服务网关层通过刚才的注册中心可以获取到目前有哪些下游的微服务可以使用。当网关层从注册中心得到通知说微服务不可用以后,就可以把微服务踢掉
  • 但是一旦采用注册中心这种心跳机制来做以上的事情,微服务网关层从注册中心发现一些不可用的服务可能需要几秒钟的时间才可能完全发现并且剔除。
  • 在被发现的这几秒钟时间,怎么保证微服务网络层的请求都被正确处理?如图,微服务网关第一次会重试到微服务1上,由于微服务1已经挂了(timeout),这时候微服务网关就会向微服务2进行重试、把请求丢到微服务2上去。由于微服务2是正常的,所以可以正常请求,并且回复到微服务网关层,再返回给上游
  • 通过心跳信息(Keepalive)和超时重试(Retry)不同的微服务来保证任何一个请求都不会丢失
  • 所以微服务网关这时候做两件事情:下游发现和负载均衡

5. 柔性可用与服务治理;

5.1 柔性可用实践;

在流量高峰期,短时请求量大

  • 服务能力有限
  • 大量请求导致性能下降
  • 服务宕机
  • 系统雪崩

怎么办?做微服务柔性可用(服务降级)

  • 目标:保证核心服务可用;非核心服务弱可用,甚至不可用
  • 系统降级、数据层降级、柔性可用策略生效

5.1.1 系统降级;

拒绝部分请求:请求过来以后,会丢弃掉一部分请求,保留能承受住的这部分请求继续提供服务,其它多余的请求丢弃掉

  • 拒绝部分老请求

    • 减轻微服务请求处理数量
    • 确保新请求正常响应
    • 微服务内部采用 RPC 方式,任何一个微服务都有一个 RPC 队列(先进先出的队列)。队列收到上游发出的请求之后,首先会进入这个队列,此时工作线程会从这个队列里面拿出请求进行处理。当服务出现高峰期(负载比较高),工作线程从队列里面取出请求的时候,会查看请求时间。如果请求时间(出队时间)已经超过 1 秒钟,说明请求在队列里已经待了 1 秒钟,根据配置的丢弃策略,直接丢弃。这样就能保证新进来的请求能够处理。
    • 但是这个方式不够公平,也有可能丢弃的是核心请求,处理的是 非核心请求
  • 优先级请求

    • 非核心请求直接丢弃,处理核心请求
    • 任何一个请求都是有命令号的(或通过配置文件),根据命令号可以知道哪些请求是核心请求,哪些请求是边缘请求。当整个服务性能扛不住的情况下,就只处理核心请求,非核心请求直接丢弃。
    • 优先级请求方式的开启,是基于拒绝部分老请求,什么时候开启优先级请求,就要看请求出队的时间有没有超过 1 秒钟
    • 附:每个请求的内容称之为报文(json 格式或者 xml 格式),每个报文都会属于某一类,用 CMD 命令号,这个命令号会放在报文里边,字段的名称叫做 cmd,字段的值是在系统设计之初指定的接口规范中规定的
  • 随机拒绝方式

    • 随机丢弃一定比例请求
    • 网站一会儿可用,一会儿不可用

关闭部分服务(业务紧密):整个系统里面在高峰期的时候,把一些边缘的服务直接关闭掉。

5.1.2 数据层降级;

更新请求:在系统压力比较大的时候,更新请求做两件事情

  • 更新请求更新到消息队列,通过追加(append)方式先保存起来,消息队列是持久化的
  • 把请求更新到缓存,不会更新到整个数据库里

读请求:

  • 读缓存,不再读数据库

当高峰期过了以后,需要做数据补齐:之前已经把消息写到消息队列里,这时候还没有到数据库里,需要把消息队列里的数据慢慢的回放到数据库里。

5.1.3 柔性可用策略生效;

  • 柔性可用一定是系统层面和数据层面互相配合完成
  • 柔性可用策略不能依赖于人肉,要能自动打开。这就需要去做线下演练,保证线上生效。

5.2 服务治理;

  • 服务治理对线上是非常重要的,模块上线仅仅是第一步,需要对线上情况做监控,发现进程状态,及时发现问题,掌握主动权
  • 主要监控机器资源和进程状态

监控手段

  1. 监控是否还活着:在 Linux 下父进程通过 fork 命令开启一个子进程,子进程如果退出的话,父进程是能够收到退出命令的。收到退出命令以后,可以再把它拉起。所以进程监控可以做同样的事情,使用 supervisor 工具(相当于父进程),被监控的程序就是一个子进程
  2. 语义监控:监控仅仅能监控进程是否还活着,进程活着并不代表它还在正常工作,在这种情况下需要对进程的接口进行监控。可以模拟用户的请求进行发送,如果返回值和预期的返回值一样,说明整个进程还活着
  3. 错误日志监控:需要做语义监控,最核心的手段就是监控接口,监控模块的错误日志。当模块上线以后,它一段时间(比如每分钟)的错误量都是一定的。如果在某段时间错误量飙升,就表示系统应该是出问题了。
  4. 数据波动监控:比如说某段时间数据流量突增(突减)了 80%,通过之前几种监控手段是没办法发现的,所以这个时候需要通过数据波动的方式来做监控
  5. 机器监控:主要对机器内存、CPU、磁盘、网络做监控

微服务实时监控:微服务监控框架 Open-falcon,可以二次开发去支持语义监控

发布了125 篇原创文章 · 获赞 13 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/hualaoshuan/article/details/104251390