《极简微服务》

1 概述

1.1 写做的目的

《极简微服务》的原始动机是为了总结本身所学,但后来发现不少同窗在学习微服务后仍然一头雾水,处于一种知道可是还没有深入的阶段。我但愿可以经过《极简微服务》这篇文章,用尽可能少的语言将各部分的知识串联起来,帮助刚入门的同窗们从新梳理一遍,但愿可以让你们对微服务造成一个更清晰的认识。由于是“极简”,因此本文不会涉及到任何代码的具体实现。java

我想要为你们带来的思路是:linux

  • 微服务是什么?
  • 微服务包含了哪些东西?
  • 组件之间是如何相互做用,并构建成为一个总体?
  • 微服务会对咱们的开发带来何种影响?

首先要说明的是,我入门微服务走的是Spring Cloud相关技术栈,因此我可能很难作到彻底的脱离这个技术栈去总结。我对于微服务的了解可能也是肤浅的,某些方面上的理解可能也会存在一些误差,我更多的把这看做是一种记录和交流,由于我也不过是经过阅读书籍和一些博文后作了一些梳理,因此但愿读者朋友们可以有批判地阅读个人文字。数据库

当你们阅读个人文字,而后再提起微服务的时候,若是能说出更多本身想法,那这恐怕就是对我莫大的鼓励了。windows

由于叫作 “极简”,因此其实我已经尽可能想要控制好篇幅不要太长了,可是很无奈到最后仍是超过了本身所认为的最理想篇幅,由于我以为有些东西是不得不去了解的,望读者朋友可以见谅。安全

1.2 咱们的目标

其实就是微服务的目标啦。服务器

终极目标网络

经过将大的项目拆分红不一样子服务,不一样子服务相互协做,创造出一个分布式的、稳定的、高可用的、可控制的系统。

管理对象架构

服务。为了实现终极目标管理好各个服务,让他们之间的沟通无障碍。

所以,接下来我将针对咱们的服务与服务之间的关系来描述微服务。负载均衡

2 什么是微服务

2.1 微服务

微服务是一种架构风格 ,就是将业务系统拆分为不一样的服务,而后每一个服务是独立的。不一样的服务经过轻量级的协议通讯(如HTTP)。部署的时候,一个服务可能会有多个实例。服务与服务的合做,构成了一个完整的系统。框架

经过微服务咱们能够达到一些理想的效果。

  • 组件化
  • 可伸缩
  • 面向错误设计
  • 职责分明
  • 技术多样性

    ...

2.2 什么是好服务

  • 高内聚:相关的东西都扔一起,不然出BUG不知道哪里找问题。
  • 松耦合:不强依赖其余服务,减小每次改动所影响的范围。
  • 独立性:能够开发、测试、部署,不受其余因素影响。
  • 好看:指的是接口好看,好用。

3 微服务的组件

3.1 配置中心

3.1.1 配置的发展

有一种说法是,开发人员是被迫写配置的。由于开发者得让本身的软件去适应不一样的变化。

650,450

一开始是写配置文件,可是太零散,因而将配置都写在一个大的集合里面,好比数据库或者一个文件。

可是存在几个问题:

  • 不容易拓展:就一我的文件或者数据库,通常就只能读取和修改。想要别的功能,SORRY。
  • 边界模糊:谁来管理这个大的集合体?权限怎么分配?怎么保证你的修改不影响到别人?
  • 单点故障:数据库挂了,文件丢了,读取这个集合的配置的应用也均可能受到影响。固然能够经过一些手段解决,但大都比较麻烦。

因此,后面提出了 配置中心 ,但愿可以解决上述的问题。

3.1.2 需求

对于程序而言,它但愿:

  • 配置与程序部署彻底分离
  • 调用可别太麻烦了
  • 配置有变化请立刻通知我
  • 配置中心千万别挂掉

对于配置中心而言,它但愿:

  • 隐私,加密,配置得是足够安全的
  • 权限,每一个人只能读取本身的配置

3.1.3 配置中心工做流程

800,600

3.1.4 问题

