SpringCloud入门教程与基本概念

SpringCloud

1、SpringCloud简介

springCloud是基于SpringBoot的一整套实现微服务的框架。他提供了微服务开发所需的配置管理、服务发现、断路器、智能路由、决策竞选、分布式会话和集群状态管理等组件。

常用的6大核心组件

  • 服务发现——Netflix Eureka
  • 客服端负载均衡——Netflix Ribbon
  • 声明式web service客户端——Netflix feign
  • 断路器——Netflix Hystrix
  • 服务网关——Netflix Zuul
  • 分布式配置——Spring Cloud Config

2、服务注册与发现-eureka

什么是服务注册与发现?

在分布式环境下,一个项目往往被拆分成多个模块,各模块部署在不同的区域或节点上,而往往一个大的项目可能就有几十个子模块,这对于开发和管理来说是非常棘手的事情。例如下图中,你想知道有多少个模块,你得一个个去找启动的服务才能算出你运行了多少个模块,而开发者还得去记每个模块的访问地址,如果是这样,我宁愿我不是一只程序猿。
在这里插入图片描述

而服务注册就是通过注册中心来配置和管理这些模块。

但是注册也分手动注册和自动注册呀,手动注册很好理解,通过配置文件方式在注册中心将每个模块写上就可以实现了。但是手动注册对于弹性扩容与下线来说,无疑是难以处理的,如果要下线一个模块,就得将注册中心停止重新启动,因为大家知道,配置一般都是启动时一次加载生效的。

自动注册就是让每个模块向注册中心发起注册请求,注册中心只需要接收到该请求就知道该模块被运行了,而开发人员只需要通过注册中心就可以知道每个模块的访问方式,也能知道有多少个模块被运行了。如下图所示

在这里插入图片描述

如果其中一个模块下线了,注册中心还能感知这个模块的状态是上线还是下线,那么这就是服务发现。

什么是eureka

eureka在springcloud中是Spring Cloud Eureka的简称, 它是Spring Cloud Netflix 微服务套件中的一部分, 它基于netflix开源组织提供的Netflix Eureka 做了二次封装, 主要负责完成微服务架构中的服务治理功能。

Spring Cloud 通过为Eureka 增加了Spring Boot 风格的自动化配置,我们只需通过简单引入依赖和注解配置就能让Spring Boot 构建的微服务应用轻松地与Eureka 服务治理体系进行整合。

eureka的三个角色

eureka中有3个重要角色,分别是服务注册中心、服务提供者、服务消费者。

• 服务注册中心:

Eureka 提供的服务端, 提供服务注册与发现的功能, 一般被称作eureka-server。

服务提供者:

提供服务的应用, 可以是Spring Boot 应用, 也可以是其他技术平台且遵循Eureka 通信机制的应用。它将自己提供的服务注册到Eureka, 以供其他应用发现

• 服务消费者:

消费者应用从服务注册中心获取服务列表, 从而使消费者可以知道去何处调用其所需要的服务,这个不是我们这部分的内容,暂不介绍。

在这里插入图片描述

一般来说,服务提供者也可以是消费者,服务消费者也可以是服务提供者。

在这里插入图片描述

下面我们将分别来创建注册中心、服务提供者、服务消费者。

eureka的使用

1、首先,我们创建一个maven项目,用来管理所有的子模块,由于它是个父项目,不写具体业务逻辑,所以创建完成后可以将src目录删除。

创建eureka注册中心

2、创建springboot项目,名称为:eureka-server,选择eureka Server组件

在这里插入图片描述

在eureka-server的application.properties文件中加入如下内容

# 端口
server.port=8080

# 是否将自己作为客户端注册到注册中心(缺省true),选择不注册自己
eureka.client.register-with-eureka=false

# 设置是否从注册中心获取注册信息(缺省true)
# 因为这是一个单点的EurekaServer,不需要同步其它EurekaServer节点的数据,故设为false
eureka.client.fetch-registry=false

# 注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/

在启动类中加上@EnableEurekaServer

启动服务,输入:localhost:8080可以看到eureka的监控见面

在这里插入图片描述
从上图看到,在"Instances currently registered with Eureka"信息中,没有一个实例,说明目前还没有服务注册。接下来创建一个服务提供者eureka-client进行注册测试。

创建服务提供者/消费者

