Spring Cloud笔记:简单项目搭建

微服务概述与Spring Cloud

微服务:
	强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,
狭意的看,可以看作Eclipse里面的一个个微服务工程/或者Module
	从技术角度而言微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。

微服务架构:
	微服务架构是⼀种架构模式,它提倡将单⼀应⽤程序划分成⼀组⼩的服务,服务之间互相协调、互相配合,为⽤户提供最终价值。每个服务运⾏在其独⽴的进程中,服务与服务间采⽤轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进⾏构建,并且能够被独⽴的部署到⽣产环境、类⽣产环境等。另外,应当尽量避免统⼀的、集中式的服务管理机制,对具体的⼀个服务⽽⾔,应根据业务上下⽂,选择合适的语⾔、⼯具对其进⾏构建。

- - -Spring Cloud 项目搭建流程- - -

一、利用idea创建一个空项目

在这里插入图片描述

二、创建注册中心Eureka

file–>new–>Module–>Spring Initializer
在这里插入图片描述
目录结构:
在这里插入图片描述

1、启用注册中心

启动类上

启动一个服务注册中心,只需要一个注解 @EnableEurekaServer

/**
 * 注册中心配置步骤
 * 	   配置Eureka信息
 *     在启动类中使用注解@EnableEurekaServer启用注册中心
 */
@EnableEurekaServer //启用注册中心
@SpringBootApplication
public class EurekaServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}
2、配置Eureka信息

application.yml

在application.yml文件中配置相关参数

server:
  port: 8761 #服务的端口号

# eureka配置
eureka:
  instance:
    hostname: eureka-server  # eureka实例的主机名
  client: #eureka客户端配置
    register-with-eureka: false #不把自己注册到eureka上
    fetch-registry: false #不从eureka上来获取服务的注册信息
    service-url: #指定eureka注册中心的地址
      defaultZone: http://localhost:8761/eureka/
3、启动注册中心

Eureka Server 是有界面的,启动工程,打开浏览器访问:

http://localhost:8761

三、创建服务提供者

file–>new–>Module–>Spring Initializer
在这里插入图片描述

目录结构:
在这里插入图片描述

1、配置Eureka信息

application.yml

server:
  port: 8762 #服务提供者的端口
spring:
  application:
    name: spring-cloud-provider #服务提供者的名字

#注册中心的配置
eureka:
  instance:
    prefer-ip-address: true # 注册服务的时候使用服务的ip地址
  client:
    serviceUrl:  #指定eureka注册中心的地址
      defaultZone: http://localhost:8761/eureka/

**注意:**需要指明 spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个 name

2、声明为Eureka Client

启动类上

启动类上添加注解@EnableEurekaClient表明自己是一个Eureka Client

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient//表明自己是一个Eureka Client
@SpringBootApplication
public class SpringCloudProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudProviderApplication.class, args);
    }
}
3、编写Controller层测试
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @Value("${server.port}")//将配置文件中配配置的端口号读进来
    private String port;//8762

    @RequestMapping(value = "hi", method = RequestMethod.GET)
    public String sayHi(@RequestParam(value = "msg") String msg) {
        //格式化字符串返回
        return String.format("地址栏信息为: %s ,端口号为 : %s", msg, port);
    }
}

这时打开 http://localhost:8762/hi?message=前端数据 ,你会在浏览器上看到 :
在这里插入图片描述

打开 http://localhost:8761 ,即 Eureka Server 的网址,你会发现一个服务已经注册在服务中了,服务名为 SPRING-CLOUDPROVIDER ,端口为 8762
在这里插入图片描述

四、创建服务消费者

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于 http restful 的。Spring cloud 有两种服务调用方式,一种是 ribbon + restTemplate,另一种是 feign。首先讲解下基于 ribbon + rest。

*创建基于Ribbon 的服务消费者

Ribbon 是一个负载均衡客户端,可以很好的控制 httptcp 的一些行为。

1、创建消费者

file–>new–>Module–>Spring Initializer
在这里插入图片描述

目录结构:
在这里插入图片描述

在这里为了后面页面操作,引入了thymeleaf模板引擎。在pom文件中主要是增加了Ribbon的依赖

<!--引入模板引擎-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!--引入ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2、注册到服务中心(注册处中心)

启动类上

通过 @EnableDiscoveryClient 注解注册到服务中心

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient//注册到服务中心
@SpringBootApplication
public class SpringCloudRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudRibbonApplication.class, args);
    }
}
3、配置Eureka信息

application.yml

spring:
  application:
    name: spring-cloud-ribbon #服务发现者的名字
  #模板引擎的配置
  thymeleaf:
    cache: false
    mode: LEGACYHTML5
    encoding: UTF-8
    servlet:
      content-type: text/html

server:
  port: 8764 #端口为8764
#Eureka设置
eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka/
4、编写RestTemplate配置类

新建config.RestTemplateConfiguration类

配置注入 RestTemplate 的 Bean,并通过 @LoadBalanced 注解表明开启负载均衡功能

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration //表明这是一个配置类
public class RestTemplateConfiguration {