既然配置中心存了全部服务的配置,当服务们要加载配置就至少要和配置中心通讯一次。若是说服务要硬编码配置中心的地址,假如配置中心换个地址,那么就必须手动修改全部服务的这个配置。当服务数量达到几十个的时候,这简直是个噩耗。

因此硬编码地址显然不是一个好的方案。

微服务架构里面,配置中心也是一个服务。发散的思考一下:不一样服务之间的通讯是怎样的?总不可能都是硬编码吧?

3.2 服务发现

3.2.1 问题

回顾上一个章节的问题,服务之间应该如何通讯。简单来讲就是:服务太多了,不知道怎么才能找到对方。

3.2.2 方案

其实很简单,咱们找一个第三者,让第三者告诉咱们就行了。就像是出去旅行同样,不认识路的话,你查百度地图就行了,让地图告诉你具体的位置。

800,550

因此咱们要抽象出一个中间服务,专门用来作这个事情,告诉你其余服务的位置,这个过程就叫作服务发现。而其余服务告诉这个中间服务本身的位置的过程,就叫作服务注册(相似于把本身的位置告诉百度地图,让他记录你的位置)。

3.2.3 需求

服务注册/发现中心:

  • 我很懒,其余服务大家要本身上门注册本身的位置啊。

其余服务(客户端):

  • 方便我查其余服务的地址;
  • 我无论,反正你不能挂掉,否则我好不着北;

3.2.4 流程

不一样的服务注册、发现中心实现,流程可能存在差别。我在这里只拿Eureka来看一下(目前我也只了解这个 = = )。

600,800

说明:

  • 启用多个Eureka ,多个Eureka 实例信息共享,防止一个服务中心挂掉致使所有服务不可用。
  • 启用客户端的时候,客户端本身告诉Eureka 本身是谁,地址是多少。
  • 客户端(消费者)按期从服务中心Eureka处拉取最新的服务地址,这个服务地址就像是一本地图小手册,上面记录了全部服务的地址。这个客户端只须要定时更新这个小手册,保证它是最新的就行了。

3.2.5 问题

服务注册于发现机制,解决了不一样服务之间的位置问题。可是仅仅是这样是否足够呢?

来听一听客户端的疑问:

我就想去吃鸭脖,你这个地图小手册,鸭脖店的地址怎么有两个啊?那我到底要去哪个店家呢?

3.3 负载均衡

3.3.1 问题

选择鸭脖子店的问题,严肃一点来讲,就是当拥有多个服务实例的时候,选择哪一个实例去调用的问题。

这个过程实际上就叫作负载均衡。

3.3.2 负载均衡

负载均衡能够分两种类型:服务端的负载均衡和客户端的负载均衡。他们之间存在什么样的差别呢?

服务端负载均衡

600,300

顾名思义,就是把负载均衡(选择哪一个鸭脖子店的选择权)在服务端完成。在这种方案下,其实对于客户端来讲,就不存在选择的问题了。当客户端说 “要吃鸭脖” 的时候,服务端查看本身的地址列表,发现有两个鸭脖店,那么服务端会挑一个店的地址告诉客户端。

怎么挑选呢?一般能够根据目标服务实例的网络情况,负载的请求数量,甚至是随机分配等,通常都是事先制定好一套规则。

客户端负载均衡

600,300

相对于服务端的负载均衡,客户端负载均衡就是把所谓的选择权交给客户端。也就是说,有多少个可用的服务实例的地址,服务端就返回多少个地址。客户端要调用哪个服务实例,彻底由本身去选择。

一样,客户端怎么去选择,通常也都是预先设定好规则的。

3.3.3 问题

如今,服务与服务之间的通讯,服务注册与发现解决了 “在哪里” 的问题;负载均衡解决了 “若是有多个位置应该去哪里” 的问题。服务注册/发现 和 负载均衡是属于相互合做的关系,共同解决了 “去哪里” 的问题。

可是咱们要如何保证客户端真的顺利到达目的地呢?

严肃点说就是:要如何保证客户端对目标服务的调用是正常的?

3.4 弹性

