业务之前采用了单体应用的架构 不同功能模块的代 码耦合在一起,编译打包部署也都在一起。
有的人忘记提交代码、有的人忘记打包、有的人忘记修改工程依赖到最新版本。一次上 线过程需要反复确认,耗费了大量精力,严重影响了整体的开发和部署效率。
最后选定了服务化的解决方案 对原有的单体应用架构进行改造,把功能相对独立的模块拆分出去,部署为微服务
当前移动互联网时代最先进的业务架 构解决方案,能更好地迎合移动互联网业务快速迭代的要求。
单体应用的痛
然而随着业务规模的不断扩大,团队开发人员的不断扩张,单体应用架构就会开始出现问 题。
部署效率低下
应用编译打包、部署测试一次,甚至需要 10 分钟以上
团队协作开发成本高
超过 5 人修改代码,然后一起打包部署,测试阶段只要有一块功能有问题,就得重 新编译打包部署,然后重新预览测试,所有相关的开发人员又都得参与其中,效率低下, 开发成本极高。
系统高可用性差
某段代码不断在内存中创建大对象,并且没 有回收,部署到线上运行一段时间后,就会造成 JVM 内存泄露,异常退出,那么部署在 同一个 JVM 进程中的所有服务都不可用,后果十分严重。
线上发布变慢
特别是对于 Java 应用来说,一旦代码膨胀,服务启动的时间就会变长, 有些甚至超过 10 分钟以上,如果机器规模超过 100 台以上,假设每次发布的步长为 10%,单次发布需要就需要 100 分钟之久。因此,急需一种方法能够将应用的不同模块 的解耦,降低开发和部署成本。
想要解决上面这些问题,服务化的思想也就应运而生。
什么是服务化?
服务化就是把 传统的单机应用中通过 JAR 包依赖产生的本地方法调用,改造成通过 RPC 接口产生的远程方法调用
举个例子
以微博系统为例,微博既包含了内容模块,也包含 了消息模块和用户模块等。 其中消息模块依赖内容模块,消息模块和内容模块又都依赖用户 模块。 当这三个模块的代码耦合在一起,应用启动时,需要同时去加载每个模块的代码并连 接对应的资源。一旦任何模块的代码出现 bug,或者依赖的资源出现问题,整个单体应用 都会受到影响。
首先可以把用户模块从单体应用中拆分出来,独立成一个服务部署,以 RPC 接口的 形式对外提供服务.
什么是微服务
那么微服务相比于服务化又有什么不同呢?
服务拆分粒度更细。
微服务可以说是更细维度的服务化,小到一个子模块,只要该模块依 赖的资源与其他模块都没有关系,那么就可以拆分为一个微服务。
服务独立部署
每个微服务都严格遵循独立打包部署的准则,互不影响。比如一台物理机 上可以部署多个 Docker 实例,每个 Docker 实例可以部署一个微服务的代码。
服务独立维护。
每个微服务都可以交由一个小团队甚至个人来开发、测试、发布和运维, 并对整个生命周期负责。
服务治理能力要求高
因为拆分为微服务之后,服务的数量变多,因此需要有统一的服务 治理平台,来对各个服务进行管理。
什么时候应该拆分单体应用?拆分单体应用有哪些标准可依呢?
什么时候进行服务化拆分?
一个收费视频用户量访问过大导致内存泄露 因为免费视频和收费视频耦合在一起 最后导致免费视频无法观看
一旦单体应用同时进行开发的人员超过 10 人,就会遇到上面的问 题,这个时候就该考虑进行服务化拆分了。
服务化拆分的两种姿势
1是纵向拆分 :是将不同的功能模块 服务化,独立 部署和运维
标准是按照业务的关联程度来决定,关联比较密切的业务适合拆分为一个微服务,而功能相对比较独立的业务适合单独拆分 为一个微服务。
2是纵向拆分 :是从公共且独立功能维度拆分。
标准是按照是否有公 共的被多个其他服务调用,且依赖的资源独立不与其他业务耦合。
服务化拆分的前置条件
单体应用迁移到微服务架构时必将面临也必须解决的。
服务如何定义
每个服务都运行在各自的进程之中,应该以何 种形式向外界传达自己的信息呢
答案就是接口,无论采用哪种通讯协议,是 HTTP 还 是 RPC,服务之间的调用都通过接口描述来约定,约定内容包括接口名、接口参数以及 接口返回值。
服务如何发布和订阅
拆分为微服务独立部署后,服务提供者该如何对外暴露自己的地址,服务调 用者该如何查询所需要调用的服务的地址呢
注册中心
服务如何监控
需要一种 通用的监控方案,能够覆盖业务埋点、数据收集、数据处理,最后到数据展示的全链路功 能。
来关注我们最关心的是 QPS(调用量)、AvgTime(平均 耗时)以及 P999(99.9% 的请求性能在多少毫秒以内)这些指标
服务如何治理
服务的数量变多了,依赖关系也变复杂 了。比如一个服务的性能有问题时,依赖的服务都势必会受到影响。可以设定一个调用性 能阈值,如果一段时间内一直超过这个值,那么依赖服务的调用可以直接返回,这就是熔 断,也是服务治理最常用的手段之一。
故障如何定位
需要有一种解决方案能够将一次用 户请求进行标记,并在多个依赖的服务系统中继续传递,以便串联所有路径,从而进行故 障定位。
起走进微服务架构,来看看 它的各个组成部分
1.向注册中心注册服务 告诉我能提供什么服务和那个服务的地址
2.来服务消费者 ,查询所需要调用服务的地址 拿到地址发请求 拿到结果解析
3.服务的请求耗时、调用量以及成功率都被记录下来用监控 而调用经过的链路信息会被记录下来,用于故障定位和问题追踪
4.如果期间调用失败 可以通过重试等服务治理手段来保证成功率
总结一下,微服务架构下,服务调用主要依赖下面几个基本组件:
服务描述
注册中心
服务框架
服务监控
服务追踪
服务治理
服务描述
首先要解决的问题就是服务如何对外描述。的服务名叫什么?调用这个服务需要提供哪些信息?调用这个服务返回的结果是什么 格式的?该如何解析?
这些都是服务描述组件解决的 一般包括 RESTful API、XML 配置以及 IDL 文件
RESTful API 方式通常用于 HTTP 协议的服务描述,并且常用 Wiki 或者Swagger来 进行管理
IDL 文件方式通常用作 Thrift 和 gRPC 这类跨语言服务调用框架中,比如 gRPC 就是通过 Protobuf 文件来定义服务的接口名、参数以及返回值的数据结构,示例如下
注册中心
下一步要解决的问题就是服务的发布和订阅
提供者一启用 就向注册中心注册自己服务(会根据 服务发布文件的发布信息)
消费者在启动时 就向注册中心订阅自己服务(消费者配置文件 中 配置的服务信息)
再然后注册中心返回服务提供者地址列表给服务消费者
当服务提供者发生变化 ,注册中心将变更通知给服务消费者。
服务框架
在发起调用之前你还需要解决以下几个问题
服务通信采用什么协议? TCP、UDP 协议,还是采用七层 HTTP 协议,还是采用其他协议?
数据传输采用什么方式? 就是说服务提供者和服务消费者之间的数据传输采用哪种方式, 是同步还是异步,是在单连接上传输,还是多路复用。
数据压缩采用什么格式?比如常见的 JSON 序列化
服务监控
一旦服务消费者与服务提供者之间能够正常发起服务调用,你就需要对调用情况进行监控, 以了解服务是否正常。通常来讲,服务监控主要包括三个流程。
指标收集。就是要把每一次服务调用的请求耗时以及成功与否收集起来,并上传到集中的 数据处理中心。
数据处理。每次调用的请求耗时以及成功与否等信息,就可以计算每秒服务请求量、 平均耗时以及成功率等指标。
数据展示。数据收集起来,经过处理之后,还需要以友好的方式对外展示,才能发挥价 值。通常都是将数据展示在 Dashboard 面板上,并且每隔 10s 等间隔自动刷新,用作 业务监控和报警等。
服务追踪
原理:
服务消费者发起调用前,会在本地按照一定的规则生成一个 requestid,发起调用时,将 requestid 当作请求参数的一部分,传递给服务提供者。
服务提供者接收到请求后,记录下这次请求的 requestid,然后处理请求。如果服务提供 者继续请求其他服务,会在本地再生成一个自己的 requestid,然后把这两个 requestid 都当作请求参数继续往下传递。
服务治理
服务监控能够发现问题,服务追踪能够定位问题所在,而解决问题就得靠服务治理了。服务 治理就是通过一系列的手段来保证在各种意外情况下,服务调用仍然能够正常进行
单 IDC 故障。你应该经常听说某某 App,因为施工挖断光缆导致大批量用户无法使用的 严重故障。而服务治理可以通过自动切换故障 IDC 的流量到其他正常 IDC,可以避免因 为单 IDC 故障引起的大批量业务受影响。
依赖服务不可用。比如你的服务依赖依赖了另一个服务,当另一个服务出现问题时,会拖 慢甚至拖垮你的服务。而服务治理可以通过熔断,在依赖服务异常的情况下,一段时期内 停止发起调用而直接返回。这样一方面保证了服务消费者能够不被拖垮,另一方面也给服 务提供者减少压力,使其能够尽快恢复。