前言一、微服务开发基础
1、微服务架构开发
1.1单体架构的应用的困境1.2 微服务架构
1.2.1 理解微服务架构1.2.1 微服务的优缺点 1.3 微服务架构设计
1.3.1 微服务粒度——粗粒度划分较好1.3.2 微服务拆分原则——从面向对象理论中借鉴1.3.3 微服务自治原则——由一个服务提供数据操作1.3.4 微服务交互原则——协议交互1.3.5 微服务架构迁移——单体架构应用迁移到微服务架构 1.4 不使用微服务架构的情形 2、微服务基础-SpringBoot
2.1 Spring与SpringBoot2.2 快速启动SpringBoot2.3 使用Spring Boot构建示例项目
2.3.1 经典三层应用架构2.3.2 设计领域对象2.3.3 实现数据管理2.3.4 编写业务逻辑层2.3.5 编写RESTful API2.3.6 数据库初始化2.3.7 启动测试 2.4 Spring Boot特性
2.4.1 Spring Boot自动配置机制2.4.2 Spring Boot扩展属性配置2.4.3 Spring Boot日志配置 2.5 关于敏捷开发2.6 关于RESTful设计 二、SpringCloud组件实战
3、SpringCloud简介
3.1 微服务架构的核心关键点---各个环节组件介绍3.2 SpringCloud技术概览
3.2.1 SpringCloud子项目3.2.2 为何选择Spring Cloud 3.3 SpringCloud版Hello World 4、服务治理与负载均衡
4.1 什么是服务治理4.2 构建服务治理--eureka
4.2.1 搭建微服务Parent工程4.2.2 搭建服务治理服务器——Eureka服务器4.2.3 搭建服务提供者——注册服务4.2.4 搭建服务消费者——获取服务4.2.5 服务调用(自己加上的一个) 4.3 使用客户端负载均衡——Ribbon
4.3.1 什么是客户端负载均衡4.3.2 启用Ribbon4.3.3 负载均衡测试 4.4 使用epenFeign简化微服务调用(原文是使用feign)4.5 深入Eureka
4.5.1 服务注册及相关原理4.5.2 Eureka自我保护模式4.5.3 注册一个服务实例需要的时间4.5.4 Eureka高可用集群及示例4.5.5 多网卡及IP指定4.5.6 Eureka服务访问安全 5、微服务容错保护——Hystrix6、API服务网关——Zuul7、统一配置中心——Config8、分布式服务跟踪——sleuth9、消息驱动——Stream10、微服务应用安全——Security 三、微服务与docker
11、微服务与Docker
前言本篇内容参考自《SpringCloud微服务架构开发实战》-董超、胡炽维,书中源码
一、微服务开发基础 1、微服务架构开发 1.1单体架构的应用的困境
①后期功能扩展不易:在传统的单体架构项目中,所有的东西都集中在一个项目,开发,部署,运维会随着业务的扩张而变得非常的麻烦,牵一发而动全身
②团队协作开发保持一致:而且对于一个团队开发来说,如果修改了数据库,那么其他所有人都应该知晓,而且技术栈也要一致,对于一个项目来说,很难使用和切换不同的框架,语言,新的开发者往往需要了解到整个项目的架构才能加入开发,并且多人使用git开发修改统一文件还会导致文件冲突,解决冲突也是一件很麻烦的事情
③项目部署难以水平扩展:因为每一个应用实例对服务器来说都需要相同的硬件配置,这让服务器无法充分发挥其能力,造成浪费,并且部署的服务速度会随着代码积累逐渐变慢,性能降低。
①核心原理:分而治之,就是将我们的应用分解成多个功能独立的模块/服务,服务之间的交互通过某种协议(REST,RPC-dubbo)进而完成一系列复杂的业务功能,每个服务都是一个能够独立提供范围有限的一个小型的完整功能,所以是能够单独部署在服务器上的,而且还能够水平复制,通过负载均衡算法确定调用的微服务,对外隐藏了具体的业务逻辑代码的细节,只提供外部访问的接口,
②可扩展模型:AFK可扩展立方体
X轴:服务可部署到多个服务器,然后再做一个集群负载均衡即可
Y轴:可运行多个实例,每个实例用来处理部分数据,在之前没有负载均衡, 而是一个路由,将请求转发到不同的实例中
Y轴:应用分解,高可扩展/font>
优点:
①松耦合:应用拆解成多个服务,提供接口调用②抽象:调用特定的服务才能修改数据③独立:服务之前相互独立,独立部署④高可用
缺点:
感觉和优点有点悖论
①可用性降低:当一个服务崩溃之后,可能会产生级联反应,造成应用雪崩
②处理分布式事务:当用户操作涉及到多个服务时,如何保证数据的一致性,
③学习难度大:学习一系列的组件才能搭建应用系统
④全能对象:服务拆分时,可能遇到多个服务使用同一对象
⑤组织架构变更:涉及服务编排和服务治理等一系列处理
设计可分为三个步骤:
①根据应用的需求定义
②识别应用中所包含的所有服务
③将关键需求用来描述服务之间如何协作
识别服务:通过业务逻辑识别核心微服务,然后将核心服务相关的服务都定义出来,不可以一开始从技术的角度去拆分
服务的协作:根据业务分析,有的场景可能只需要某个服务,或者两个甚至多个服务才可以实现,有些协作是需要同步的,甚至是异步的,此外还需要考虑用户最初发起请求是由哪个服务承担
如果我们将每一个部分都当做一个服务,那么粒度就太细了,每个服务都只实现了数据处理,而业务的处理需要粘合过多的代码才能够让这些微服务整合来完成一个具体的业务处理,
最好的方式是先专注于各个服务之间的交互,先分成粗颗粒度的服务,随着系统的升级和功能的提升再去细化这些服务
从面向对象的开发理论中进行借鉴:
①单一职责原则(SRP):一个类应该有且只有一个变化的原因
一个类承担多个职责后,往往这些职责就会耦合在一起,某一职责的改变可能会影响到其他的职责。这样的类设计是非常脆弱的,从而会导致应用的稳定性。因此,我们在进行类设计时要遵守单一职责原则
②共同封闭原则(CCP):包中的所有的类对于同一种性质的变化应该是共同封闭的。一个变化若对一个封闭的包产生影响,则将对该包中的所有类产生影响,而对其他包则不造成任何影响
开闭原则(OCP)中的关闭概念,说当需要修改某项业务时,我们需要将修改的范围限制在同一个包内,而不是遍布在很多包中
1.3.3 微服务自治原则——由一个服务提供数据操作
需要更改某一业务数据库表时往往会涉及多个模块,甚至有时候根本不清楚修改这张数据库表到底会影响到多少业务代码,从而不敢动数据库表的定义,只好退而求其次,通过增加表来处理,进而加剧了系统架构的恶化。
将业务数据管理进行私有化之后就进一步降低了业务之间的耦合度
微服务数据自治是指将对数据的操作封装到一个服务中,其他服务只能通过这个服务调用实现功能,而不能直接操作数据库
1.3.4 微服务交互原则——协议交互
①使用REST协议:REST可以说在微服务互相调用之间起着非常重要的角色,强烈建议大家使用HTTP作为服务的调用协议,并在服务处理上使用HTTP标准动词(GET、PUT、POST和DELETE)。
②使用URI表达:服务端点的URI应该能够清晰表达出我们所要解决的问题、提供的方法、相应资源信息及资源之间的关联关系。
③使用JSON数据格式:JSON作为轻量级数据格式协议,及自带的序列化和反序列化机制,几乎已经成为通信中的数据标准协议,并且对于前端开发来说非常容易使用与整合。
④使用HTTP标准状态码:HTTP协议本身具有非常丰富的状态码,那么使用这些状态码来作为服务调用结果的状态是非常合适的。
使用Martin Fowler提出绞杀(Strangler)模式。该策略名字来源于雨林中的绞杀藤,绞杀藤为了能够爬到森林顶端都要缠绕着某棵大树生长,最终使被缠绕的大树死掉,只留下树形一样的绞杀藤。通过这种策略,我们在迁移时应首先围绕着传统应用开发出新的微服务应用,并逐渐替代传统应用中的部分业务功能。通过这种方式逐步构建微服务应用,并替代、兼容整合旧的传统应用,直到微服务承担全部应用功能
1.4 不使用微服务架构的情形①构建分布式架构非常吃力时;
②服务器蔓延时;
③采用小型应用、快速产品原型时;
④对数据事务的一致性有一定要求时。
浅谈:
①Spring核心和IOC(控制反转)和AOP(面向切面编程),属性Spring家族核心产品,
②在原始SSM项目中我们可能要写很多配置文件,每一种框架都需要写,而利用SpringBoot构建的项目采用的结构是starter启动器,每一个功能及时一个启动器,比如说整合mysql,连接redis或者是使用AOP,你只需要导入相应的依赖即可,每一个starter都会有一个配置类,所有的配置类属性通过application配置文件修改配置类默认值,极大的简化了开发,而且还有统一的日志管理,缓存,语言切换等其他功能,灰常方便
使用IDEA工具快速创建一个SpringBootDemo,再使用maven导入依赖,编写pom.xml文件
在创建的包下面的运行类启动即可
@SpringBootApplication注解告诉Spring容器:使用该类作为所有Bean源,通过该起始点构建应用的上下文,@SpringBootApplication注解继承自应该是注解套娃,该注解上的存在着两个注解@EnableAutoConfiguration和@ComponentScan,通过该注解使得项目在启动时Spring就会对该类所属目录下的所有子包进行扫描并根据Spring Boot的自动配置机制进行配置。
如果在应用启动时需要进行某些初始化处理,那么最好都在该类中完成。
针对系统:MVC:model、view、controller
针对后端:controller,service,dao
,最难也是最先需要解决的就是业务领域对象(Domain)。只有清晰地识别出这些业务领域对象,以及它们之间如何交互及关联关系之后,才能进行下一步的开发
使用commons-lang包的ToStringBuilder.reflectionToString(Object)可以快速返回实体类的toString方法,特别是实体类有几十个属性的时候,
2.3.3 实现数据管理①数据持久化:将数据存储到关系型数据库中,ORM(Object Relation Mapping)通过实体类和数据库中表的字段的映射操作数据,这只是一种想法和JDBC一样,具体的jar包才是实现,对ORM的实现有hiberate和mybatis,
②关于JPA和ORM
JPA的实现思想即是ORM。
JPA并不是一种框架,而是一类框架的总称,基于ORM思想实现的框架都称为JPA框架。
③spirngdatajpa
spring生态圈对jpa的整合,默认是使用hibernate框架实现的
处理一个业务的实际代码,将结果存储到数据库并且返回,
2.3.5 编写RESTful APIRestfult是一种编程艺术/风格/规范,你也可以不遵守,没得任何问题,就和驼峰命名法一样,但是这么多人写的代码,每个人的习惯都不一样,没有规范的话,看别人代码很头疼,而且有了规范还会提升开发效率,
Restful是指使用http请求的请求方式来判定对资源操作的增删改查,而不是通过方法名来确定,
swagger是一个用于测试api的工具类,而且还提供了测试的友好界面
2.3.6 数据库初始化数据库设置初始值便于测试
2.3.7 启动测试启动主启动类,访问swagger-ui.html主页或者postman均可测试接口
Enable
EnableAutoConfiguration,开启自动配置,找到starter的系统配置类,创建对象,
EnableConfigurationProperties指定属性配置类
condition设定条件决定是否启用这个配置
通过修改application系统配置文件,修改配置类的一些默认配置属性 ,
此外还有配置文件的优先级,profile文件,jar包外部配置文件配置,命令行启动配置,高优先级会覆盖低优先级,
还可以给自己写的配置类属性赋值,
application:ConfigurationProperties指定前缀
专注属性配置文件properties:还需要一个注解,忘记了,注解名有限制,具体也忘记了,好像是不能有大写字符和中文
也可以用通过Spirng的value("${配置文件中得变量名}")注解赋值
springboot依赖自定集成了spring-boot-starter-logging,使用slf4j作为统一的抽象接口,默认是logback日志实现,也可以自己替换
2.5 关于敏捷开发开发者每次的改进(添加、优化、修改Bug)都不能太大,如果需要增加/改动的较大,那么这个时候或许就不能严格遵守敏捷开发的原则,需要在进行代码重构的同时添加一些必要的改进
2.6 关于RESTful设计①以资源为中心进行URL设计;
/user/{id}
②正确使用HTTP方法及状态码;
get获取资源,post创建或者修改资源,put修改资源, delete删除资源
③查询及分页处理原则;
/userPage/?page=1&size=1&sort=username,desc
④其他指导原则
使用JSON作为同一个返回的数据格式,返回统一JSON数据信息,方便统一处理
2014年3月,Martin Fowler在其博客上发表了Microservices一文,对过去几年逐渐开始流行的微服务架构开发模式给出了正式的定义。同年,Netflix将自己多年实际开发所使用的微服务基础组件通过Netflix OSS(Open Source Software)进行开源,加速了微服务架构模式的推广和普及。随之,Pivotal在Netflix OSS的基础上进行了封装和集成,推出了SpringCloud。如今,随着微服务架构的普及,使微服务在技术生态上得到了不断的完善和更新,不论是容器、应用框架、发布管理及监控等都有了长足的进步。
3.1 微服务架构的核心关键点—各个环节组件介绍1)服务治理
消费者如何访问并调用服务提供者所提供的的服务,服务提供者如何能让消费者知道并且消费。服务可以部署在多台服务器上,而我不可能利用服务IP去访问服务,因为我们不知道那个服务是否可用或者是否存在,也就是如何暴露服务
解决:服务治理(consul,eureka)
服务提供者在上线时将所提供的服务信息注册到服务治理服务器中,服务下线时,将信息从服务治理服务器中注销
服务消费者根据服务名称从服务治理服务器中获取服务并且调用
2)负载均衡
传统应用会在用户请求的入口通过负载均衡设备(如F5)或通过Ngnix反向代理方式实现负载均衡,
但在微服务架构下,负载均衡不仅仅是用户请求入口,还包含了服务之间的调用。
解决:客户端负载均衡(软负载均衡)
消费者(也叫客户端)保存有一份从服务治理服务中获取的服务者列表,客户端通过负载均衡策略来决定每次服务调用时所使用的具体服务实例,从而实现负载均衡
3)微服务统一入口
如何对众多微服务的入口统一到一个入口进行管理
解决:API服务网关
为微服务提供了统一的入口, 并能附加一些路由规则,使得不同的微服务通过路由规则提供一致的访问入口
4)微服务的容错
各个微服务的调用都是通过网络来完成的,而用户的一个请求往往需要涉及多个服务,如何防止服务调用失败不影响其他服务和调用者以及引起雪崩呢?
解决:Hystrix(断路器,服务降级)
防止服务调用失败引起的连锁反应
5)微服务的统一配置
/font>如何对众多的微服务进行统一的配置
6)微服务的监控
单体应用很容易通过系统的日志文件进行监控,而微服务架构的项目被拆分成了N多个服务,一个请求会设计到多个服务的调用,而日志由自己的服务实例管理,如何将分散在多个日志之间的调用串联起来,形成一个完整的请求链
解决:日志聚合,日志可视化分析,调用链跟踪
7)服务的部署
几十上百个的微服务的上线,下线,需要耗费很大的人力,
解决:自动化部署
Docker工具快速部署,K8s来构建自动化部署编排
Spring Cloud并不是一个传统意义上的项目,而是众多子项目的一个大集成,在版本号中Spring Cloud也没有采用传统的方式,而是通过一个“发布列车”的概念来定义版本
核心功能包:
3.2.1 SpringCloud子项目①基于Netflix实现服务治理、客户端负载均衡和声明式调用;
②服务网关;
③微服务容错管理;
④整合消息中间件提供消息驱动式开发;
⑤基于Spring Security提供微服务安全、单点登录功能;
⑥分布式、版本化的统一配置管理;
⑦微服务调用链及追踪管理
1)服务治理
eureka原本是Netflix下的开源产品,但是springcloud对其进行了二次封装,成了SpringCloudNetflix,
eureka提供了服务注册,服务发现,以及UI界面,在集群部署中即使只剩一个节点存活,也可以正常治理服务
2)负载均衡
ribbon实现,默认与eureka进行了无缝整合,当消费者去调用服务时,ribbon就会根据负载均衡策略选择一个合适的服务提供者实例并进行访问
服务调用方式:
①RestTemplate对象调用
②feign(自动集成了ribbon)接口调用,声明式服务调用
3)服务容错和降级
Hystrix提供容错,降级,回退,默认集成到了feign子项目中
其中可视化工具仪表盘可以监控服务调用所消耗的时间,请求数,成功率
4)服务网关
zuul实现,提供请求的路由和过滤
路由:将外部请求转发到具体的服务实例上,
过滤:对请求的处理过程进行干预
通过zuul可以将细粒度的服务组合起来提供一个组粒度的服务,所有请求都导入一个统一的入口,对外整个服务只需要暴露一个API接口,屏蔽了服务的实现细节,
5)消息中间件
SpirngCloud提供了Stream子项目,提供了建立消息应用抽象层,构建了消息收发、分组消费和消息分片等功能处理,将业务应用中的消息收发与具体消息中间件进行解耦.。和springboot日志的抽象类似
6)分布式配置中心
SpringCloud提供了Config子项目,将微服务分为两种角色,配置服务器,和配置客户端。
使用配置服务器集中地管理所有配置属性文件,配置服务中心可以将配置属性文件存储到Git、SVN等具有版本管理仓库中,也可以存放在文件系统中
7)微服务链路追踪
SpringCloud子项目sleuth提供了微服务之间调用的链路追踪,
leuth核心思想就是通过一个全局的ID将分布在各微服务服务节点上的请求处理串联起来,还原了调用关系,并借助数据埋点,实现对微服务调用链路上的性能数据的采集,可以很清楚地了解到一个用户请求经过了哪些服务、每个服务处理花费了多长时间
8)微服务安全
Spring CloudSecurity为我们提供了一个认证和鉴权的安全框架,实现了资源授权、令牌管理等功能,同时结合Zuul可以将认证信息在微服务调用过程中直接传递,简化了我们进行安全管控的开发
3.2.2 为何选择Spring Cloud1)Spring Cloud作为Spring Boot的传承,遵循约定优于配置的原则,在使用时不需要复杂的配置就可以运行起来,学习曲线低。
2)Spring Cloud中的大部分子项目开箱即用,采用自动化配置机制,可说使用门槛非常低。
3)…
4)…
三个服务:服务提供者,服务消费者,服务治理服务器
消费者通过feign调用提供者注册在服务治理服务器中得服务,
代码暂时没有,书中代码版本较为破旧
4、服务治理与负载均衡 4.1 什么是服务治理对于微服务架构来说,各个服务的快速上线和下线,从而可以快速进行水平扩展,并且保证服务的可用性,服务治理正好可以解决这一问题
服务治理:通过抽象将服务消费者和提供者进行隔离
消费者不知道真实的服务提供者的真实物理地址,也无须知道具体有多少个服务可以用;
提供者只需要将自己的服务注册到服务治理服务器中即可,也不需要知道具体是哪个消费者来调用的。而且一旦某个服务出现了,那么服务治理服务器可以发现这个有问题的服务,并且绕过有问题的服务实例
实现框架:eureka,是netflix开源框架中一系列项目中的一个,
服务治理框架–eureka解决方案
①eureka服务器(注册中心):负责服务的注册,维护和查询功能
②服务提供者:将服务实例将自己配置信息通过服务名的形式注册到注册中心中
③服务消费者:通过所需要的服务名从注册中心获取服务并且调用
搭建当前项目所需的pom依赖的父工程maven,对依赖版本进行统一的管理,其他项目都继承这个maven即可
4.2.2 搭建服务治理服务器——Eureka服务器继承父工程依赖,导入eureka依赖,
org.springframework.cloud spring-cloud-starter-netflix-eureka-server ${euraka.server.version} //2.1.5.RELEASE
配置文件
server:
port: 7002 #端口号
eureka:
instance:
hostname: cloud-payment-service
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
eureka.client.register-with-eureka属性是用来控制当Spring Boot启动服务完成后是否将该服务注册到服务治理服务器上。这里因为服务本身就是服务治理服务器,而且尚未构建任何服务治理集群,因此将其设置为false,表示不注册。
eureka.client.fetch-registry属性也设置为false,表示应用启动后不需要从服务治理服务器中同步已注册的服务注册列表数据到本地。
其他配置:启动类加上@EnableDiscoveryServer
4.2.3 搭建服务提供者——注册服务创建新模块继承父工程的POM,
org.springframework.cloud spring-cloud-starter-netflix-eureka-client ${euraka.server.version} //2.1.5.RELEASE
eureka:
client:
register-with-eureka: true #是否注册到注册中心
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eurekaServer
defaultZone: http://localhost:7001/eureka/
其他配置:启动类加上@EnableDiscoveryClient
Eureka要求服务提供者必须发送3次心跳(默认每次心跳间隔为10秒)后才认为该服务实例已经准备好
4.2.4 搭建服务消费者——获取服务创建的模块依赖和提供者一样,配置略有不同,eureka-client-fetch-registry改为true即可,因为服务消费者需要调用服务,所以需要从服务中心获取已注册的信息到本地
eureka:
client:
register-with-eureka: false #是否注册到注册中心
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eurekaServer
defaultZone: http://localhost:7001/eureka/
应用第一次与服务治理服务器同步注册服务列表数据后,默认以每30秒的频率与治理服务器进行同步
4.2.5 服务调用(自己加上的一个)RestTemplate
① 提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是spring提供的 用于访问Rest服务的客户端模板工具集,
②发出的http请求的请求方式必须和生产者对应接口所能处理的请求方式一致
DiscoveryClient
①通过resource注解注入
②
List4.3 使用客户端负载均衡——Ribbonlist = discoveryClient.getServices();//获取所有的实例名称 List instanceList = discoveryClient.getInstances("cloud-payment-service");//指定服务名称获取服务实例
在微服务出现之前,消费者和提供者有一个独立的集中式负载均衡系统,该系统通常由专门的硬件(如F5)或者基于软件(Visual Studio、HAproxy等)来承担。
当服务消费者调用某个目标服务时,先向负载均衡系统发起请求,由负载均衡系统以某种策略(如Round-Robin)做负载均衡后再将请求转发给目标服务
4.3.1 什么是客户端负载均衡缺点
①单点失败:一旦负载均衡宕机,那么整个应用无法访问
②难扩展:扩展时非常困难,
③复杂:有些负载均衡本身还对请求处理一些处理,这样导致在使用时还要去学习一下它的技术
在微服务中,负载发生在某个服务消费者调用上面
微服务架构负载均衡解决方案
①集中式负载均衡
独立的一个负载均衡系统,和之前传统的单体架构负载均衡原理一致
②进程内负载均衡(客户端负载均衡)
以库的形式整合到消费者服务中,当消费者调用某些服务时,内置的负载均衡会以某种负载均衡策略选择一个目标服务实例,然后查询真实服务地址,并且调用
③主机独立负载均衡进程方案
将负载均衡从消费者中抽移出来,变成同一主机上的一个独立进程,为该主机上的一个或多个服务消费者提供负载均衡处理。
ribbon就是第二种方案的实现
4.3.2 启用Ribbonribbon中自动整合了eureka,默认负载均衡算法是轮询,
使用
①在RestTemplate中加上增加一个@LoadBalanced注解,这时ResTemplate就具有了负载均衡的功能
@LoadBalanced
@Bean(value="restTemplate")
RestTemplate restTemplate(){return new RestTemplate();}
4.3.3 负载均衡测试
需要搭建两个消费者服务,本机上设置两个服务端口不一样即可,也就是jar包启动设置不同端口就可以了。
4.4 使用epenFeign简化微服务调用(原文是使用feign)有必要说一下,feign已经停更,新版本openFeign功能更加强大,但是主要功能差别不大
openFeign整合了Hystrix和ribbon,接口式调用服务,在当前接口上添加注解,标明HTTP请求的参数,格式,地址等信息。
ribbon简单使用
org.springframework.cloud spring-cloud-starter-openfeign ${openfeign.version} //2.2.1.RELEASE
主启动类:@EnableFeignClients
接口调用:FeignClient(“服务名”),方法和服务端controller一致,并且注解也需要
@FeignClient(value = "cloud-payment-service")
public interface PaymentHystrixService {
@RequestMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id);
@RequestMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id") Integer id);
}
4.5 深入Eureka
4.5.1 服务注册及相关原理
1)CAP理论
在分布式系统领域有个CAP定理(CAP theorem),又被称为布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下3点。
①一致性(Consistency):同一个数据在所有集群的节点中,同一时刻是否有事同样的值
②可用性(availiability):集群中一部分节点故障,集群整体是否还能处理客户端的请求
③分区容忍性(Partition tolerance):是否允许数据的分区,数据分区的意思是指是否允许集群中的节点之间无法通信。
任何一个服务都无法同时满足以上条件:Zookeeper采用的设计原则就是CP原则,Netflix在设计Eureka时遵守的也就是AP原则。
2)eureka服务注册
由eureka服务器维护和存储服务列表,使用嵌套的HashMap保存信息
①第一层hashmap为应用名称和对应的服务实例
②第二层hashmap为服务实例及其对应的注册信息,包括宿主机服务IP地址,服务端口,运行状况指示符,URL等数据
当服务实例状态发生变化时,就会向eureka服务器更新自己的服务状态。
3)服务续约
当服务成功注册eureka服务器时,eureka客户端默认以每隔30秒的频率向eureka发送心跳,也就是续约,避免自己的注册信息被eureka剔除掉
对于eureka服务器来说,默认90秒内,也就是连续3次没有收到心跳,那么就会从维护的服务列表中剔除掉当前服务,如果设置了自我保护模式,那么不会清楚服务实例信息
4)服务下线与剔除
当服务关闭时,会自动向eureka服务器发起下线请求,直接从服务器中剔除
5)获取服务
eureka客户端启动的时候,会从服务器中获取服务列表的信息,并且缓存到本地,默认30秒从eureka服务器进行同步
6)Region、zone
这是由于Region和Zone (或者Availability Zone)均是AWS(Amazon Web Services)的概念。在非AWS环境下,可以暂时将Region简单地理解为大区域或地域,比如当我们租用阿里云服务器的时候需要选择华南、华北、华东等,Zone可理解成机房
4.5.2 Eureka自我保护模式当Eureka服务器每分钟收到心跳续租的数量低于一个阈值,就会触发自我保护模式。当它收到的心跳数重新恢复到阈值以上时,该Eureka服务器节点才会自动退出自我保护模式
服务实例总数量×(60/每个实例心跳间隔秒数)×自我保护系数(0.85)
1)客户端/服务端本地缓存需要时间,默认30秒同步
2)ribbon负载均衡缓存,默认30秒同步
3)服务实例不是启动时注册实例,而是在启动之后的一个延时时间(默认40秒)再注册
eureka服务器的互相复制,同步注册信息,让整个eureka集群中的每个服务都拥有注册服务的信息列表。
4.5.5 多网卡及IP指定当一个服务注册到Eureka服务器后,其他的服务消费者会通过该服务所部署的主机名称进行通信,可能会出错,在开发环境中并没有DNS支持,所以当采用主机名称进行通信的时候就会产生无法找到服务器的错误,
所以推荐使用IP地址访问
4.5.6 Eureka服务访问安全eureka服务器(注册中心)直接通过IP和端口访问不太安全,可以加上验证