3.4.1 问题

接过上一小节的问题,你以为咱们应该如何保障咱们服务之间的调用是正常的呢?

为了回答这个问题,咱们先抛出一个概念,叫作 “弹性”。

何谓弹性呢?弹性对于不一样的对象来讲略有不一样。

对于客户端来讲:

弹性就是是否有响应。任何一个请求都应该有响应,且响应时间不该太长。

对于被调用的服务端来讲:

弹性就是自我保护。为了保护正常的运做,我可能会拒绝一些请求,以保障服务没有由于过多的请求而崩溃。

咱们在这里打个比方。服务之间的调用是正常 就像是 去店里买蛋糕,这就是一个 “是否能顺利抵达目标地点并买到蛋糕” 的问题。

在这里咱们首先要明确,确定不能保证每一个人都可以顺利抵达商店,由于目标商店随时均可能会 “关门不干”;其次,就算抵达了店里,也不必定可以买到蛋糕,由于可能卖完了,或者机器出故障了。

因此咱们要换个思路,若是店家关门了,我就提早告诉它关门了,你最好别去了;或者你已经到了店家但发现蛋糕都卖完了,因而你改为买饼干,或者是你干脆直接去别的店里买。

3.4.2 方案

维持弹性的方案有很多,其实以前也有碰到过,让咱们来总结一下。

以前咱们学习到的有:

  • 服务发现与注册机制:移除注册但已死掉的服务实例,这就保障了客户端不会调用到已经崩溃的服务啦。
  • 负载均衡:选择好的服务来调用。调用状态正佳的服务才会有快速的响应。

再来看看其余的方案吧:

  • 断路器 :就像是保险丝同样,若是请求过多了服务器承受不住,或者服务器长期有问题。就断开链接。不让后续的请求过来了。
  • 后备模式:若是不当心碰到了服务没反应或者网络故障,拿出一个B方案临时处理。
  • 舱壁模式 :就是隔离性。将某个服务(或者某些服务)进行隔离,就算调用它出错了,也不影响其余的服务调用。把影响控制在必定范围内。

因为服务发现与注册机制、负载均衡在上面的章节已经有介绍了,故在此就再也不赘述。下面会围绕其余的方案来进行分析。

3.4.3 流程

断路器的流程

微服务中最多见的就是断路器了,下面来看看断路器的流程(不一样的断路器实现可能会有所差别):

970,650

如上图所示,有四个对象,分别是用户、客户端、断路器、目标服务。

由用户向客户端发起请求,客户端调用目标服务来完成用户的指望。断路器在这其中承担了客户端与目标服务之间的 “中间人” 的角色。

通讯能够划分为三个阶段:

  • 第一阶段:客户端对目标服务的调用 全放行。此时断路器认为目标服务没有问题,因此所有放行。可是当达到一些特定指标(好比必定次数之后的故障比率)之后,断定目标服务已经出现问题,则断路器切换到第二阶段。
  • 第二阶段:客户端对目标服务的调用在一段时间内 全拒绝。通常来讲,第二阶段过了一段时间之后才会触发第三阶段的检测。
  • 第三阶段:客户端经过特殊机制 检测目标服务是否已经恢复正常。若是目标服务已恢复正常状态,则切换到第一阶段,不然切换到第二阶段。

后备模式的流程

其实很简单,用伪码来表示就是:

boolean success = callService();
if (success) {
    doSomething();
} else {
    excutePlanB();
}

其实后备模式是能够和断路器结合起来使用的,当在断路器流程中,判断目标服务出现问题后的第二阶段,客户端的调用能够所有走Plan B。

舱壁模式的流程

其实就是隔离,隔离的方式有不少种,好比线程的隔离,模块的隔离,地域隔离等。这里咱们拿线程隔离的举个例子:

600,300

上图中,本来客户端对全部服务的调用都使用同一个线程池。

当某个目标服务A出现故障的时候,堆积在这个服务的调用越积越多,一直到线程池中的线程全被占用了,此时客户端新来一个须要对服务B的调用,却没有线程池能够用了,只能排队等待。