创建springboot项目,项目名:eureak-client-01,选择web、eureak Discovery这2个组件,注意,一定要选择web模块让它持久运行,不然服务一注册就会立马销毁了。

在这里插入图片描述
在这里插入图片描述

在eureka-client-01这个项目的application.properties文件中,添加如下内容:

# 端口
server.port=9090

# 客户端名称,非常重要
spring.application.name=client1

# 注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/

在启动类中加上@EnableEurekaClient

@EnableEurekaClient和@EnableDiscoveryClient的区别

spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),@EnableDiscoveryClient基于spring-cloud-commons,@EnableEurekaClient基于spring-cloud-netflix。

就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

其它配置
##############client#############

#健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true

# 服务和注册中心的心跳间隔时间,默认为30s
eureka.instance.lease-renewal-interval-in-seconds=30

# 服务和注册中心的心跳超时时间,默认为90s
eureka.instance.lease-expiration-duration-in-seconds=90

##############server#############
# 关闭自我保护机制(开发时建议关闭)
eureka.server.enable-self-preservation=false`

#清理间隔(单位毫秒,默认是60*1000)
eureka.server.eviction-interval-time-in-ms=1000
Eureka跨机房灾备

Eureka通过增加region和zone的定义可以快速时间跨机房灾备(region和zone的概念均来自于亚马逊的AWS)
一般region概念指代区域,如亚洲地区、华北地区、北京等。而zone概念指代具体机房。
灾备原则是一个机房内的Consumer优先调用同机房的Service,当同一机房的service或者eureka不可用时,再去调用其他机房的服务。

#多区域多机房配置
eureka.client.prefer-same-zone-eureka=true
#区域
eureka.client.region=beijing
#在该区域下定义两个机房
eureka.client.availability-zones.beijing=zone1,zone2

#分别配置这2个机房
eureka.client.serviceUrl.zone1=http://localhost:9002/eureka
eureka.client.serviceUrl.zone2=http://localhost:9003/eureka
eureka的其它概念
1、服务注册
服务启动时向注册中心发送REST请求将自己注册到Eureka Server中
2、服务同步
多个注册中心时,向其中一个注册中心注册,会自动同步到其它注册中心
3、服务续约
服务注册完后,服务提供者会维护一个心跳来不停的告诉Eureka Server:“我还在运行”,请不要将我踢出去。
4、获取服务
当我们启动服务消费者的时候,它会发送一个REST请求给服务注册中心来获取服务注册中心上面的服务提供者列表。
5、服务调用
服务消费者从注册中心拿到服务列表后,通过restTemplate或fegin调用服务。
6、服务下线
服务进行正常关闭时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心我要下线了,注册中心会踢出该服务。
7、失效剔除

Eureka Server每隔60秒剔除服务列表中超过90秒还没续约的服务,通常是非正常下线的服务。

8、自我保护

Eureka Server在运行期间会去统计心跳失败比例在15分钟之内是否低于85%,如果低于85%,Eureka Server会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。我们在单机测试的时候很容易满足心跳失败比例在15分钟之内低于85%,这个时候就会触发Eureka的保护机制,一旦开启了保护机制,则服务注册中心维护的服务实例就不是那么准确了,此时我们可以使用eureka.server.enable-self-preservation=false来关闭保护机制,这样可以确保注册中心中不可用的实例被及时的剔除。

9、Eureka基本规则
  • 服务启动时会生成服务的基本信息对象InstanceInfo,然后在启动时会register到服务治理中心。
  • 注册完成后会从服务治理中心拉取所有的服务信息,缓存在本地。
  • 之后服务会被30s(可配置)发送一个心跳信息,续约服务。
  • 如果服务治理中心在90s内没有收到一个服务的续约,就会认为服务已经挂了,会把服务注册信息删掉。
  • 服务停止前,服务会主动发送一个停止请求,服务治理中心会删除这个服务的信息。
  • 如果Eureka Server收到的心跳包不足正常值的85%(可配置)就会进入自我保护模式,在这种模式下,Eureka Server不会删除任何服务信息。
10、服务注册中心的缓存

Eureka注册中心有一个Map来保存所有的服务及映射的机器信息:

private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry
            = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
  • 服务注册时,会把服务的信息写到这个registry中
  • 服务从治理中心拉取服务列表信息时,不会从这个registry中拉取,而是从一个ResponseCache中拉取,这样读写分离的原因应该是为了支持高并发。

而ResponseCache又分为了两个部分,一个是ReadWriteMap,一个是ReadOnlyMap。

  • ReadWriteMap的数据是从registry中来的,可以认为是registry的缓存,当服务注册时,除了把信息写到registry中外,还会让ReadWriteMap主动过期,使得会去从registry重新拉取数据。
  • ReadOnlyMap的数据是从ReadWriteMap来的,可以认为是ReadWriteMap的缓存(所以它是registry缓存的缓存,双层缓存了),当服务需要获取服务列表是,会直接取这个ReadOnlyMap的数据,当这个数据不存在时,才会从ReadWriteMap中更新。
  • ReadWriteMap与registry的数据是实时一致的(因为有注册后让ReadWriteMap失效的机制),但是ReadWriteMap与ReadOnlyMap不是实时一致的。
  • 有定时任务会定时从ReadWriteMap同步到ReadOnlyMap,这个时间配置是:eureka.server.responseCacheUpdateInvervalMs
  • EurekaServer内部有定时任务,每隔检查过期实例时间,扫描Registry里面过期的实例并删除,并且使对应的ReadWriteMap缓存失效,这个时间是eureka.server.eviction-interval-timer-in-ms
Eureka与Zookeeper

Dubbo使用Zookeeper作为注册中心,而SpringCloud使用Eureka作为注册中心。两者作为服务中心,在单点使用时差别不大,但是在作为集群服务时有些区别。

  • 以CAP理论,zookeeper是保证CP的,而Eureka是保证AP的。即在集群面临各种宕机、网络波动等分布式问题时,前者更偏向保证数据一致,而后者更偏向保证服务可用。
  • 集群方式:zookeeper集群需要以选举算法保证集群中有一个唯一的leader,这样,集群在选举过程中,容易导致短暂服务不可用。而Eureka集群的方式则是简单的互相注册,即把当前Eureka节点也作为一个服务,向其他Eureka节点进行注册。这样当有节点宕机后,直接用另外一些节点提供服务即可。但是这时,就存在节点之间数据同步没有完成的问题。这个集群方式也是两者CP与AP之争的根本。
  • Eureka的自我保护机制也是别人说Eureka更适合做服务中心的特点之一。

3、远程调用

现在服务确实知道在哪里了,同时也知道监听着哪些端口号了。但是新问题又来了,难道要自己写一大堆代码,跟其他服务建立网络连接,然后构造一个复杂的请求,接着发送请求过去,最后对返回的响应结果再写一大堆代码来处理吗?来感受一下Http Client发请一个post请求的代码,是不是感到很绝望?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ANiYkOAZ-1575627764486)(assets/1574726835883.png)]

如果是这样,我宁愿我不是只程序猿。

别慌,这些脏活早就有人帮我们做好了,那就是RestTemplate和Feign。

RestTemplate
简介

spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,
我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

特点

在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring *模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。

RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。

考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。

使用

RestTemplate包含以下几个部分:

  • HttpMessageConverter 对象转换器
  • ClientHttpRequestFactory 默认是JDK的HttpURLConnection
  • ResponseErrorHandler 异常处理
  • ClientHttpRequestInterceptor 请求拦截器

在Spring Cloud中使用RestTemplate的几种方式

直接使用

RestTemplate restTemplate = new RestTemplate();

使用@LoadBalanced注解方式

restTemplate.getForObject("http://client1/demo", String.class);
资料

源代码分析

Feign

Feign是一个声明式远程调用客户端。使用Feign能让编写远程调用客户端更加简单,
它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

使用

1、添加依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、启动类上加上@EnableFeignClients

3、编写Feign接口

@FeignClient("client1")
public interface FUserService {

    @GetMapping("demo")
    public String demo();
}

其中,@FeignClient(“服务名称”),也就是要调用的服务的spring.applicaiton.name的值。

方法public String demo();和普通接口一样,方法名随便定义,方法返回值是远程接口返回的类型,@getMapping(“demo”)是指远程服务"client1"中controller的方法映射地址。如果远程服务是Post,那么就得用PostMapping。

负载均衡

修改服务提供者的端口,再次启动一个实例,此时eureka监控面板上出现了2个client1的服务,使用Feign调用client1,会发现两个服务交替调用的现象,说明此时已经是进入负载了。

4、熔断器-Hystrix

雪崩效应

在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。
在这里插入图片描述

熔断器

熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。 熔断器开关相互转换的逻辑如下图:
在这里插入图片描述
熔断器就是保护服务高可用的最后一道防线。

Hystrix特性

1.断路器机制

断路器很好理解, 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.

2.Fallback

Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.

3.资源隔离

在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池. 例如调用产品服务的Command放入A线程池, 调用账户服务的Command放入B线程池. 这样做的主要优点是运行环境被隔离开了. 这样就算调用服务的代码存在bug或者由于其他原因导致自己所在线程池被耗尽时, 不会对系统的其他服务造成影响. 但是带来的代价就是维护多个线程池会对系统带来额外的性能开销. 如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话, 可以使用Hystrix的信号模式(Semaphores)来隔离资源.

Hystrix

因为熔断只是作用在服务调用这一端,因此我们只需要改动上面项目相关代码就可以了。因为,Feign中已经依赖了Hystrix所以在maven配置上不用做任何改动。

1、配置文件

application.properties添加这一条:

feign.hystrix.enabled=true
2、创建回调类

创建HelloRemoteHystrix类继承与HelloRemote实现回调的方法

@Component
public class HelloRemoteHystrix implements HelloRemote{

    @Override
    public String hello(@RequestParam(value = "name") String name) {
        return "hello" +name+", this messge send failed ";
    }
}
3、添加fallback属性

HelloRemote类添加指定fallback类,在服务熔断的时候返回fallback类中的内容。

@FeignClient(name= "spring-cloud-producer",fallback = HelloRemoteHystrix.class)
public interface HelloRemote {

    @RequestMapping(value = "/hello")
    public String hello(@RequestParam(value = "name") String name);

}
熔断监控Hystrix Dashboard和Turbine

Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数据。但是只使用Hystrix Dashboard的话, 你只能看到单个应用内的服务信息, 这明显不够. 我们需要一个工具能让我们汇总系统内多个服务的数据并显示到Hystrix Dashboard上, 这个工具就是Turbine.

Hystrix Dashboard

我们在熔断示例项目spring-cloud-consumer-hystrix的基础上更改,重新命名为:spring-cloud-consumer-hystrix-dashboard。

1、添加依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
 <!--指标流-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

这三个包必须添加

2、启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableCircuitBreaker
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}


3、测试

启动工程后访问 http://localhost:9001/hystrix,将会看到如下界面:
在这里插入图片描述
到此单个应用的熔断监控已经完成。

Turbine

在复杂的分布式系统中,相同服务的节点经常需要部署上百甚至上千个,很多时候,运维人员希望能够把相同服务的节点状态以一个整体集群的形式展现出来,这样可以更好的把握整个系统的状态。
为此,Netflix提供了一个开源项目(Turbine)来提供把多个hystrix.stream的内容聚合为一个数据源供Dashboard展示。

1、添加依赖
<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-turbine</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-netflix-turbine</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
	</dependency>
</dependencies>
2、配置文件
spring.application.name=hystrix-dashboard-turbine
server.port=8001
turbine.appConfig=node01,node02
turbine.aggregator.clusterConfig= default
turbine.clusterNameExpression= new String("default")

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
  • turbine.appConfig :配置Eureka中的serviceId列表,表明监控哪些服务
  • turbine.aggregator.clusterConfig :指定聚合哪些集群,多个使用”,”分割,默认为default。可使用http://.../turbine.stream?cluster={clusterConfig之一}访问
  • turbine.clusterNameExpression : 1. clusterNameExpression指定集群名称,默认表达式appName;此时:turbine.aggregator.clusterConfig需要配置想要监控的应用名称;2. 当clusterNameExpression: default时,turbine.aggregator.clusterConfig可以不写,因为默认就是default;3. 当clusterNameExpression: metadata[‘cluster’]时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster: ABC,则需要配置,同时turbine.aggregator.clusterConfig: ABC
3、启动类

启动类添加@EnableTurbine,激活对Turbine的支持

@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
public class DashboardApplication {

	public static void main(String[] args) {
		SpringApplication.run(DashboardApplication.class, args);
	}

}

到此Turbine(hystrix-dashboard-turbine)配置完成。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值