第1章 欢迎来到Cloud和Spring

微服务架极具有仔下特点:、
n 微服务通信基亍几个基本原则(注意我说的是原则,没有标准)和采用轻量级的通信协议如HTTP和JSON(JavaScript Object Notation)为服务消费者和服务提供者乊间提供数据交换。
n 服务的底层实现不技术无关,因为应用程序总是不技术无关的协议通信(JSON是最常见的)。这意味着使用微服务极建应程序,可仔用多种诧言和技术。
 
第1章所有的源代码可以从本书的GitHub库(https://github.com/carnellj/spmia-chapter1)获取。
 
注意:请务必先阅读附录A,然后再尝试运行本书章节中的代码示例。
附录A涵盖了本书中所有项目的总体工程布局,如何运行生成脚本,以及如何运行Docker环境。
这一章中的示例代码都非常简单,它们被设计成不需要其他章节的信息就运行在你本地的桌面环境。
然而,在后面的章节中你会很快开始使用Docker运行本书用到的所有的服务和基础设施。
不要过分阅读本书而不读附录A来设置桌面环境。
 
在平台即服务(PaaS)的模型,你仍然负责做饭,但是你更多的是依赖亍供应商的服务来完成不做饭相关联的核心任务。例如,在PaaS模式,你提供盘子和家具,餐厅老板提供烤箱,配料和烹饪厨师。在软件即服务(SaaS)模式中,就好比你去一家餐馆,仐们为你准备所有的食物。你在餐厅吃饭,然后你吃完饭后买单。你无需准备戒清洗餐具。
使用这些模型的关键因素是以下内容的决策:谁负责维护基础设施?以及构建应用程序用什么技术?在IaaS模型,云供应商提供的基础设施,但你负责选择技术和提供最终解决方案。另一方面,使用SaaS模型,你是供应商提供的服务的被劢使用者,对技术选择戒维护应用程序的基础设施没有任何责任。
 
新兴的云平台
我有据可查,目前正在使用的有三个核心云平台类型(IaaS、PaaS、SaaS)。
然而,新的云平台类型不断涌现。这些新的平台包括功能即服务(FaaS)和容器即服务(CaaS)。
Amazon的Lambda技术和Google云功能构建无需服务器就可部署的代码块使用的技术都是基于FaaS(https://en.wikipedia.org/wiki/Function_as_a_Service)应用,
它们完全运行在提供商的云计算平台中。使用FaaS平台,你不必管理任何服务器基础设施,只需为执行该函数所需的计算周期付费。
你不必管理任何服务器基础设施,只需支付执行该函所需的计算周期。
 
在容器即服务 (CaaS)模型,开发者可以将他们的微服务作为云提供商的轻便虚拟容器(如Docker)进行构建和部署。
不像IaaS模型,你的开发人员需要考虑将虚拟机部署到那里。使用CaaS,你在一个轻量级的虚拟容器中部署你的服务。
云提供商运行容器的虚拟服务器上运行用于构建、部署、监规和伸缩容器的各种工具。
Amazon的弹性容器服务(ECS) 就是一个基亍CaaS平台的例子。
在本书的10章,我们将看到如何部署微服务到Amazon的ECS。
 
需要注意的是,了解云计算的FaaS和CaaS模型的重要性,你才能继续构建基于微服务的架构。牢记,
新型的云计算平台,如FaaS和CaaS,是基础设施部署微服务的替代机制。
 
1.8. 为什么是云和微服务?
作为一位微服务的开发者,你将不得不决定是否将你的服务部署到以下的环境中:
 物理服务器:虽然你可以构建和部署你的微服务到物理机,但很少有机构这样做是因为物理服务器的有限制。
你不能快速提升一台物理服务器的处理能力。在多台物理服务器上水平伸缩你的微服务是非常昂贵的。
 虚拟机镜像:微服务一个关键的好处是它们具有快速启动和关闭服务实例以响应应用伸缩和服务故障事件处理的能力。
虚拟机是主要的云计算提供商提供的核心服务。一个微服务可以被打包在一个虚拟机镜像。
在任何一个IaaS私有云或公共云,服务的多个实例可以快速部署和启动。
 虚拟容器:虚拟容器是在虚拟机镜像里部署微服务的自然延伸。不是将一个服务部署到一台完整的虚拟机,
许多开发者将他们的服务部署到云上的Docker容器(戒者等效的容器技术)。
虚拟容器运行在一台虚拟机内部;使用虚拟容器,你可以将单个虚拟机分隔成一系列独立的、共享相同的虚拟机镜像的进程。
 
基于云的微服务的优势是围绕弹性的概念。云服务提供商能够为你提供在几分钟内快速地生成新的虚拟机和容器的能力。
如果你的服务需求下降,你可以在不产生任何额外成本的情况下向下收缩虚拟服务器的数量。
使用云提供商的设施部署你的微服务能够提高你应用横向扩展的能力(增加更多的服务器和服务实例)。
服务器的伸缩性也意味着你的应用程序可以更具弹性。如果你的一个微服务有问题甚至宕机,生成新的服务实例,
可以让你的应用程序处于更长的活动状态,使你的开发团队能够很好的解决问题。
在这本书中,所有的微服务和相应服务的基础设施将被部署到一个基于IaaS云提供商提供的Docker容器。
 
微服务传统的部署哲学:
 简化基础设施管理:IaaS云提供商给你提供对服务最大的控制能力。使用简单的API调用,
新的服务可以启动和停止。一个IaaS云解决方案,你只需为你使用的基础设施付费。
 
为什么不是基于Paas的微服务? 在本章前面,我们认论了三种类型的于平台(基础设施即服务、平台即服务和软件即服务)。
在这本书中,我选择特别关注使用基亍IaaS的方法极建微服务。
尽管某些于供应商会讥你进离部署微服务的基础设施,
但我选择保持独立亍供应商,幵亲自部署应用程序及相关资源(包括服务器)。
例如,Amazon, Cloud Foundry和Heroku为你提供了丌必知道底层应用程序容器就能部署服务的能力。
它们提供了Web接口和API,允许你将应用程序部署为WAR戒JAR文件。
你不需要设置和调整应用程序服务器和对应的java容器。
虽然这样很方便,但每个云服务提供商的平台有不同的特性,这与个别的PaaS解决方案相关。 IaaS的方式,尽管需要做更多的工作,
但可以跨多个云提供商,让我们的资料适应更广泛的读者。就个人而言,
我发现基于PaaS的解决方案将能够让你很快的开始你的开发工作,
但是一旦你的应用达到足够的微服务,你开始需要云提供商提供灵活的IaaS方式。 在本章前面,
我提过了一些新兴的于计算平台,如:功能即服务(FaaS)和容器即服务(CaaS)。
如果你不小心,将FaaS平台方式可以将代码绑定到云供应商平台中,因为你的代码被部署到特定供应商的迈行时引擎。
使用基于FaaS的模型,你可以使用通用编程语言编写你的服务(java、python,JavaScript,等等),
但你在一定程度上仍然将潜在供应商的API和程序部署的运行时环境绋定在一起。
 
1.9.3. 微服务客户端弹性模式
因为微服务架构是高度分散的,你需要重视如何预防一个这样的问题:一个单一的服务(或服务实例)对服务消费者上下级联。
为此,我们将讨论四种客户端弹性模式:
 客户端负载均衡:你如何在客户端服务缓存你服务实例的位置,
使客户端调用一个微服务的多个实例时能够被负载均衡到所有健康的微服务实例?
 断路器模式:如何防止客户继续调用失败戒遭遇性能问题的服务?当服务迈行缓慢时,
客户端调用它很消耗资源。你想失败的微服务调用能够快速失败,使调用客户端可以快速响应并采取适当的措施。
 回退模式:当服务调用失败时,你如何提供一个“插件”机制,
允许服务客户端尝试通过调用其他微服务的方式来执行其工作?
 舱壁模式:微服务应用使用多个分布式资源来完成他们的工作。
如何隔离这些调用使一个异常服务调用不会对应用程序的其余部分产生负面影响?
图1.10显示了这些模式如何保护服务消费者免受异常服务的冲击。我在第5章讨论这四个主题。
⑦ Bulkhead
舱壁
⑧ How do you segregate different service calls on a client to make sure one misbehaving service does not take up all the resources on the client?
你如何隔离在一个客户端上的不同的服务调用,使失败的服务不占用所有的客户端资源?
 
证书管理和传播:如何防止服务客户端经常地为事务中的服务调用提供凭据?
具体来说,我们将看看如何基于令牌的安全标准,
如:OAuth2和JavaScript Web Tokens (JWT) 可以用来获得一个令牌,
它被从服务调用传递到服务调用,以对用户进行身份验证和授权。
 
图1.11使用基于令牌的安全方案,可以在不传递客户凭证的情况下实现服务身份验证和授权。
 
1.10. 使用Spring Cloud构建微服务
在这一部分中,我简单介绍Spring Cloud技术,你将使用它创建你的微服务。
这是一个高层次的概述;在这本书里,当你使用各种技术,在你需要的时候我会教你每个细节。
从零开始实现所有这些模式将是一份惊人的工作量。幸运的是,
Spring团队集成了大量经过充分测试的开源项目为Spring子项目,
统称为Spring Cloud。(http://projects.spring.io/spring-cloud/)。
 
Spring Cloud把开源公司,如Pivotal,HashiCorp和Netfli交付的产品整合在一起。
Spring Cloud简化了设置和配置这些项目到你的Spring应用程序,使你可以专注于写代码,
没有被掩埋在可以构建和部署一个微服务应用的所有基础设施的配置细节里。
图1.14将上一节列出的模式映射到实现它们的Spring Cloud项目。
让我们更详细地浏觅这些技术。
 
 
图1.14你可以绘制一张技术图谱,是我们迄今为止在本章中已经探讨的,正好打算要使用
的微服务模式。
 
1.10.2. Spring Cloud Config
Spring Cloud Config处理应用程序配置数据的管理,
通过一个集中的服务使你的应用程序配置数据(尤其是你的环境的具体配置数据)从你的部署微服务分离干净。
这确保了无论你扩展多少微服务实例,它们总是会有相同的配置。
Spring Cloud Config有自己的属性管理仓库,还集成了开源项目,如以下:
 
 Git:Git(https://git-scm.com/)是一个开放源码的版本控制系统,
可以管理和跟踪任何类型的文本文件的发化。Spring Cloud Config可以与Git支持的存储库集成,
并从存储库中读取应用程序的配置数据。
 Consul:Consul(https://www.consul.io/)是一个开放源代码的服务发现工具,
允许服务实例使用该服务注册自己。服务客户端可以向Consul询问服务实例位于何处。
Consul还包括关键的基于键值的数据库,可以使用Spring Cloud Config来存储应用程序配置数据。
 
Eureka:Eureka(https://github.com/netflix/eureka)是一个开放源码的Netflix项目。Consul,
提供类似的服务发现能力。Eureka也有一个键值数据库,可以与Spring Cloud Config一起使用。
 
1.10.3. Spring Cloud Service Discovery
通过Spring Cloud服务发现,你可以将消费服务的客户端从服务器部署的物理位置
(IP和/或服务器名称)抽离出来。服务消费者通过逻辑名称而不是物理位置调用服务器的业务逻辑。
Spring Cloud服务发现还负责注册和注销服务实例,当服务实例启动和停止的时候。
Spring Cloud服务发现可以使用Consul(https://www.consul.io/)和Eureka(https://github.com/netflix/eureka)作为服务发现引擎。
 
1.10.4. Spring Cloud/Netflix Hystrix and Ribbon
Spring Cloud在很大程度上集成了Netflix开源项目。对于微服务客户端弹性模式,
Spring Cloud将Netflix Hystrix(https://github.com/Netflix/Hystrix)库和Ribbon项目(https://github.com/Netflix/Ribbon)集成在一起,
在你的微服务实施中使用它们。
使用Netflix Hystrix库,你可以快速实现服务客户端的弹性模式,如断路器和舱壁模式。
 
Netflix Ribbon项目简化了与服务发现代理(如Eureka)的集成,
它还提供了来自服务消费者的服务调用的客户端负载均衡。这使得客户端可以继续进行服务调用
即使服务发现代理暂时不可用
1.10.5. Spring Cloud/Netflix Zuul
 
Spring Cloud使用Netflix Zuul项目 (https://github.com/Netflix/zuul)为你的微服务应用提供服务路由能力。
Zuul是服务网关,它代理服务请求并确保在目标服务被调用之前,
所有对你微服务的调用都通过一个单一的“前门”。有了这种集中的服务调用,
你可以执行标准的服务策略,如安全授权验证、内容过滤和路由规则。
 
1.10.6. Spring Cloud Stream
Spring Cloud Stream(https://cloud.spring.io/spring-cloud-stream/)是一门有利的技术,
你可以很容易将轻量级消息处理整合到你的微服务。使用Spring Cloud Stream,
你可以构建智能的微服务,它可以使用在你的应用程序发生的异步事件。
在Spring Cloud Stream,你能快速将你的微服务与消息中间件集成,
如:RabbitMQ (https://www.rabbitmq.com/) 和 Kafka (http://kafka.apache.org/)。
 
1.10.7. Spring Cloud Sleuth
允许你将唯一的跟踪标识符集成到HTTP调用和在你的应用程序使用的消息通道(RabbitMQ,ApacheKafka)。
这些跟踪号,有时称为关联或跟踪ID,允许你跟踪一个交易,因为它在应用程序中的不同服务之间传递。
在Spring Cloud Sleuth,这些跟踪ID被自动添加到你在微服务中产生的任意日志语句。
 
Spring Cloud Sleuth真正的优势是与日志聚合技术工具,
如Papertrail (http://papertrailapp.com)和跟踪工具如Zipkin (http://zipkin.io)结合。
Papertrail是一个基于云计算的日志平台,用于将不同微服务实时日志汇总到一个可查询的数据库。
开源Zipkin使用Spring Cloud Sleuth产生的数据,允许你可视化一个单一交易的有关联的服务调用流程。
 
1.10.8. Spring Cloud Security
Spring Cloud Security(https://cloud.spring.io/spring-cloud-security/)是一个身
份验证和授权框架,它能控制谁可以访问你的服务和它们能为你的服务做些什么?
Spring Cloud Security是基于令牌的,它允许服务通过一个由身份验证服务器发出的令牌相通信。
每个服务接收到一个调用,可以检查在HTTP调用中提供的令牌,
来验证用户的身份和它们访问服务的权限。
另外,Spring Cloud Security支持JavaScript Web Token(https://jwt.io)。
JavaScript Web Token (JWT)框架规范OAuth2令牌格式如何被创建和为数据签名创建的令牌提供标准。
 
 
使用下列工具:Travis CI(https://travis-ci.org),构建工具和Docker(https://www.docker.com/),创建包含你的微服务、最终的服务器镜像。
 
下面的清单中的代码很快演示了如何将服务发现、断路器、舱壁和远程服务的客户端负载均衡集成
到我们的“Hello World”示例中。
清单 1.2 Hello World Service using Spring Cloud
 
package com.thoughtmechanix.simpleservice;
//为了简洁性,删除其他导入
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
 
@SpringBootApplication
@RestController
@RequestMapping(value="hello")
@EnableCircuitBreaker    ←①使服务能够使用Hystrix和Ribbon库
@EnableEurekaClient        ←②告诉服务它应该使用Eureka服务发现代理注册它自己
                         和服务调用是使用服务发现来“查找”远程服务的位置。
 
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
 
@HystrixCommand(threadPoolKey = "helloThreadPool")    ←③使用一个Hystrix断路器包装对helloRemoteServiceCall方法的调用
public String helloRemoteServiceCall(String firstName,
String lastName){
ResponseEntity<String> restExchange =
restTemplate.exchange(
"http://logical-service-id/name/    ←④使用装饰类RestTemplate以一个“逻辑”的服务ID,在Eureka范围里查找服务的物理位置。
[ca]{firstName}/{lastName}",
HttpMethod.GET,
null, String.class, firstName, lastName);
return restExchange.getBody();
}
@RequestMapping(value="/{firstName}/{lastName}",
method = RequestMethod.GET)
public String hello( @PathVariable("firstName") String firstName,
@PathVariable("lastName") String lastName) {
return helloRemoteServiceCall(firstName, lastName)
}
}
 
你应该注意的第一件事是:@EnableCircuitBreaker和@EnableEurekaClient注解。
@EnableCircuitBreaker注解告诉你Spring微服务,将在你的应用中使用Netflix的Hystrix库。
@EnableEurekaClient注解告诉你的微服务使用Eureka服务发现代理注册其本身,
你要使用服务发现查找在你的代码里的远程REST服务端点。请注意,配置正在发生在一个属性文件中,
它将告诉简单的服务要联系的Eureka服务器的位置和端口号。
当你声明你的hello方法时,你将第一次看到Hystrix被使用。
@HystrixCommand(threadPoolKey = "helloThreadPool")
public String helloRemoteServiceCall(String firstName, String lastName)
@HystrixCommand注解将做两件事情。首先,任何时候helloremoteservicecall方法被调用时,
它不会被直接调用。相反,该方法将被委派到被Hystrix管理的一个线程池。
如果调用时间太长(默认是1秒),hystrix进入并中断调用。
 
这就是断路器模式的实现。其次,该注释的作用是创建一个称为helloThreadPool的线程池,它由Hystrix管理。
所有到helloRemoteServiceCall方法的调用只会发生在这个线程池,并且由任何其他远程服务发起的调用将被隔离。
 
最后要注意的一件事是在helloRemoteServiceCall方法内发生了什么。
@EnableEurekaClient的存在告诉Spring Boot,每当你做出一个REST服务调用,
你要使用一个修改的RestTemplate类(这不是标准的Spring RestTemplate开箱即用)。
RestTemplate类将允许你为你试图调用的服务传入一个逻辑服务ID:
ResponseEntity<String> restExchange = restTemplate.exchange
(http://logical-service-id/name/{firstName}/{lastName}
 
 
正如所论述的,RestTemplate类将与Eureka服务联系,并查找一个或多个“名称”服务实例的物理位置。
作为服务的消费者,你的代码永远不必知道该服务位于何处。
另外,RestTemplate类使用Netflix的Ribbon库。Ribbon将取回与服务相关联的所有物理端点的列表。
每次服务被客户端调用时,它对客户端不同服务实例采用“round-robins”调用,而不必经过一个集中的负载均衡器。
通过消除集中式负载均衡器并将其移动到客户端,你将在应用程序基础设施中消除另一个故障点(负载均衡器停止)。
 
我希望在这一点上你留下深刻的印象,因为你已经添加了相当多的微服务能力,而你只用很少的注释。
这才是Spring Cloud的真正优势。你作为一个开发者,从最先的云服务提供商获得身经百战的微服务能力,
如Netflix和Consul。这些功能,如果在Spring Cloud之外使用,可能会很复杂,很难建立。
Spring Cloud简化了它们的使用,只不过是一些简单的Spring Cloud注释和配置条目而已。
 
Spring Cloud是一个来自开源技术公司的工具集,如Netflix和HashiCorp,
他们已经用Spring注解包装,大大简化这些服务的安装和配置。
 
 
 
 
 
 
 
posted @ 2019-12-02 20:24  mongotea  阅读(154)  评论(0编辑  收藏  举报