解决方案很简单,事先将不一样的服务划分到不一样的线程池中去,这样就不会出现一个服务占用资源,致使其余服务不可用的状况了。

3.4.4 问题

如今咱们不只解决了 “去哪里” 的问题,还解决了 “是否能抵达并买到东西” 的问题。

让咱们好好想一想,咱们如今解决的都是服务与服务之间的通讯问题。若是是外部服务(咱们微服务体系外的客户端)要与咱们的服务通讯,如何解决呢?

3.5 网关

3.5.1 问题

接回上一小节的问题。

问题描述

内部服务与服务之间,是经过一本字典来查找对方的位置,可是若是是一个“外国人”(外部服务),一方面我不能把字典给他由于字典是机密,其次,就算给了他他也看不懂毕竟文字不通。

分析

所谓内部服务,通常对外都是不可见的。咱们经过服务之间的合做给外部提供一个总体,因此对外而言咱们应该是一个总体。基于安全性考虑咱们也不能讲内部服务暴露给外部服务使用。

解决方案

选举出一个中间人,专门用来和外部服务通讯。由这个中间人来判断对方是否是合法的请求,而后作相应转发工做。

这个中间人又像是一个守门人,只接纳有“令牌”的人,并“通风报信”。

550,400

3.5.2 流程

970,700

其实没有太多想要说的。咱们看一下网关所处的位置,恰好就是处于对外来请求的“守门人”的位置。咱们只须要明白网关的做用便可。

很明显,网关的做用有:

  • 验证和受权:你从哪里来?看一下随身令牌?
  • 路由(动态/静态):你要到哪里去?来,往这儿走!
  • 负载均衡:有两个蛋糕店,你去这个好了。
  • 流量控制:人满了,不能让你进来啦,抱歉!
  • 数据搜集、日志:等我记录一下,你从哪里来,去哪儿,买了啥。
  • 其余公共需求:略略略。

3.5.3 问题

想必到这里,你已经基本了解服务注册与发现、配置中心、负载均衡、断路器、网关之间是如何共同工做的了。

如今惟一的问题是,相对于以前的单体架构系统来讲,服务的数量变多了,服务之间的通讯也变多了。系统反而一会儿变得复杂了。若是服务与服务之间的调用出了问题,我应该怎么排查问题呢?

3.6 日志

3.6.1 问题

接回上一小节问题。

问题描述

相对于单体架构系统而言,微服务架构牺牲了原有的简单,换取了系统的灵活性。因此微服务看起来反而变得更复杂了。一个请求,可能要通过网关、服务与服务之间来回的调用,因此作的日志也都十分零散,怎么监控系统、排查问题,变成了使人头疼的问题。

3.6.2 解决方案

来自风筝的启发

300,300

不管风筝怎么飞,只要我手里握着一条线,我就能知道风筝在哪里。咱们能够借鉴这个思路,为咱们的请求创造出一根看不见的 “线” 。

TraceID

700,450

如上图所示,当请求进来的时候,我只须要为这个请求添加上一个标识(traceID),无论后续这个请求被如何转发,只要带有这个traceID,那他们确定是同一请求。

这个traceID不只仅要可以被转发,作日志的时候,也要将traceID一并记录下来,这样无论日志分散在哪一个服务,我均可以知道他们是否是同一个请求产生的。

经过traceID咱们能够实现请求的链路跟踪问题。

日志搜集

咱们知道,不一样的服务多是部署在不一样的服务器上的,因此才会显得零散。若是咱们要查日志,确定不可以来回登陆到不一样服务器上去查。因此,咱们须要将全部的服务的日志统一搜集起来,统一管理。这叫作日志聚合。

3.6.3 流程

600,500

经过将全部服务的日志统一搜集起来,统一存储,统一分析。再经过TraceID作链路的跟踪,咱们就能够搭建出一个日志管理和分析平台。

如此,在微服务架构下,监控和查找问题,变得一目了然。

总结

如今来回顾一下,微服务的组件,都还记得有哪些吗?

来看一下他们是如何相互协做的吧!

1000,750