    @Bean
    @LoadBalanced //使用负载均衡机制(轮流模式)
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
5、编写Controller
import com.zzr.ribbon.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @Autowired //将service层注入
    private AdminService adminService;

    @RequestMapping(value = "hi",method = RequestMethod.GET)
    public String sayHi(String msg){
        //调用service层的方法,向服务提供者获取数据
        return adminService.sayHi(msg);
    }
}
6、编写Service层

service.AdminService类

在这里我们直接用的程序名替代了具体的 URL 地址,在 Ribbon 中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的 URL 替换掉服务名,代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class AdminService {

    @Autowired //注入配置类RestTemplate
    RestTemplate restTemplate;

    public String sayHi(String msg){
        //利用RestTemplate向服务提供者获取数据  url:http://服务提供者的名字/请求参数
        return restTemplate.getForObject("http://spring-cloud-provider/hi?msg="+msg,String.class);
    }
}
测试访问

在浏览器上多次访问 http://localhost:8764/hi?msg=前端数据

浏览器交替显示下面的信息。达到了负载均衡的效果(轮流机制):

地址栏信息为: 前端信息 ,端口号为 : 8762
地址栏信息为: 前端信息 ,端口号为 : 8763

此时的架构:
在这里插入图片描述

  • 一个服务注册中心,Eureka Server,端口号为:8761
  • 服务提供者spring-cloud-provide 工程运行了两个实例,端口号分别为:87628763
  • 服务消费者spring-cloud-ribbon 工程端口号为:8764
  • spring-cloud-ribbon(消费者) 通过 RestTemplate 调用 spring-cloud-provide(服务者) 接口时因为启用了负载均衡功能故会轮流调用它的 87628763 端口
*创建基于Feign的服务消费者

Feign 是一个声明式的伪 Http 客户端,它使得写 Http 客户端变得更简单。使用 Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用 Feign 注解和 JAX-RS 注解。Feign 支持可插拔的编码器和解码器。Feign 默认集成了 Ribbon,并和 Eureka 结合,默认实现了负载均衡的效果

  • Feign 采用的是基于接口的注解
  • Feign 整合了 ribbon
1、创建服务消费者

file–>new–>Module–>Spring Initializer
在这里插入图片描述

目录结构:
在这里插入图片描述

在这里为了后面页面操作,引入了thymeleaf模板引擎。在pom文件中主要是增加了OpenFeign的依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、开启Feign功能

启动类

通过 @EnableFeignClients 注解开启 Feign 功能

@EnableFeignClients //开启Feign功能
@EnableDiscoveryClient //注册到服务中心
@SpringBootApplication
public class SpringCloudFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudFeignApplication.class, args);
    }
}
3、配置Eureka信息

application.yml

spring:
  application:
    name: spring-cloud-feign #服务发现者的名字
  #模板引擎的配置
  thymeleaf:
    cache: false
    mode: LEGACYHTML5
    encoding: UTF-8
    servlet:
      content-type: text/html

server:
  port: 8765 #端口为8765
#Eureka设置
eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka/
4、创建 Feign 接口

新建service.AdminService类

通过 @FeignClient("服务名") 注解来指定调用哪个服务。代码如下:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "spring-cloud-provider")//value=服务提供者的名字
public interface AdminService {

    @RequestMapping(value = "hi",method = RequestMethod.GET)
    //如果前端页有参数传过来,此处必须加上RequestParam注解用于获取参数
    public String sayHi(@RequestParam(value = "msg") String msg);
}
5、创建测试用的 Controller
import com.zzr.feign.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {
    @Autowired//注入Feign接口
    private AdminService adminService;
    
    @RequestMapping(value = "sayhi",method = RequestMethod.GET)
    public String sayHi(String msg){
        return adminService.sayHi(msg);
    }
}
测试访问

在浏览器上多次访问 http://localhost:8765/sayhi?msg=前端数据

浏览器交替显示:

地址栏信息为: 前端信息 ,端口号为 : 8762
地址栏信息为: 前端信息 ,端口号为 : 8763

—使用熔断器防止服务雪崩—

	在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以通过 RPC 相互调用,在 Spring Cloud 中可以用 RestTemplate + Ribbon 和 Feign 来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet 容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩” 效应。
	为了解决这个问题,业界提出了熔断器模型。
	Netflix 开源了 Hystrix 组件,实现了熔断器模式,Spring Cloud 对这一组件进行了整合。在微服务架构中,一个请求需要调用多个服务是非常常见的,如下图:

在这里插入图片描述

较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值(Hystrix 是 5 秒 20 次) 熔断器将会被打开。
在这里插入图片描述

熔断器打开后,为了避免连锁故障,通过 fallback 方法可以直接返回一个固定值。

Ribbon 中使用熔断器

1、引入依赖

ribbon服务的pom.xml

在搭建好的项目的基础上,在pom文件中引入熔断器的依赖

<!--引入熔断器-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、开启熔断器

启动类

