一.SpringCloud概述
SpringCloud也是基于RPC远程调用的,是在SOA架构基础上演变而来,相对于SOA架构来说更加请假,而且开发要求不是特别严格,基于HTTP+REST+JSON进行数据的传输
SpringCloud基于SpringBoot,提供很多组件,有Eureka,Ribbon,Fegion,zuul,config等
二.Eureka注册中心
SpringCloud当中自带注册中心,该角色就是Eureka,主要用于服务发现和调用,分为两个角色:
EurekaServer:服务端 @EnableEurekaServer
管理服务,对外暴露地址
EurekaClient:客户端 @EnableEurekaClient
连接到服务端,例如生产者连接到服务端,向上注册服务。 消费者连接到服务端,往下取服务
注册中心环境搭建:
步骤一:导入依赖
父工程中导入SpringBoot依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
子工程:
<dependencies>
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--springCloud依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
步骤二:创建配置文件,配置eureka
#声明端口
server:
port: 8001
#配置eureka
eureka:
client:
#是否把自己注册到注册中心当中去,默认值为true
register-with-eureka: false
#表示是否从Eureka Server获取注册信息,默认为true
fetch-registry: false
#配置注册中心地址
service-url:
defaultZone: http://localhost:8001/eureka
#应用名称,应用名不能有_
spring:
application:
name: eureka-server
步骤三:创建启动类
@SpringBootApplication
@EnableEurekaServer //代表是Eureka服务器
public class StartEurekaServer {
public static void main(String[] args) {
SpringApplication.run(StartEurekaServer.class,args);
}
}
Eureka生产者:
步骤一:创建一个业务接口
/**
* 业务接口
*/
public interface DoSomeService {
/**
* 业务方法
* @return
*/
public String doSome();
}
步骤二:创建一个业务接口的实现类,利用HTTP方式将次接口暴露出去
/**
* 业务接口的实现类
*/
@RestController
public class DoSomeServiceImpl implements DoSomeService {
@RequestMapping("/doSome")
@Override
public String doSome() {
System.out.println("DoSomeService 业务接口的doSome方法");
return "Eureka Provider";
}
}
步骤三:创建配置文件,指定端口,应用名称,Eureka注册中心
#端口号
server:
port: 9001
#应用名称
spring:
application:
name: eureka-provider
#配置EurekaServer注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka
Eureka消费者:
步骤一:创建一个控制器,用于通过HTTP请求到服务提供者
@RestController
@RequestMapping("/doSomeCon")
public class DoSomeController {
@Resource
private RestTemplate restTemplate;
@RequestMapping("/doSome")
public String doSome(){
System.out.println("服务消费者,控制方法");
String returnValue = restTemplate.getForObject("http://localhost:9001/doSome", String.class);
return returnValue;
}
}
步骤二:创建一个启动类,要将RestTemplate模板注入到容器当中
@SpringBootApplication
@EnableEurekaClient
public class StartConsumer {
public static void main(String[] args) {
SpringApplication.run(StartConsumer.class,args);
}
//注入RestTemplate模板
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
}
步骤三:创建配置文件,指定端口,应用名称,Eureka注册中心
#端口号
server:
port: 10001
#应用名称
spring:
application:
name: eureka-consumer
#注册中心
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka
三.Ribbon负载均衡
1.搭建生产者服务集群
条件:端口号不同,应用名称要相同,数据同步
问题:消费者调用怎么办?
消费者不能根据端口号调用,通过应用名字调用
@RequestMapping("/doSome")
public String doSome(){
System.out.println("服务消费者,控制方法");
String returnValue = restTemplate.getForObject("http://eureka-provider/doSome", String.class);
return returnValue;
}
附带问题:restTemplate不知道要使用应用名字调用,默认使用的是IP+端口,解决办法:在注入RestTemplate模板时加入@LoadBalanced注解
//注入RestTemplate模板
@Bean
@LoadBalanced //负载均衡配置,可以使用应用名称调用服务
RestTemplate restTemplate(){
return new RestTemplate();
}
调用的机制(负载均衡机制):
在RestTemplate模板上加入@LoadBalanced注解,即可实现Ribbon负载均衡,默认机制为轮训机制
调整机制:
自定义算法,也可以使用随机访问
//重新创建一个均衡策略,表示不使用默认
@Bean
public IRule getIReule(){ //通过获取一个IRule对象,
return new RandomRule(); //达到的目的,用我们重新选择的随机,替代默认的轮训方式
}
四.Fegion服务调用
开发步骤:
步骤一:在原有基础上导入fegin依赖
<!--Fegin依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
步骤二:创建调用的服务接口,使用fegin注解指定调用应用,和该应用的哪个地址
/**
* 会员服务
*/
@FeignClient("member-service") //指定调用的服务应用名称
public interface MemberService {
//获取会员ID服务方法
@RequestMapping("/getMemberId") //调用方法的地址
public Integer getMemberId();
}
步骤三:创建配置文件
#端口号
server:
port: 10001
#应用名称
spring:
application:
name: order-service
#eureka注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka
步骤四:启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class StartOrderService {
public static void main(String[] args) {
SpringApplication.run(StartOrderService.class,args);
}
}
Fegin默认集成Ribbon,带负载均衡,默认轮训机制
五.zuul路由网关
作用:路由转发和过滤
步骤一:导入依赖
<dependencies>
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--zuul依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--springCloud依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
步骤二:配置配置文件
#端口
server:
port: 20001
#应用名称
spring:
application:
name: zuul
#注入到注册中心
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka
#zuul路由配置
zuul:
routes:
api-a:
path: /member/** #外界访问地址
service-id: member-service #真实服务名称
api-b:
path: /order/**
service-id: order-service
步骤三:启动类
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy //zuul路由网关代理
public class StartZuul {
public static void main(String[] args) {
SpringApplication.run(StartZuul.class,args);
}
}
六zuul过滤器
在zuul路由网关工程当中,加入过滤器
实例:需要传递token,如果不传递则不能正常请求
@Component
public class MyFilter extends ZuulFilter {
/**
* filterType过滤类型
* @return 代表过滤的时机
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器执行顺序,值越小越先执行
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否执行run
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤方法
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//获取到token
String token = request.getParameter("token");
if(token!=null){
return null;
}
//没有传递Token
ctx.setSendZuulResponse(false); //不会转发
ctx.setResponseStatusCode(401); //401代表没有需要的参数
try {
ctx.getResponse().getWriter().write("token is empty");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
七.断路器Hytrix
服务雪崩产生原因:
1.某几个机器故障
2.服务器负载发生变化
3.人为因素
雪崩解决办法:
1.熔断模式:类似于保险丝,当服务响应时间过长或者请求处理不过来的情况下,我们可以熔断该服务,停止服务的调用,快速释放资源,等服务恢复后恢复正常调用
2.隔离模式
3.限流模式
1.Fegin配置熔断
步骤一:开启熔断,配置调用服务的超时时间
#开启熔断
feign:
hystrix:
enabled: true
##配置服务处理的时间,超过该时间服务没有相应就执行服务的降级
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
步骤二:开启熔断注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class StartOrderService {
public static void main(String[] args) {
SpringApplication.run(StartOrderService.class,args);
}
//重新创建一个均衡策略,表示不使用默认
@Bean
public IRule getIReule(){ //通过获取一个IRule对象,
return new RandomRule(); //达到的目的,用我们重新选择的随机,替代默认的轮训方式
}
}
步骤三:服务降级,如果服务在一段时间内没有相应,那么我们执行服务降级处理
在本地新建一个实现类,然后重写业务方法,实现降级处理
@Component
public class MemberServiceImplLocal implements MemberService {
@Override
public Integer getMemberId() {
System.out.println("服务降级处理");
return 20002;
}
}
步骤四:Fegin调用指定fallback降级处理执行得类
/**
* 会员服务,fallback服务降级执行得类
*/
@FeignClient(name = "member-service",fallback = MemberServiceImplLocal.class) //指定调用的服务应用名称
public interface MemberService {
//获取会员ID服务方法
@RequestMapping("/getMemberId") //调用方法的地址
public Integer getMemberId();
}
1.Rest配置熔断
步骤一:降级处理创建处理方法@HystrixCommand注解指定降级处理的方法名称
@RestController
@RequestMapping("/order")
public class OrderController {
/*@Resource
private MemberService memberService;*/
@Resource
private RestTemplate restTemplate;
@RequestMapping("/getOrderByMemberId")
@HystrixCommand(fallbackMethod = "lower") //服务降级执行得方法
public Object getOrderByMemberId(){
return restTemplate.getForObject("http://member-service/getMemberId",String.class);
}
public Object lower(){
return "服务降级";
}
@RequestMapping("/requestOrder")
public Object requestOrder(){
return "order success";
}
}
步骤二:配置降级处理时间
##配置服务处理的时间,超过该时间服务没有相应就执行服务的降级
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
步骤三:在启动类中加入Hystrix注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class StartOrderService {
public static void main(String[] args) {
SpringApplication.run(StartOrderService.class,args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
//重新创建一个均衡策略,表示不使用默认
@Bean
public IRule getIReule(){ //通过获取一个IRule对象,
return new RandomRule(); //达到的目的,用我们重新选择的随机,替代默认的轮训方式
}
}
二.配置中心config
1.准备仓库
2.创建一个配置中心
加入config-server依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
3.创建配置文件
#应用名称
spring.application.name=config-server
#配置端口号
server.port=8888
spring.cloud.config.server.git.uri=https://gitee.com/fenglichao/cloud-config.git
spring.cloud.config.server.git.searchPaths=respo
spring.cloud.config.label=master
spring.cloud.config.server.git.username=
spring.cloud.config.server.git.password=
4.创建启动类
@SpringBootApplication
@EnableConfigServer
public class StartConfigServer {
public static void main(String[] args) {
SpringApplication.run(StartConfigServer.class,args);
}
}
三.配置客户端
1.加入config依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2.配置文件
spring.application.name=config-client
spring.cloud.config.label=master
spring.cloud.config.profile=dev
#配置中心地址
spring.cloud.config.uri=http://localhost:8888/
server.port=9999
3.获取配置文件中值
@RestController
public class ConfigController {
@Value("${userName}")
String userName;
@RequestMapping("/getConfig")
public String getConfig(){
return userName;
}
}
配置文件对空格等形式比较讲究,容易入坑
结尾感谢超哥一路指引