4 测试

4.1 测试分类

4.1.1 测试类型

(这只是从一种维度上去划分,划分的维度能够有不少)

  • 面向业务的测试。如验收测试、可用性测试等。
  • 面向技术的测试。如单元测试、集成测试、性能测试、安全测试等;

4.1.2 单元测试

是函数级别的。一般咱们在这里捕获到大部分的错误。

4.1.3 服务测试

服务级别的集成测试。测试某个服务的功能。

4.1.4 端到端测试

系统测试,多个服务的测试。一般须要在页面上用鼠标点点点。

4.2 测试的手段

对于单元测试而言,有时候一个函数依赖于另一个函数,也就是说,另一个的正确与否,会直接影响到我这个测试的结果。因此有时候咱们须要制造必定的隔离空间。

对于服务测试来讲,也存在这样的问题。

如此来讲,测试的隔离性咱们须要重视。

为了创造这种隔离性,咱们能够用Mock、或者打桩技术。

4.2.1 打桩

所谓打桩,最简单的理解就是你能够认为是“写死”,a函数,须要依赖b函数的返回值。那么咱们能够将b函数的返回值“写死”。这就保证了b的返回确定不会出错了。

看似简单,可是你不能直接修改函数b,由于很容易出错,如果你忘了改回来,就把你“写死”的代码一并提交了。

4.2.2 Mock

Mock和打桩很相似,区别在于,打桩是不关心你函数b(即你这个测试要依赖的那个函数)执行了多少次的。而Mock不只仅能够模拟调用函数b不少次,还会不少其余的问题,好比,调用是否成功等。

咱们一般借助一些测试框架来打桩和Mock,好比Java最经常使用的JUnit。

4.3 测试金字塔

900,650

如上图所示,不一样的测试,会带来不一样的效果。

  • 测试范围越大,会让咱们对本身的系统更有信心。范围越大的测试,测试时间越长,致使反馈时间比较越长;
  • 底层的单元测试测试很快,可是单元测试是函数级的,单元测试的数量大。由于单元测试范围小,因此问题定位会比较精准,普通的错误咱们甚至能够定位到“行”;
  • 金字塔的比例是能够变化的。咱们应该针对现有的系统去改造。为这三者找到一个合适的测试比例。但每一次改造都会产生额外的成本,成本随着项目规模愈来愈大。

4.4 自动化

随着服务愈来愈大,测试愈来愈多,人工的测试变得愈来愈困难。微服务离不开自动化测试。因此咱们须要借助CI/CD来让咱们的测试变得自动化。

5 持续集成

持续集成对于微服务来讲真的很重要。微服务组件解决的是技术上的问题,而持续集成所解决的是流程和效率上的问题。

持续集成可以加快微服务架构下的开发、测试、部署,可以帮助咱们更快的发现和解决问题。

初闻持续集成,让人摸不着头脑,怎么会有如此晦涩的词语呢!

可是且慢,先来看看哪些典型的场景:

  • 咱们写完代码后,提交到SVN/GIT,而后本身打包,登FTP将打包好的代码上传到测试服务器,而后对服务器 shutdown/startup。
  • 一我的修改了不少东西,可是不当心改错了某个东西,可是他提交了,这时候没人知道出错了。
  • 几我的一块儿开发同一个服务,由于周期较长,其中有一我的长时间不提交代码,一个月后,他要提交的时候发现,全是代码冲突都不知道怎么merge了。

这些场景都使人头疼,他们的共同特征是:要么都是重复的工做,要么是常常出现的问题,对项目工期、团队协做产生了较大的影响。

咱们须要解决这些问题,用的手段就是持续集成。接下来咱们就来解释什么叫持续集成。

5.1 CI 持续集成

所谓持续集成(Continuous Integration)。

先来看一下什么叫作集成。什么是集成呢?集成就是将代码提交到主干,经过一系列自动化的工具来构建(你能够简单理解为打包)和测试,验证是否有错误,是否会对其余人的代码产生影响。

因此持续集成,就是不断的进行集成,即常常提交代码以集成。持续集成的目的就是尽早集成,早点发现错误,早点解决问题。