在 启动类 中增加 @EnableHystrix 注解开启熔断器

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@EnableHystrix //开启熔断器
@EnableDiscoveryClient //注册到服务中心
@SpringBootApplication
public class SpringCloudRibbonApplication {

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

3、在 Service 中增加 @HystrixCommand 注解

service.AdminService

在 Ribbon 调用方法上增加 @HystrixCommand 注解并指定 fallbackMethod 熔断方法

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class AdminService {

    @Autowired //注入配置类RestTemplate
    RestTemplate restTemplate;


    @HystrixCommand(fallbackMethod = "error")//熔断器注解   失败后回调error方法
    public String sayHi(String msg){
        //利用RestTemplate向服务提供者获取数据  url:http://服务提供者的名字/请求参数
        return restTemplate.getForObject("http://spring-cloud-provider/hi?msg="+msg,String.class);
    }

    //熔断方法 连不上服务后执行此方法返回,就不会一直阻塞了
    public String error(String msg){
        return String.format("前端的消息为:%s, 但是请求失败了!!",msg);
    }

}

测试熔断器

关闭服务提供者,再次请求 http://localhost:8764/hi?msg=前端数据,浏览器会显示:
在这里插入图片描述

Feign 中使用熔断器

1、开启熔断器

Feign 是自带熔断器的,但默认是关闭的。需要在配置文件中配置打开它,在配置文件增加以下代码:

application.yml

feign:
  hystrix:
    enabled: true #开启熔断器

2、创建熔断器类并实现对应的 Feign 接口

/**
 * 熔断器类
 *   当阻塞时执行这个类中的熔断方法,直接返回
 */

import com.zzr.feign.service.AdminService;
import org.springframework.stereotype.Component;

@Component //交由容器管理
public class AdminServiceHystrix implements AdminService {
    //重写Service接口中的方法,当阻塞时执行此类中的方法
    @Override
    public String sayHi(String msg) {
        //直接返回消息,就不会导致一直阻塞
        return String.format("前端的消息为:%s, 但是请求失败了!!",msg);
    }
}

目录结构:
在这里插入图片描述

3、在 Service 中增加 fallback 指定类

import com.zzr.feign.service.hystrix.AdminServiceHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

//@FeignClient(value = "spring-cloud-provider")//value=服务提供者的名字

//增加熔断器后的写法  fallback=熔断器类.class  本service类的实现类
@FeignClient(value = "spring-cloud-provider",fallback = AdminServiceHystrix.class)
public interface AdminService {

    @RequestMapping(value = "hi",method = RequestMethod.GET)
    //如果前端页有参数传过来,此处必须加上RequestParam注解用于获取参数
    public String sayHi(@RequestParam(value = "msg") String msg);
}

测试熔断器

关闭服务提供者,再次请求 http://localhost:8765/hi?msg=前端数据,浏览器会显示:
在这里插入图片描述

使用熔断器仪表盘监控

在 Ribbon 和 Feign 项目增加 Hystrix 仪表盘功能,两个项目的改造方式相同

1、在 pom.xml 中增加依赖

<!--熔断器仪表盘  监视仪熔断器状态-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

2、开启熔断器仪表盘

在 Application 中增加 @EnableHystrixDashboard 注解,开启熔断器仪表盘

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableHystrixDashboard//开启熔断器仪表盘
@EnableFeignClients //开启Feign功能
@EnableDiscoveryClient //注册到服务中心
@SpringBootApplication
public class SpringCloudFeignApplication {

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

3、创建 hystrix.stream 的 Servlet 配置

在这里插入图片描述

Spring Boot 2.x 版本开启 Hystrix Dashboard 与 Spring Boot 1.x 的方式略有不同,需要增加一个 HystrixMetricsStreamServlet 的配置,代码如下:

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //表明这是一个配置类
public class HystrixDashboardConfiguration {

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

}

测试 Hystrix Dashboard

浏览器端访问 http://localhost:8765/hystrix 界面如下:
在这里插入图片描述

再访问前面的请求,就可以在这里监控到:
在这里插入图片描述

什么情况下会触发 fallback (失败回调-熔断)方法

名字描述触发fallback
EMIT值传递NO
SUCCESS执行完成,没有错误NO
FAILURE执行抛出异常YES
TIMEOUT执行开始,但没有在允许的时间内完成YES
BAD_REQUEST执行抛出HystrixBadRequestExceptionNO
SHORT_CIRCUITED断路器打开,不尝试执行YES
THREAD_POOL_REJECTED线程池拒绝,不尝试执行YES
SEMAPHORE_REJECTED信号量拒绝,不尝试执行YES

fallback 方法在什么情况下会抛出异常

名字描述抛异常
FALLBACK_EMITFallback值传递NO
FALLBACK_SUCCESSFallback执行完成,没有错误NO
FALLBACK_FAILUREFallback执行抛出出错YES
FALLBACK_REJECTEDFallback信号量拒绝,不尝试执行YES
FALLBACK_MISSING没有Fallback实例YES

Hystrix Dashboard 界面监控参数

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值