spring cloud 是一系列框架的集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。spring cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 spring boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
spring cloud 对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用 spring cloud 一站式解决方案能在从容应对业务发展的同时大大减少开发成本。同时,随着近几年微服务架构和 docker 容器概念的火爆,也会让 spring cloud 在未来越来越“云”化的软件开发风格中立有一席之地,尤其是在目前五花八门的分布式解决方案中提供了标准化的、一站式的技术方案,意义可能会堪比当年 servlet 规范的诞生,有效推进服务端软件系统技术水平的进步。
1、Spring cloud是一个工具集,集成了多种工具,来解决服务中的各种问题。
微服务的整体解决方案,微服务全家桶
服务发现、远程调用、负载均衡、系统容错—降级熔断、API网关、配置中心、系统监控。。。
2、不是一个解决单一问题的框架
微服务治理,服务注册和发现
负载均衡、请求重试
断路器,服务降级、熔断
ribbon + hystrix 集成,并提供声明式客户端
hystrix 数据监控
API 网关,提供微服务的统一入口,并提供统一的权限验证
配置中心
消息总线, 配置刷新
链路跟踪
Dubbo只是一个远程调用(RPC)框架
默认基于长连接,支持多种序列化格式
dubbo是远程调用工具—RPC调用,java序列化—效率高
2、Spring Cloud --大多是企业的选择
框架集
提供了一整套微服务解决方案(全家桶)
基于http调用, Rest API
Spring cloud集成工具,集成多种工具解决微服务中的所有问题----Http,RestAPI调用,http请求
IDEA/STS、Lombok、Maven—依赖有问题,可通过阿里/中央仓库来回切换,尝试更新
服务注册:
(1)提供者:provider----向注册中心注册自己的地址
(2)消费者:consumer----从注册中心发现其他服务
(1)注册:一次次反复链接,知道注册成功为止
(2)拉取:每个30秒拉取一次注册表,来更新注册信息
(3)心跳:每30秒发送一次心跳(提供者发送),3次收不到则删除父
(4)自我保护模式:特殊情况:由于网络不稳定,15分钟内,85%服务器出现心跳异常----丢失一次,保护所有注册信息不被删除,3次丢失也不删除,网络恢复后,自动退出保护模式,在开发测试期间,可关闭保护模式。
zk—线程的应用
eureka—需要手动添加依赖:eureka server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1、关闭保护模式
2、配置主机名(集群中区分服务器)
3、单台服务器:不向自己注册,也不向自己拉取
eureka:
# 1、关闭保护模式
server:
enable-self-preservation: false
# 2、主机名、配置集群时用来区分主机名
instance:
hostname: eureka1
# 3、单台配置,不向自己注册,也不从自己拉取
client:
register-with-eureka: false
fetch-registry: false
eureka 集群服务器之间,通过 hostname
来区分
eureka.server.enable-self-preservation
eureka 的自我保护状态:心跳失败的比例,在15分钟内是否超过85%,如果出现了超过的情况,Eureka Server会将当前的实例注册信息保护起来,同时提示一个警告,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据。也就是不会注销任何微服务
eureka.client.register-with-eureka=false
不向自身注册
eureka.client.fetch-registry=false
不从自身拉取注册信息
eureka.instance.lease-expiration-duration-in-seconds
最后一次心跳后,间隔多久认定微服务不可用,默认90
@EnableEurekaServer
package cn.tedu.sp05;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class Sp05EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(Sp05EurekaApplication.class, args);
}
}
C:\Windows\System32\drivers\etc\hosts
添加内容:
127.0.0.1 eureka1
127.0.0.1 eureka2
源码: https://github.com/benwang6/spring-cloud-repo
在pom.xml文件中添加eureka客户端依赖
在pom文件中使用快捷键:Alt+Insert
—>Edit Starters
若没有,则添加插件EditStarters
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
# defaultZone:默认地址,其他地点配置,需要由云服务来提供
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka
@EnableDiscoveryClient
(可选)eureka.instance.lease-renewal-interval-in-seconds
心跳间隔时间,默认 30 秒
defaultZone,默认位置,可以修改为具体地理位置,比如:beiJing, shangHai, shenZhen 等,表示 eureka 服务器的部署位置, 需要云服务器提供
eureka.client.registry-fetch-interval-seconds
拉取注册信息间隔时间,默认 30 秒
主程序启用服务注册发现客户端
修改 item-service、user-service 和 order-service,
主程序添加 @EnableDiscoveryClient
注解
启动并访问eureka查看注册信息
源码: https://github.com/benwang6/spring-cloud-repo
原因:自动配置的集群服务器:localhost:8761
解决:在yml文件中添加配置:
service-url:
defaultZone:http://eureka1:2001/eureka
item-service 高可用
启动参数--server.port
可以覆盖yml中的端口配置
配置启动参数:
--server.port=8001
--server.port=8002
相同配置:profiles的配置会覆盖主配置
添加两个服务器的 profile 配置文件
1、application-eureka1.yml
eureka:
instance:
hostname: eureka1
client:
register-with-eureka: true #profile的配置会覆盖公用配置
fetch-registry: true #profile的配置会覆盖公用配置
service-url:
defaultZone: http://eureka2:2002/eureka #eureka1启动时向eureka2注册
2、application-eureka2.yml
eureka:
instance:
hostname: eureka2
client:
register-with-eureka: true #profile的配置会覆盖公用配置
fetch-registry: true #profile的配置会覆盖公用配置
service-url:
defaultZone: http://eureka1:2001/eureka #eureka2启动时向eureka1注册
--spring.profiles.active
和 --server.port
--spring.profiles.active=eureka1 --server.port=2001
--spring.profiles.active=eureka2 --server.port=2002
如果在命令行运行,可以在命令行中添加参数:
java -jar xxx.jar --spring.profiles.active=eureka1 --server.port=2001
java -jar xxx.jar
只加载主配置
eureka客户端注册时,向两个服务器注册
修改以下微服务
sp02-itemservice
sp03-userservice
sp04-orderservice
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
当一个 eureka 服务宕机时,仍可以连接另一个 eureka 服务
源码: https://github.com/benwang6/spring-cloud-repo
ribbon 提供了负载均衡和重试功能, 它底层是使用 RestTemplate 进行 Rest api 调用
RestTemplate 是SpringBoot提供的一个Rest远程调用工具,类似HttpClient,对Http Rest API
调用做了高度封装,只需要调用一个方法就可以完成请求、响应、json转换
常用方法:
后面我们通过一个Demo项目演示 Spring Cloud 远程调用
主程序:
创建 RestTemplate 实例
RestTemplate 是用来调用其他微服务的工具类,封装了远程调用代码,提供了一组用于远程调用的模板方法,例如:getForObject()、postForObject() 等
package cn.tedu.sp06;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {
//创建 RestTemplate 实例,并存入 spring 容器
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Sp06RibbonApplication.class, args);
}
}
SpringCloud提供的工具,对RestTemplate进行了封装,提供了负载均衡和重试的功能。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2、添加@LoadBalanced注解对restTemplate记性增强
@LoadBalanced
负载均衡注解,会对 RestTemplate 实例进行封装,创建动态代理对象,并切入(AOP)负载均衡代码,把请求分发到集群中的服务器
3、用restTemplate调用的地址改成service-id(注册中心注册的服务名):http://item-service/{1}
一种容错方式,调用远程服务失败(异常、超时)时,可以自动进行重试调用
添加重试:
1、在pom.xml文件中添加 spring-retry 依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
application.yml 配置 ribbon 重试
spring:
application:
name: ribbon
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
ribbon:
MaxAutoRetriesNextServer: 2
MaxAutoRetries: 1
OkToRetryOnAllOperations: true
2、配置重试参数:
(1)MaxAutoRtries - 单台服务器的重试次数
(2)MaxAutoRtriesNextServer - 更换服务器的次数
(3)OkToRetryOnAllOperations - 是否对所有类型请求都进行重试,默认只对get重试
(4)ConnectTimeout - 和远程服务建立连接的等待超时时长
(5)ReadTimeout - 建立连接并发送请求后,等待响应的超时时长
两个超时设置,不能在yml中配置,而是要在java代码中设置
ConnectionTimeout
ReadTimeout
OkToRetryOnAllOperations=true
MaxAutoRetriesNextServer
MaxAutoRetries
主程序设置 RestTemplate 的请求工厂的超时属性
package cn.tedu.sp06;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(1000);
f.setReadTimeout(1000);
return new RestTemplate(f);
//RestTemplate 中默认的 Factory 实例中,两个超时属性默认是 -1,
//未启用超时,也不会触发重试
//return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Sp06RibbonApplication.class, args);
}
}
源码: https://github.com/benwang6/spring-cloud-repo