咱们谈到CI的时候,每每涉及到几个方面:

  • 自动化工具:人工手段的集成是及其低效率的,因此咱们须要借助自动化工具来协助;
  • 版本管理:拥有一套良好的版本管理机制,咱们才可以更好的进行持续集成。
  • 多提交:。因此开发者得有这样的意识,多提交代码,多集成。
  • 多写测试:有测试才能发现问题。

这其实也就是技术和流程问题。

一个好的持续集成环境是怎样的?

代码提交后自动(或者按期手动)触发持续集成:自动跑单元测试,自动构建代码,自动上传部署。不须要过多的人工参与。中间每一步出现问题的时候,都会立刻经过一些手段进行反馈,防止出现更多的错误。

5.2 CD 持续部署

咱们谈论CI的时候,不少时候也包含了持续部署(Continuous Delivery)的含义在里面。

何谓持续部署?

是CI的下一步。CI经过自动化的流程,确保软件语法和单元测试上是没有问题的。可是还不够,因此下一步须要将软件的新版本交给质量团队或者用户。让他们去继续测试、评审。若评审经过则说明代码就能够进入生产阶段了。

5.3 常见的CI/CD工具

  • Jenkins
  • Travis CI

6 容器

容器也是微服务架构不得不去思考的一个问题。它解决的是部署的问题。

6.1 部署的问题

部署有哪些问题呢?

  • 不一样服务器之间环境存在差别且这些差别难于发现。环境的差别性可能会致使许多让人意想不到的问题。
  • 要新增或者删除一台服务器成本较高。包含时间成本和金钱成本。要能达到部署标准的服务器,须要装各类软件和配置很多环境变量,很难保证新配置的环境彻底没有问题。并且不一样服务的部署,所须要的环境也是不一样的。
  • 难于管理。服务器数量几十台的时候,你们基本上处于战战兢兢提醒吊胆的状态,由于根本管不过来。

6.2 虚拟机

能不能减小服务器的数量,在一台服务器部署多个服务,而且能作到能够支持多种服务的部署?

要支持不一样服务,确定要支持不一样的环境,好比windows,好比linux。

其实能够的,用虚拟机嘛。

虚拟机的大概思路是:

将整个环境先搭建好,而后打包成为虚拟机镜像,每次须要增长一个新环境的时候,直接实例化作好的镜像便可

900,550

一方面,虚拟机技术解决了环境的问题,部署比之前快了很多;

另外一方面,构建镜像耗费时间长(一旦环境须要改变的时候,或者须要多个不一样环境的时候),镜像文件大;而且,虚拟机的管理也须要占用额外的资源和空间;

虚拟机技术的特色是:

  • 拥有一个Hypervisor,用来管理全部的虚拟机;
  • 实例化的镜像中,是一个独立的空间,拥有独立的操做系统,内核,应用;
标准的虚拟机中存在一个Hypervisor,它会帮助咱们管理运行在Hypervisor之上的其余虚拟机,包括资源的分配,外部的请求路由管理,内存的映射等;虚拟机越多,Hypervisor占用的资源越多;

6.3 Linux 容器

即Linux container,简称LXC。

LXC的原理是,建立一个隔离的进程空间,在这个空间中运行其余的进程。而且由物理机的内核来完成资源的分配工做。

以下图所示:

400,600

与传统虚拟机不同的地方是:

  • 不须要Hypervisor
  • 隔离的空间内没有内核
  • 启动快,只须要几秒
  • 更轻量,对资源利用更充分

6.4 Docker

如今你们都知道Docker了

LXC是操做系统级别的虚拟化方案,毕竟是Linux下的容器。是否存在应用级别的容器技术呢?

那就是Docker了。

Docker的发展

2013年,Docker横空出世的时候,在底层上也借助了LXC来管理容器,而后本身在上层作其余的管理工做。可是过了几年,Docker 0.9的时候有了新欢libcontainer,LXC就变成了一个“备胎”,此时Docker能够选择再也不依赖Linux部件了。再Docker 1.8的时候,LXC被认定为“前妻”。

