Java微服务开发指南 — Java环境下的微服务

Java环境下的微服务

本文涉及的内容,能让你学到什么/h2>

    本书适用于开发微服务的Java开发人员和架构师。我们在开始介绍微服务架构前,先讲述一些抽象的基本概念。不幸的是,使用新技术并不能神奇地解决分布式系统问题。但是我们通过一些做的很好的公司,它们是如何使用微服务来进行构建的,包括文化、组织结构和市场压力。然后我们深入了解几个Java微服务框架,附带的源代码反馈可以在GitHub上找到。我们会讨论有关部署、集群、故障转移以及Docker和Kubernetes在这些领域是如何解决这些问题。随后我们会重点介绍一些使用Docker,Kubernetes和NetflixOSS的示例,以演示微服务架构。我们这么少的章节无法讨论所有的问题,但不代表除了这些其他的都不重要,比如:配置、日志记录和连续交付。

    微服务不仅仅是技术上的讨论。 微服务的实现源于复杂自适应理论,服务设计,技术演进,领域驱动设计,依赖考量等背景。 它们允许使用这些技术的组织,能够真正地展示敏捷、快速响应并在快速发展的商业世界中保持竞争力。 让我们近距离的来看看吧。

你实际是在为一家软件公司工作

    软件正在统治这个世界。企业正在慢慢意识到这一点,这个现象有两个主要的驱动因素:通过高品质的服务和技术的快速投产来提供价值。 这本书主要是涉及到动手实践,但在我们深入了解技术之前,我们需要适当地了解整个环境以及关键因素。近年来我们一直在谈论让企业如何变得敏捷,但我们需要充分了解这是什么意思,否则一切都是都是白搭。

