spring cloud是一个一站式的开发分布式系统的框架,为开发人员提供了快速构建分布式系统中一些常见模式的工具(如:配置管理,服务发现,断路器,智能路由,微代理等)
springcloud版本 | springboot版本 |
---|---|
Finchley | 2.0.X |
Edgware | 1.5.X |
Daslton | 1.5.X |
Camden | 1.4.X |
Brixton | 1.3.X |
Angel | 1.2.X |
provider:暴漏服务的服务提供者
consumer:调用远程服务的服务消费方
eureka server:服务注册中心和服务发现中心
(1)Eureka是一个服务治理组件,主要包括服务注册和服务发现,主要用来搭建服务注册中心。是springcloud对netflix Eureka的二次封装
(2)采用c/s设计架构,分客户端和服务端。服务端是注册中心,而系统中其它微服务使用客户端连接到服务端,并保持心跳连接
1.CAP理论:一个分布式系统不可能同时满足一致性,可用性,分区容错性
(1)一致性:集群中各个节点的数据都是一致的(所以要保证a节点修改的数据及时同步到b节点)
(2)可用性:总是能够访问集群,即使某个机器宕机
(3)分区容错性:大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败
2.为什么不能同时保证ca?
要保证一致性,就要a在写数据的时候,b不能读写。这样就不能保证b的可用性。所以他们之间是相互矛盾的
zookeeper保证cp,eureka保证ap,nacos支持ap和cp
(1)引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RC2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(2)入口类加@EnableEurekaServer注解,开启Eureka注册中心服务端
(3)在application.properties中配置
#端口
server-port=8761
#设置注册中心的hostname
eureka.instance.hostname=localhost
#禁止自己向自己注册
eureka.client.register-with-eureka=false
#不去检索其它服务,因为本身职责就是维护服务实例
eureka.client.fetch-register=false
#指定服务注册中心位置
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
(1)eureka客户端依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RC2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(2)@EnableEurekaClient
表明自己是一个eureka客户端,让服务提供者可以连接eureka注册中心
(3)配置服务名和注册中心地址
server.port=9100
spring.application.name=provider1
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
服务发现(发现注册中心的服务)由eureka客户端实现,服务消费由Ribbon实现
1.ribbon是什么?
Ribon是基于HTTP和TCP的客户端负载均衡器。在eureka客户端服务发现的基础上,实现对服务实例的选择策略,从而实现对服务的负载均衡消费
2.搭建服务消费者调用服务
(1)添加依赖 消费者从注册中心获取服务需要eureka客户端支持
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RC2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(2)@EnableEurekaClient
(3)配置服务注册中心地址
spring.application.name=consumer1
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
(4)使用Ribbon实现服务调用(@LoadBalanced )
@configuration
public class BeanConfig{
@LoadBalanced
@Bean
pulibc RestTemplate restTemplate(){
return new RestTemplate();
}
}
(5)加入Ribbon支持,就不要使用ip+端口来访问,直接通过服务名访问
@RestController
public class WebController{
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/hello")
public String hello(){
return restTemplate.getForEntity("http://provider1/hello").getBody();
}
}
其实就是各个注册中心相互注册
(1)配置多个服务注册中心
8761里配置
eureka.client.service-url.defaultZone=http://eureka8762:8762/eureka/
8762同理...
(2)服务提供者注册到两个服务中心
eureka.client.service-url.defaultZone=http://eureka8762:8762/eureka/,http://eureka8761:8761/eureka/
在没有Eureka自我保护的情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka server将会注销该实例。但有时候仅仅是因为网络故障,直接注销就会很危险,因为微服务本身是正常的。开启自我保护,只会在注册中心页面弹出红色的警告信息。
(1)关闭自我保护机制(服务器端)
#关闭自我保护机制
eureka.server.enable-self-preservation = false
(2)开启自我保护机制带来的问题
在保护期内某个服务提供者刚好非正常下线,此时消费者就会拿到一个无效的服务实例,就会调用失败。
解决方式:服务消费端有重试,断路器等容错机制
(3)eureka客户端相关配置
#每隔两秒向服务器发送一次心跳
erureka.instance.less-renewal-interval-in-seconds=2
#高速服务器,如果10s内没给你发心跳,就代表我故障了
eureka.instance.less-expiration-duration-in-seconds=10
服务消费者通过被@LoadBalanced注解修饰过的RestTemplate来调用服务提供者
nginx是服务器端负载均衡,Ribbon是客户端负载均衡(先通过eureka客户端把服务查出来,缓存,才知道怎么去做负载均衡)
public class BeanConfig{
@Bean
public Irule irule(){
//随机负载均衡策略
return new RandomRule();
}
}
(1)轮询策略(默认):就是拿到所有的server集合,然后根据id进行遍历(当轮询了10个服务端节点还没有找到可用服务的话,轮询结束)
(2)随机策略:使用jdk自带的随机数生成工具,生成一个随机数,然后去可用服务列表中拉取服务节点Server
(3)可用过滤策略:过滤掉连接失败的服务节点,并且过滤掉高并发的服务节点,然后从健康的服务节点中,使用轮询策略选出一个节点返回。
RestTemplate是Spring提供的用于访问Rest服务的客户端
get请求有两种方式
(1)方式一:getForEntity
该方法返回一个ResponseEntity对象,是spring对http请求响应的封装。包含几个重要的元素,比如响应码,contenttype,contentlength,响应消息体等
ResponseEntiry<String> responseEntity = restTemplate.getForEntity("http://provider1/hello", String.class);
String s = responseEntity.getBody();
String.class表示希望返回的类型为String。也可以是其它对象等
可以加第三个参数,代表传的参数
(2)方式二:getForObject
直接返回响应体,没有响应头等一些信息
post与get非常类似
RestTemplate.postForEntity();
RestTemplate.postForObject();
//提交成功之后,返回新资源的URI
RestTemplate.postForLocation();
RestTemplate.put();
RestTemplate.delete();
当被调用方长时间没有响应,调用方直接返回一个错误响应即可,而不是长时间等待。避免了故障在分布式系统蔓延
spring cloud Hystrix基于netflix的hystrix实现了熔断器,线程隔离等一系列保护功能
(1)添加依赖
<!--添加Hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
(2)在入口类使用@EnableCircuitBreaker注解开启断路器功能
(3)在调用方法的地方加
//发生错误回调erroe方法 设置超时时间(默认1s)
@HystrixCommand(fallbackMethod="error", commandProperties = {
@HystrixProperty(name="excution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
(@SpringbotApplication @EnableEurekaClient @EnableCircuitBreaker可以合为一个注解:@SpringCloudApplication)
有了熔断,就会出现服务降级,服务端提供的服务将不被再使用。由客户端准备一个本地的fallback回调。
Hystrix仪表盘主要用来监控Hystrix的实时运行状态,发现系统中的问题从而解决
(1)添加依赖
<!--HystrixDashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
(2)入口类添加注解
@EnableHystrixDashbord
(3)访问
localhost:8080/hystrix
(4) 要实现监控还需要消费者构建监控端点(hystrix.stream)
(1)添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
(2)配置监控端点访问权限
management.endpoints.web.exposure.include=*
(3)访问入口
localhost:8081/actuator/hystrix.stream
Fegin是nexflix公司开发的声明式Rest调用客户端。spring cloud feign基于netflix feign整合了Ribbon和hystrix两个组件(类似于springBoot整合spring和springmvc)
(1)加入Feign依赖
(2)启动类加注解
@EnableFeignClients
(3)声明服务
service包下定义一个接口,通过@FeignClient指定服务提供者名字
//括号里是远程服务名
@FeignClient("helloApplication")
public interface HelloService{
//远程方法
@RequestMapping("/service/hello")
public String hello();
}
(4)调用服务
controller包下
@RestController
public class FeignController{
@Autowired
private helloService HelloService;
@Requestmapping("/web/hello")
public String hello(){
return helloService.hello()
}
}
前面提到Feign整合了ribbon。所以也可以实现负载均衡
不需要额外配置
1.开启hystrix功能
feign.hystrix.enable=true
2.指定熔断回调逻辑
@FeignClient("helloApplication", fallback = MyFallBack.class)
@Component
public class MyFallback implements HelloService{
@Override
public String hello(){
return "发生异常";
}
}
spring cloud zuul基于netflix zuul。实现了请求路由,负载均衡(这里是指服务端的负载均衡。Ribbon和Feign是客户端的),权限验证等功能
(1)添加zuul依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
(2)在入口类添加@EnableZuulProxy注解
(3)配置路由规则
#路由规则
zuul.routes.abc.path=/abc/**
zuul.routes.abc.serviceId=springcloud-service
#可以将上面两条简化为一条
zuul.routes.springcloud-service=/abc/**
①如果什么规则都不写,就会有一套默认规则(上面的abc改成服务名)
②如果有某个规则不想被外部路由
zuul.ignored-services=service-provider
(1)定义一个过滤器,继承ZuulFilter。并将该filter作为一个bean
public class AccessFilter extends ZuulFilter {
private static Logger log = Logger.getLogger(AccessFilter.class);
//过滤器类型 决定在哪个生命周期执行
@Override
public String filterType() {
return "pre";
}
//过滤器执行顺序
@Override
public int filterOrder() {
return 0;
}
//过滤器是否执行
@Override
public boolean shouldFilter() {
return true;
}
//具体的过滤逻辑
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("accessToken");
if (accessToken == null) {
log.warn("access token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
log.info("access token ok");
return null;
}
}
spring cloud config是一个解决分布式系统的配置管理方案。分client和server,server提供配置文件的存储并向外提供接口,client通过接口获取数据(springcloud使用git或svn存放文件)
(1)pom.xml添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config</artifactId>
</dependency>
(2)入口类添加@EnableConfigServer
(3)github创建一个spring-cloud-config的项目
(4)配置文件中配置git仓库信息
(5)访问http://localhost:8080/application/dev/master
路径分别代表配置文件名字,环境,分支
spring.cloud.config.server.git.uri = https://github.com/xuwujing/springcloud-study/
spring.cloud.config.server.git.search-paths = /springcloud-config/config-repo
spring.cloud.config.server.git.username =
spring.cloud.config.server.git.password =
(1)创建配置文件
application.properties
application-dev.properties
application-test.properties
application-online.properties
(1)添加依赖
<!-- spring cloud config 客户端包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
(2)创建bootstrap.yml文件
spring:
profiles: dev
application:
name: config-single-client
cloud:
config:
#配置中心访问路径
uri: http://localhost:3301
label: master
profile: dev
(1)环境部署之前,将所需的配置信息推送到配置仓库
(2)启动配置中心服务端,将配置仓库的配置信息拉取到服务端,配置服务端对外提供REST接口
(3)启动配置客户端,客户端根据 spring.cloud.config 配置的信息去服务器拉取相应的配置
原文:https://www.cnblogs.com/muacheng/p/13289458.html