SpringCloud入门

SpringCloud核心

基于HTTP协议,这就是它和Dubbo的最本质的区别。Dubbo的核心是基于RPC。

SpringCloud组件

注册中心:Eurake

客户端负载均衡:Ribbon

声明式远程方法调用:Feign

服务降级、熔断:Hystrix

网关:Zuul

虽然这个博客涉及到的大部分都是停更的技术,但是停更不停用,还是有很多的企业在用的。

这几个也是比较经典的技术,肯定不会白学

在这里插入图片描述
本博客涉及到的源码地址:https://gitee.com/rabbityyhh/spring-cloud-parent

对应版本:

在spring的官网就有springcloud的全面的介绍,具体的版本问题大家可以在官网里面看

Spring Cloud

测试环境

创建maven父工程spring-cloud-parent,导入springcloud所需要的依赖,cloud的版本与boot的版本要对应,在官网上可查

打包方式为pom就行

<dependencyManagement>
    <dependencies>
        <!--spring cloud Hoxton.SR11-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR11</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--spring boot 2.3.10-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.3.10.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

创建第一个maven module

spring-cloud-common

建立实体类

(把getter setter 无参有参 tostring那一套整上 也可以用Lombok 都随意自己喜欢啥弄啥 太长这里就不写了)

public class entity {
    
    private Integer empId;
    private String empName;
    private Double empSalary;
    
}

创建服务提供者maven module

spring-cloud-provider

这个module打包的方式设置jar 因为后来这个module要以springboot的方式跑起来

pom中导入common还有spring boot web

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.yh.spring.cloud</groupId>
        <artifactId>spring-cloud-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

在yml文件里把这个module的端口号改为1000

server:
  port: 1000

创建一个主启动类

@SpringBootApplication
public class AtYHMainType {

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


}

新建一个handlerEmployeeHandler查看环境是否搭建成功

@RestController
public class EmployeeHandler {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote(){
        return new Employee(555,"nbclass",555.55 );
    }

}

成功就是这样的

在这里插入图片描述

整个module的结构
在这里插入图片描述

创建消费者maven module

spring-cloud-consumer

pom中的依赖跟服务提供者一样 这里省略

主启动类也是跟服务提供者一样的 这里省略

创建config 得到RestTemplate SpringCloudConfig

@Configuration
public class SpringCloudConfig {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

创建handler

@RestController
public class HumanResourceHandler {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/get/employee")
    public Employee getEmployeeRemote(){

        //1.声明远程微服务的主机地址加端口号
        String host = "http://localhost:1000";

        //2.声明具体要调用的功能的URL地址
        String url = "/provider/get/employee/remote";

        //3.通过RestTemplate调用原称为服务
        return  restTemplate.getForObject(host + url, Employee.class);


    }
}

然后把消费者的端口号设为4000就可以跑起来测试了 为什么要设置为4000 因为还有俩提供者用于测试

server:
  port: 4000

成功以后是这样的

在这里插入图片描述

Eureka

创建Eureka注册中心工程

继续创建maven module

spring-cloud-eureka

在pom中导入eureka必要的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

创建主启动类需要注意一点

  • ​ 就是这个@EnableEurekaServer注解是必须加的 没有它就不能导入Eureka相关的Bean
@EnableEurekaServer
@SpringBootApplication
public class AtYHMainType {

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

在yaml配置文件中 这回不关要写端口号了,还得写点eurake自己的配置

server:
  port: 5000

eureka:
  instance:
    hostname: localhost         # 配置当前Eureka服务的主机地址
  client:
    register-with-eureka: false # 当前服务本身就是注册中心,不必“自己注册自己”
    fetch-registry: false       # 当前服务本身就是注册中心,不必“从注册中心取回信息”
    service-url:                # 客户端(指consumer、provider)访问当前注册中心时使用的地址
      defaultZone: http://${eureka.instance.hostname}/${server.port}/eureka

配置之后就可以访问Eureka注册服务中心的主页了

在这里插入图片描述

将provider注册到eureka

在provider中添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置yaml 必须要指定应用名称,每一个微服务工程都要设置一个应用名称 不然没法使用Eureka的功能

spring:
  application:
    name: yh-provider    # 指定当前微服务名称,以便将来通过微服务名称调用当前微服务时能够找到

eureka:
  client:
    service-url:    # 配置当前微服务作为Eureka客户端访问Eureka服务器端时使用的地址
      defaultZone: http://localhost:5000/eureka

注册成功之后可以在Eurake注册中心里看到

在这里插入图片描述

consumer访问provider时使用微服务名称代替localhost:1000

首先在consumer中替换主机地址端口号

//1.声明远程微服务的主机地址加端口号
//        String host = "http://localhost:1000";