再到后来,libcontainer上位。Docker致力于去实现容器化的标准,你只须要实现libcontainer提供的标准接口,那么你就可以运行Docker,这为Docker的全面跨平台提供了可能。

Docker的特色

分层

一个镜像能够分为任意多层,好比:

  • 操做系统层(第一层)
  • 依赖库(第二层)
  • 软件包和配置文件(第三层)
  • 运行的应用程序(第四层)

若是几个镜像拥有相同的层。好比,镜像A和镜像B用的是相同的操做系统,那么下载A时已经下载好了这个操做系统,下载B的时候,就不须要从新下载了,只须要下载第一层之上的数据便可。

增量更新/版本管理

对于一个公共镜像A来讲,有许多镜像可能都是根据它来制做的,而镜像A制做好了便不能够改变。但对于其余镜像来讲,有时候一些环境变量不免须要改变,这时应该怎么办呢?

Docker中约定:

  • 上层的优先级大于下级
  • 层都是只读的

这样,只须要在最上层添加一个读写层,将须要改变的配置都集中到这个层来进行改写。在写的时候同时拷贝出一个只读属性的文件备份,应用实际读取的时候读取的是这个只读属性的拷贝。

400,250

如上图所示,底层中环境变量A是1,可是在读写层,咱们将A设置为3,那么应用程序读取的时候,读取到的是A=3。而读写层不只仅能够修改配置,还能够将移除某些组件。每新加一层发布出去的时候,就至关于发布了一个更新。这样的一个好处就是,对于以前发布出去的镜像,咱们拥有了 增量更新版本管理 的能力。

Docker的构成

Docker采用了C/S架构。分为Client和Server,而后还借鉴了Git的思想,能够搭建本身的中央镜像仓库。大致的架构以下图所示(图片来自于网络):

700,500

须要解释一下几个名词:

  • Image:镜像。一个可执行的包。它包括了一个程序要正常运行,所依赖的包括应用程序自己在内的软件,环境变量,配置文件,依赖包等环境;
  • Container:容器,一个镜像的运行实例;
  • Docker-Daemon:一个运行在后台的守护进程,能够看作是Server;
  • Registry:镜像注册中心,这里存在着各类镜像,用户能够上传或者下载上面的镜像。分为public和private,咱们还能够搭建本身的Registry;

咱们所说的Docker,一般是指Docker Engine,它包括了:

  • Docker-Daemon
  • REST API
  • CLI

其中,REST API和CLI都是用来跟server交互的。

6.5 与CI合做

咱们原先所谓的部署,对于Java来讲,都是将代码打包成jar或者war,也就是说,jar和war就是咱们CI的构建物。

采用了容器技术之后,CI每次集成的结果是一个容器镜像,那么咱们就只须要在服务器将这个镜像实例化就能够了,从而不须要关心环境的差别问题。

7 总结

微服务经过将系统拆分为不一样的服务,经过服务与服务之间的相互协做,构成一个总体。

在微服务架构下,咱们关心服务与服务之间如何通讯。因此咱们会单独构建一个服务中心,专用用于帮助服务与服务之间更好的沟通;再经过断路器的方式,为咱们的服务提供保障,让服务间的调用具有弹性;此外,咱们还会独立出一个服务,专门管理服务的配置;考虑到咱们须要支持外部的访问,因此咱们独立出一个网关,用来承担“看门人”的角色。上述的种种为系统带来了巨大的复杂性,为此,咱们还单首创造创一套日志聚合和链路跟踪机制,用于监控微服务的状态。

除了这些,咱们还须要经过持续集成和容器技术来帮助咱们达成更高效的开发、测试、部署效率,让服务具有更好的伸缩性,要增长新的服务实例的时候,只须要再实例化一次镜像便可。

仿佛一切都变得美好了,这就是微服务。

8 参考书目

《Spring微服务实战》

《微服务设计》

(这是个人原创文章,若要转载,但愿你们可以注明出处,谢谢你们~)

相关文章
相关标签/搜索