服务的价值

    100多年来,我们的商业市场一直在创造产品,并推动消费者想要这些产品:书桌,微波炉,汽车,鞋子等等。 “生产者主导”经济背后的理念来自于亨利·福特(Henry Ford)的观点:“如果您能以低成本生产大量产品,市场几乎是无限的”。为了达到目的,还需要几个单向渠道直接向客户进行营销,以说服他们他们需要这些产品,并且他们的生活将会由这些产品得以大大的改善。在20世纪的大部分时间里,这些单向渠道以电视、报纸、杂志广告和高速公路广告牌等形式存在。然而,这个生产者主导的经济已经翻篇了,因为市场中充满了过剩的产品(你需要多少手机/汽车/电视机此外,互联网以及社交网络正在改变公司如何与消费者(或更重要的是消费者如何与他们互动)的交互渠道。

    社交网络使作为消费者的我们能够更自由地彼此分享我们对于公司产品的看法和意见。与营销渠道相比,我们更加相信自己的家人和朋友。这就是为什么我们去社交媒体选择餐馆、酒店和航空公司。我们以点评、评价以及朋友圈等等形式进行反馈,好的反馈能够对公司的品牌产生积极的推动作用,反之,能让某些公司伤透脑筋。现在,公司和消费者之间的双向关系前所未有,公司需要更加努力的经营自己的品牌。

chapter1-2.png

    开源技术也是技术领域的引领者。随着时间的推移,开发人员可以使用开源技术用很低的成本构建一个原来需要昂贵专有软件才能构建的产品。这驱使社区构建了诸如:操作系统(Linux)、编程语言(Go)、消息队列(Apache ActiveMQ)和Web服务器(httpd)等知名的产品。即使是最初拒绝开源的公司也开源他们自己的技术并为现有社区做出贡献。随着开源和开放的生态系统已经成为常态,我们开始直接从开放源码社区(例如:Apache Spark、Docker和Kubernetes)看到软件技术的大量创新。

纷乱

    服务设计与技术的进步,能使更多的人开始创建自己的服务,可以学习编程,使用框架,并且利用按需计算(serverless)进行服务的构建。可以利用微博、微信渠道与客户进行免费的沟通。随着我们市场的快速发展,任何一个创业公司的新点子的有效实施,都会使得原有公司的业务死的很惨。

    而这个事实让大多数CIO和CTO感到害怕。随着软件成为成为公司构建服务,经验和差异化的关键因素,许多人意识到他们必须成为各自垂直行业的软件公司。以前企业将IT视为成本,而今发现它已经变为与对手比拼的关键,为了不落后于对手,他们必须变得敏捷起来。

拥抱组织结构的敏捷

    大多数诞生于20世纪(工业时代)的公司并不是以敏捷的方式进行构建。它们的构建是为了最大限度地提高效率、减少流程中的变化、消除工人的创造性思维,并将工作人员组装成流水线的方式。整个过程被构建成类似机器一样,接受输入,经过高度定制调优的流程,完成生产输出。这种自上而下的分级管理结构,对于变化也是自上而下的思考,来自底层的信息经历了许多层面的管理和传达,最终到达高层,经过高层的决断后再下派到下层,而这一过程一般需要18个月左右的周期。这种组织方法能够极大的进行产品生产并尽可能的压榨流程中的每一点效率,但它并不适合用来提供服务。

chapter1-4.png

    团队之间通过承诺来进行沟通,这种方式的目的是将服务发布的内容和计划让其他组件知晓,使他们能够使用到自己的服务,而描述这些承诺就是需要足够的wiki以及文档。如果文档不够好、API定义也不清晰,那么服务提供方就没有做好他们的工作。

    每个团队都有涉及服务、技术选型、解决问题的职责,他们会在部署、管理服务上花时间,甚至可能会在凌晨2点起床处理问题。例如:在亚马逊,有一个单独的团队负责税率计算功能,而这个服务会在订购时被调用。这个服务的模型(Item,Address,Tax等)在团队内大家都心知肚明,这个团队拥有税率计算服务的设计、开发和运维的权限。围绕这些,亚马逊也提供了非常成熟的自动化技术,用于服务的构建、部署和运维。

    我们能够使用微服务来定义服务的范畴,它能帮助我们便于:

  • 理解具体服务的工作,避免一开始陷入到大应用的过多概念中
  • 本地快速构建服务
  • 为问题域采用最适合的技术(写多多延时并发
  • 测试服务
  • 和其他的服务保持独立的构建、部署和发布的节奏
  • 能够按需的识别出架构中需要伸缩的部分
  • 能够平滑的升级系统

    微服务帮助我们解决: 我们怎样能够快速响应,怎样解耦服务以及组织团队 的问题。它允许团队专注于提供的服务以及面对问题的快速响应,而避免了不必要的技术或者组织同步。下面这些内容是你采用了微服务架构后,不会遇到的问题:

  • 跨工程的需求
  • 不必要的会议
  • 共享类库
  • 企业级共享模块

    微服务架构是否适合你服务架构提供了很多好处,但是它也带来了它自己的不足之处。你可以认为微服务是一种处理问题有偏向性的优化方式,它专注于问题的快速和可伸缩的解决,但并不一定是成本最低的解决方式,它可能造成资源的集中,或许从开发者的角度去看,或多或少有些结构上的重复。运维操作嘛,会有一些复杂度,而且微服务架构实施后,会使得开发人员不是那么容易从全局看清整个系统,这使得进行问题调试的想法变得很困难,在某些场景下你必须对强事务做出一定的牺牲,而最重要的开发团队对这种开发模式并不一定熟悉。

    不是每一块业务都是能够使用很少的资源进行改造为微服务架构的,也许面向客户的前台系统可以,但是后台支撑系统就没那么容易。但假设两种模式的系统一旦混合在一起使用,我们能够发现微服务架构能够慢慢的影响到整个系统的其他部分,让它们慢慢改变。

挑战

    用微服务架构设计云端和本地的应用需要思考它们在构建、部署和运维上的不同,我们不能及其悲观的看待每一次微服务调用,用容错等方式处理它。而事实上,那些用微服务架构组织的复杂系统,确实需要我们去应对不确定性,在这个章节将会介绍5个主要的相关方面,而在后续开发微服务时,需要时刻记在心上。

应对失败(design for failure)

    在复杂的系统下,任何内容都是不可靠的,磁盘的损坏,网线插口被拔掉,在生产环境的数据库上进行维护,vm无缘无故的消失。而这些单点的故障会造成系统部分功能的问题,进而导致系统层层出现问题,最终造成整个系统不可用。

    在构建应用时,一般传统做法是我们先预想我们的应用可能在那个地方出现问题,然后在问题可能出现的点进行预防措施,比如创建一些拦截的手段来使当前处理得以执行,避免直接失败。这种处理方式是以问题为导向的处理方式,因为我们在一个复杂系统中无法准确的预知哪里会出现问题。但是问题总会出现,所以我们需要让应用能够优雅的处理失败而不是防止它发生,我们应该能够优雅的处理失败,而不是看着它不断向上抛出,最终导致整个系统崩溃。

    构建一个分布式系统远比构建一个共享内存、单进程的单体应用要来的复杂,一个重要的难点在于沟通方式从共享内存变为了网络调用,而网络调用不总是那么可靠。网络调用失败的原因有很多种(例如:网络信号的长度、缆线、路由器或者交换机的损坏,以及防火墙等),而且网络调用容易成为一个主要的瓶颈。网络调用除了不可靠以外,还有可能造成对于性能产生潜在的影响,下游的响应时间对你的服务会产生影响,同时也会导致上游系统出现问题。

    网络调用一般意义上很难调试,理想情况下,如果你的网络调用不能完全成功,那么它们应该立即失败,这样应用程序就能立即捕获到这个问题(例如:IOException),当捕获到这个问题,我们就可以立刻采取行动,提供降级的行为或者返回一个消息让用户稍后再试。但是网络错误在分布式环境下远远没有这么简单,试想如果下游的应用处理请求的时间比平时常很多怎么办种致命的场景将会成为拖慢你的应用的瓶颈,下游的网络调用超时,将会使你的服务被慢慢拖住,最终导致服务的不可用,而由于你的服务挂在那里,从而导致你的上游也变慢,最终级联的问题导致整个分布式系统出现问题。

依赖设计(design with dependencies)

    从一个组织或者站在一个分布式系统的角度,为了能够快速响应、敏捷,我们需要在设计系统时考虑依赖这个影响因素。在内部团队的组织中、技术选择上以及团队治理上,我们需要松耦合。使用微服务架构的一个目标是利用团队自治、服务自治的优点,这意味着能够在不影响到整个系统的前提下,使我们能够快速的响应用户需求。这也意味着我们依赖的服务,当它们不可用或者降级时,我们能够优雅的处理这些问题。

    在《Dependency Oriented Thinking》这本书中,作者 Ganesh Prasad 对于依赖这个话题,说“创新的一个原则就是丢弃约束,换句话讲,你可以认为解决一个以往的问题而减少了一个或者多个依赖”。而问题就是我们能够在脑海中快速的构建组织结构,但是它会在系统设计上带来很多的零散依赖。

    例如:当我们需要变更服务时,首先需要咨询其他的几个团队(DBA,测试和安全),这样会显得非常麻烦,和任何一个团队的沟通都是同步的,任何沟通的延迟,都会造成项目的延迟。如果能够将这些依赖的团队整合到你的团队中,你就能够减少这些零碎的步骤,可以更快的解决用户的需求,避免在人上面耗费资源。

    另一个依赖管理的故事是针对遗留系统。将遗留系统的细节暴露给下游系统是一场灾难,这样做一个小的变动(比如客户ID长度从16变为20)就会使下游系统收到影响。我们需要仔细考虑如何同其他系统之间保持隔离。

领域设计(design with the Domain)

    几个世纪以来,我们一直使用建模这个工具来简化和理解问题,例如:手机上使用的GPS地图软件就是进行城市中导航的绝佳模型,但是这个模型却在从一个城市飞往另一个城市的飞行旅行中显得力不从心,此刻最好的模型是给出合适的方位、地标和航线信息。从这个例子中可以看出,模型的定义离不开它的语境,不能偏离它处理的问题域,更深入的说没有模型是万能的,模型只有在上下文语境中才有意义。Eric Evans 具有开创新的著作 《Domain-Driven Design》 (Addison-Wesley, 2004) 指导我们如何为复杂的业务过程构造模型,并将其转换为软件系统。最终软件中最复杂的部分不是技术本身,而是运行时操作那些那些有歧义、循环或相互矛盾的业务模型。人类能够通过给定一个上下文语境来理解模型,但是计算机需要更多的提示和帮助,这些模型和上下文语境必须都打包入软件,如果我们能这样建模,那么业务逻辑在任何时候做出修改,我们就能快速的在软件实现中定位它们。在软件实现中定位了这些变动,通过修改模型等方式响应了需求的变化,而这个迭代的过程需要尽可能的快速。

其实这就是应用划分的一个策略,比如做交易的订单中心,商品中心,这些都是模型和上下文的复合体

    在 Evans 的书中,对于领域建模的一个工具就是识别和明确的区分不同的模型,并将它们各自聚合在具备边界的上下文中。

chapter1-6.png

    在分布式系统的场景下,承诺(Promise)将更能清楚的表达一个服务能提供什么,能更清楚的假设能做到什么,不能做到什么。例如:我们团队维护了图书推荐服务,我们承诺为每个用户提供不同的图书推荐。当业务方请求我们的接口时,如果我们的后端依赖的产品挂了该如何是好(存储用户图书推荐关系的数据库)们可以抛出一个异常给业务方,但是体验不太好,因为可能会让调用方的系统出现问题。因为我们做出了承诺,我们就竭尽全力的维护这个承诺,包括返回一个默认的图书列表。有时确实无法维护承诺,那么最好的方式是返回用户期望的结果。这里的关键在于我们的服务,尽量维护其承诺(返回一些图书推荐),即使我们的依赖服务不能维护其承诺(数据库已经挂了)。在维护承诺的过程中,这也有助于让系统的其余部分正常工作,并维护其他服务的承诺。

    对于承诺(Promise)的另一个视角是换位思考(比如交换服务提供者和消费者),但是我们如何决定这两边的价值,以及如何做出承诺呢果没有消费方调用我们的服务,获取我们的数据,那么提供的服务是否还有价值呢一种方式用来描述消费者和服务提供者之间的承诺,就是使用consumer-driven contracts。使用这个方式,我们能够捕获到我们承诺的价值,使用它能够测试我们是否能维护我们的承诺。

洋人说了这么多,其实价值不大,简单说就是服务设计要取中庸之道,即不能让消费者麻烦,也不要坑了自己的未来

分布式系统管理

    当下,管理一个单一系统(一台机器)要比管理一个分布式系统显得容易许多。如果只是一台机器,一个应用服务器,如果出现问题,我们立刻就知道该做什么。如果你需要做一个配置变更,或者升级软件,这些内容就一定在一个物理或者逻辑位置,改动它就好了,管理、调试和变更都显得很容易。一个单一系统在某些场景下非常常见,但是如果堆伸缩性有要求,那就显得力不从心了,这时微服务架构就登场了。就像我们之前讨论的,微服务并没有那么便宜,它是一次价值交换,我们使用系统管理的复杂性来换取柔性和伸缩性。

    下面是一些关于微服务部署和管理的常见问题:

  • 如何启动和停止一批服务/li>
  • 如何能够跨服务的手机日志、指标和SLA/li>
  • 如何在一个具备弹性的环境中发现服务/li>
  • 如何做负载均衡/li>
  • 如何察觉整个集群和某个服务的健康度/li>
  • 如何重启一个具备故障迁移的服务/li>
  • 如何做细粒度的服务路由/li>
  • 如何应对服务的安全性/li>
  • 如何在集群的部分机器出现崩溃或者行为异常时减少对他们的请求或者进行隔离/li>
  • 如何部署服务的不同版本,然后通过路由解决/li>
  • 如何在大量服务中完成配置变更/li>
  • 如何能够安全且可复制的修改应用代码或者配置/li>

    这些都不是简单的问题,本书接下来的部分致力于Java开发者如何使用微服务并解决上述的部分问题,而全部的解决方案将会在本书的第二版中涉及。

技术解决方案

    本书借来来的部分将会介绍一些流行的技术组件,用它们来帮助我们解决微服务架构下开发和交付场景下遇到的问题。微服务的采用并不是一个技术问题,而需要正确的组织架构和团队组建方式,这些是首要的问题,将SOAP切换到REST并不是微服务架构的实践。

    对于Java开发第一步,先在本地创建微服务,本书介绍了三款出名的Java微服务框架:Spring Boot、Dropwizard和WildFly Swarm。其中每个框架都有各自的维护方,属于不同的组织,也有不同的方式来开发微服务。因为是大部分团队使用,所以选择的框架都是通用性或较为常用的,但这并不代表着只有这些框架。有一些基于响应式的微服务框架,例如:Vert.x和Lagom,使用基于事件模型方式进行编程,与普通的开发模型有些不同,同时也有更陡峭的学习曲线,本书还是使用大多数企业Java开发人员习惯的开发框架。

    本书的目标是让读者能够使用上述框架的最基本特性,我们将在最后一节深入一些高级概念,但是在这些框架的最初使用阶段,我们会创建一些hello-world级别的简单应用。本书不是一个针对微服务面面俱到的参考书,在每章结束的地方会给出一些继续深入学习的参考链接,我们会在hello-world级别的应用上不断的迭代增加一些特性,让读者对一些模式有更加深化的认识。

    在这些框架的最后迭代过程中,将会演示如何实现承诺(Promise)等技术,使我们的服务能够面对失败的场景。我们将深入部分 NetflixOSS 的产品,例如:Hystrix ,它让我们更容易的实现这些内容,而我们将会从服务端和客户端不同途径来探索有何种更好的方式。

    当完成了所有的示例,我们也会探讨Linux容器为微服务的部署、管理以及隔离带来的价值。Docker和Kubernetes为可伸缩的分布式系统带来了卓有成效的简化,我们将围绕容器和微服务的最佳实践展开讨论。

    在本书的最后部分,我们遗留了一些你会更深入学习的话题,比如:分布式配置、日志、指标和持续交付。

准备你的环境

    我们将使用Java 1.8 来构建所有的示例,确保你的环境比以下罗列的内容更新:

  • JDK 1.8
  • Maven 3.2+
  • 命令行控制(bash, cmd, Cyg-win, etc)

    Spring生态中有很多出色的工具,可以选择命令行或者IDE集成的方式使用它们。以Spring Boot为例,我们使用Spring CLI v1.5.4.RELEASE。

    在IDE中可以替代的工具有:

  • Eclipse based IDE: Spring Tool Suite
  • Spring Initializr web interface

    而对于Dropwizard和WildFly Swarm,我们使用Jboss Forge CLI通过插件的方式,以交互式的方式来创建工程:

  • JBoss Forge 3.0+

在Mac下,可以通过安装JBoss Forge

    在IDE中可以替代的工具有:

  • Eclipse based IDE: JBoss Developer Studio
  • Netbeans
  • IntelliJ IDEA

    最后,当我们将微服务以Docker容器的方式部署在Kubernetes中时,我们需要在对应的环境下安装以下工具:

  • Vagrant 1.8.1
  • VirtualBox 5.0.x
  • Container Development Kit 2.x
  • Kubernetes/Openshift CLI
  • Docker CLI (optional)

由于作者是redhat旗下的工程师,以redhat产品为主,所以这些环境的安装笔者出于通用性将其做了一些更改,以下内容以笔者的环境为准:

  • VirtualBox 5.1
  • DockerCE
  • Kubernetes & MiniKube

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91730 人正在系统学习中 相关资源:fouro-application:iOSAndroid应用程序,用于发送虚拟拥抱并与朋友…

来源:weixin_34115824

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年9月15日
下一篇 2017年9月15日

相关推荐