        // 将远程微服务调用地址从“IP地址+端口号”改成“微服务名称”
        String host = "http://yh-provider";

在consumer工程加入如下依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在yml中加入配置

server:
  port: 4000
spring:
  application:
    name: yh-consumer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:5000/eureka/

之后在SpringCloudConfig中的方法中加入@LoadBalance注解,让RestTemplate有负载均衡的功能,通过调用Ribbon访问Provider集群

可以改一下com.yh.spring.cloud.handler.HumanResourceHandler中的@RequestMapping("/consumer/ribbon/get/employee")代码看着更明确点

Ribbon

provider以集群方式启动修改provider的handler方法

@RestController
public class EmployeeHandler {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote(HttpServletRequest request){

        // 获取当前服务的端口号
        int serverPort = request.getServerPort();

        return new Employee(555,"nbclass "+serverPort,555.55 );
    }

}

首先启动Eurake中心 然后启动provide:1000 2000 3000

在这里插入图片描述

这样就有三个实例了

再然后我们启动消费者consumer 点击刷新就可以得到轮询负载均衡的 效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Feign

使用Feign实现远程方法声明式调用

在common module中导入feign的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

在common中创建一个接口 实现远程调用的接口方法

//这个注解表示当前接口和一个Provider对应,
// 注解中value属性指定要调用的Provider的微服务名称
@FeignClient(value = "yh-provider")
public interface EmployeeRemoteService {

    //远程调用的接口方法,
    // 要求RequestMapping注解映射的地址一致
    //要求方法声明一致
    // 用来获取请求参数的@RequestParam、@PathVariable、@RequestBody不能省略,两边一致

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote();

}

创建新的maven module

spring-cloud-feign-consumer

导入所需要的一些个依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yh.spring.cloud</groupId>
        <artifactId>spring-cloud-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

之后在主启动类当中加入@EnableFeignClients注解来启用Feign客户端功能

创建handler方法

@RestController
public class FeignHumanResourceHandler {

    // 装配调用远程微服务的接口,后面向调用本地方法一样直接使用
    @Autowired
    private EmployeeRemoteService employeeRemoteService;

    @RequestMapping("/feign/consumer/get/emp")
    public Employee getEmployeeRemote(){
        return employeeRemoteService.getEmployeeRemote();
    }

}

编写yaml配置文件

server:
  port: 7000
spring:
  application:
    name: yh-feign-consumer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:5000/eureka/

都完事之后可以去跑一下 成功的话是可以拿到数据的

在这里插入图片描述

Hystrix

简介

hystrix,框架,提供了高可用相关的各种各样的功能,然后确保说在hystrix的保护下,整个系统可以长期处于高可用的状态,100%。

高可用系统架构:

资源隔离、限流、熔断、降级、运维监控

资源隔离:让你的系统里,某一块东西,在故障的情况下,不会耗尽系统所有的资源,比如线程资源。

限流:高并发的流量涌入进来,比如说突然间一秒钟100万QPS,废掉了,10万QPS进入系统,其他90万QPS被拒绝了。

熔断:系统后端的一些依赖,出了一些故障,比如说mysql挂掉了,每次请求都是报错的,熔断了,后续的请求过来直接不接收了,拒绝访问,10分钟之后再尝试去看看mysql恢复没有

降级:mysql挂了,系统发现了,自动降级,从内存里存的少量数据中,去提取一些数据出来

在这里插入图片描述

测试服务熔断

在服务提供者provider里添加相关的依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

之后在著启动类中加入@EnableCircuitBreaker注解,使用这个注解开启断路器功能

handler

在handler中写一个测试方法

// @HystrixCommand注解指定当前方法出问题时调用的备份方法(使用fallbackMethod属性指定)
@HystrixCommand(fallbackMethod = "getEmpWithCircuitBreakerBackup")
@RequestMapping("/provider/get/emp/with/circuit/breaker")
public ResultEntity<Employee> getEmpWithCircuitBreaker(@RequestParam("signal") String signal) throws InterruptedException {

    if("quick-bang".equals(signal)) {
        throw new RuntimeException();
    }

    if("slow-bang".equals(signal)) {
        Thread.sleep(5000);
    }

    return ResultEntity.successWithData(new Employee(666, "empName666", 666.66));
}

public ResultEntity<Employee> getEmpWithCircuitBreakerBackup(@RequestParam("signal") String signal) {

    String message = "方法执行出现问题,执行断路 signal="+signal;

    return ResultEntity.failed(message);
}

执行成功可以看到

在这里插入图片描述

测试hystrix降级

首先在common module中加入hystrix依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

消费者降级 在common module中的MyFalBackFactory中添加消费者服务降级功能

实现FallbackFactory接口时要传入@FeignClient注解的接口类型
在create方法中返回@FeignClient注解标记的接口类型的对象,当Provider调用失败后,会执行这个对象对应方法

@Component
public class  MyFallBackFactory implements FallbackFactory<EmployeeRemoteService> {


