Springcloud分布式框架

 

一、SpringCloud概述

SpringCloud也是基于RPC远程调用的,是在SOA架构基础上演变而来,相对于SOA架构来说更加请假,而且开发要求不是特别严格,基于HTTP+REST+JSON进行数据的传输

SpringCloud基于SpringBoot,提供很多组件,有Eureka,Ribbon,Fegion,zuul,config等

 

二、Eureka注册中心

SpringCloud当中自带注册中心,该角色就是Eureka,主要用于服务发现和调用,分为两个角色:

EurekaServer:服务端    @EnableEurekaServer

管理服务,对外暴露地址

 

EurekaClient:客户端    @EnableEurekaClient

连接到服务端,例如生产者连接到服务端,向上注册服务。   消费者连接到服务端,往下取服务

 

 

1、注册中心环境搭建

步骤一:导入依赖

父工程中导入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>
依赖-->
  <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
  </dependency>
</dependencies>
</dependencyManagement>

2、步骤二:创建配置文件,配置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

 

3、步骤三:创建启动类

@SpringBootApplication
@EnableEurekaServer     //代表是Eureka服务器
public class StartEurekaServer {
public static void main(String[] args) {
SpringApplication.run(StartEurekaServer.class,args);
}
}

4、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

 

 

 

5、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();
}

 

 

2、调用的机制(负载均衡机制)

在RestTemplate模板上加入@LoadBalanced注解,即可实现Ribbon负载均衡,默认机制为轮训机制

 

调整机制:

自定义算法,也可以使用随机访问

 

 

//重新创建一个均衡策略,表示不使用默认
@Bean
public IRule getIReule(){ //通过获取一个IRule对象,
return  new  RandomRule();  //达到的目的,用我们重新选择的随机,替代默认的轮训方式
}

 

 

四、Fegion服务调用

开发步骤:

1、步骤一:在原有基础上导入fegin依赖

<!--Fegin依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、步骤二:创建调用的服务接口

使用fegin注解指定调用应用,和该应用的哪个地址

/**
会员服务
 */
@FeignClient("member-service")      //指定调用的服务应用名称
public interface MemberService {
//获取会员ID服务方法
@RequestMapping("/getMemberId") //调用方法的地址
public Integer getMemberId();
}

3、步骤三:创建配置文件

#端口号

server:
  port: 10001
#应用名称
spring:
  application:
name: order-service
#eureka注册中心地址
eureka:
  client:
service-url:
  defaultZone: http://localhost:8001/eureka

4、步骤四:启动类

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class StartOrderService {
public static void main(String[] args) {
SpringApplication.run(StartOrderService.class,args);
}
}

Fegin默认集成Ribbon,带负载均衡,默认轮训机制

五、zuul路由网关

作用:路由转发和过滤

 

1、步骤一:导入依赖

<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>
依赖-->
  <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
  </dependency>
</dependencies>
  </dependencyManagement>

2、步骤二:配置配置文件

#端口

server:
  port: 20001
#应用名称
spring:
  application:
name: zuul

#注入到注册中心

eureka:
  client:
service-url:
  defaultZone: http://localhost:8001/eureka
#zuul路由配置
zuul:
  routes:
api-a:
外界访问地址
真实服务名称
api-b:
  path: /order/**
  service-id: order-service

3、步骤三:启动类

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy    //zuul路由网关代理
public class StartZuul {
public static void main(String[] args) {
SpringApplication.run(StartZuul.class,args);
}
}

 

 

 

4、zuul过滤器

在zuul路由网关工程当中,加入过滤器

实例:需要传递token,如果不传递则不能正常请求

@Component
public class MyFilter extends ZuulFilter {
/**
过滤类型
代表过滤的时机
 */
@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

2、步骤二:开启熔断注解

@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();  //达到的目的,用我们重新选择的随机,替代默认的轮训方式
}
}

 

3、步骤三:服务降级,如果服务在一段时间内没有相应,那么我们执行服务降级处理

在本地新建一个实现类,然后重写业务方法,实现降级处理

@Component
public class MemberServiceImplLocal implements MemberService {
	@Override
	public Integer getMemberId() {
							System.out.println("服务降级处理");
	return 20002;
		}
	}

4、步骤四:Fegin调用指定fallback降级处理执行得类

/**
* 会员服务,fallback服务降级执行得类
*/
@FeignClient(name = "member-service",fallback = MemberServiceImplLocal.class)      //指定调用的服务应用名称
public interface MemberService {
	//获取会员ID服务方法
						@RequestMapping("/getMemberId") //调用方法的地址
	public Integer getMemberId();
	}

 

 

 

 

七、Rest配置熔断

1、步骤一:降级处理创建处理方法@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";
			}
	}

2、步骤二:配置降级处理时间

##配置服务处理的时间,超过该时间服务没有相应就执行服务的降级

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000

3、步骤三:在启动类中加入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、创建一个配置中心

<dependencies>

  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-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>

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;
    }
}