    @Override
    public EmployeeRemoteService create(final Throwable cause) {
        return new EmployeeRemoteService() {
            @Override
            public Employee getEmployeeRemote() {
                return null;
            }

            @Override
            public List<Employee> getEmpListRemote(String keyword) {
                return null;
            }

            @Override
            public ResultEntity<Employee> getEmpWithCircuitBreaker(String signal) {
                return ResultEntity.failed(cause.getMessage());
            }
        };
    }
}

在EmployeeRemoteService接口中的@FeignClient注解中加入注解fallbackFactory属性指定provider不可用时提供备用方案的工厂类型

在feign的handler中添加调用方法

@RequestMapping("/feign/consumer/test/fallback")
public ResultEntity<Employee> testFallBack(@RequestParam("signal") String signal){
    return employeeRemoteService.getEmpWithCircuitBreaker(signal);
}

之后就可以在Feign的yaml文件中开启hystrix

feign:
  hystrix:
    enabled: true 

之后先启动7000 4000

在这里插入图片描述

当启动1000 后 服务重新连接

在这里插入图片描述

监控

在provider中添加依赖并修改他的yaml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

创建新的maven module 用于监控

pom

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
</dependencies>

主启动类

//启用仪表盘监控的功能
@EnableHystrixDashboard
@SpringBootApplication
public class AtYHMainDashboard {
    public static void main(String[] args){
        SpringApplication.run(AtYHMainDashboard.class,args);
    }
}

yaml配置文件

server:
  port: 8000

spring:
  application:
    name: yh-dashboard

之后就可以启动访问 8000

在这里插入图片描述

Zuul网关

网关有以下几个作用:

  • 统一入口:未全部为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。
  • 鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。
  • 动态路由:动态的将请求路由到不同的后端集群中。
  • 减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。

创建zuul工程

创建maven module spring-cloud-zuul

导入需要的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
</dependencies>

配置主启动类和yaml

server:
  port: 9000

spring:
  application:
    name: zuul-gateway
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:5000/eureka/
@EnableZuulProxy
@SpringBootApplication
public class AtYhMainZuul {
    public static void main(String[] args){
        SpringApplication.run(AtYhMainZuul.class,args);
    }
}

访问测试

通过zuul访问服务的,URL地址默认格式为:http://zuulHostIp:port/要访问的服务名称/服务中的URL

服务名称:properties配置文件中的spring.application.name。

服务的URL:就是对应的服务对外提供的URL路径监听。
在这里插入图片描述

使用指定地址代替微服务名称

zuul:
  ignored-services: '*'
  prefix: /maomi  #前缀
  routes:
    employee:
      service-id: yh-feign-consumer
      path: /zuul-emp/**

之后可以重启一下zuul项目

在这里插入图片描述

成功拿到数据

ZuulFilter

编写MyZuulFilter

//加到IOC容器里面
@Component
public class MyZuulFilter extends ZuulFilter {

    Logger logger = LoggerFactory.getLogger(MyZuulFilter.class);

    //判断当前请求是否要过滤
    //要     :继续执行run方法   return true
    // 不要  :直接放行  false
    public boolean shouldFilter() {

        // 获取RequestContext对象
        RequestContext requestContext = RequestContext.getCurrentContext();

        // 获取Request对象
        HttpServletRequest request = requestContext.getRequest();

        // 判断当前请求参数是否为signal=hello
        String parameter = request.getParameter("signal");

        return "hello".equals(parameter);
    }

    public Object run() throws ZuulException {

        logger.info("当前请求要进行过滤,run()方法执行了");

        // Current implementation ignores it.
        // 当前实现会忽略这个方法的返回值,所以返回null,不做特殊处理
        return null;
    }

    public String filterType() {

        // 返回当前过滤器的类型,决定当前过滤器在什么时候执行
        // pre表示在目标微服务前执行
        String filterType = "pre";

        return filterType;
    }

    public int filterOrder() {
        return 0;
    }
}

SpringCloud小结

整体流程

在这里插入图片描述

springboot和springcloud的关系

springboot是基础springcloud要基于springcloud开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rabbityyhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值