SpringCloud入门知识3

1 Gateway

1.1 Gateway概述

  • 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。

  • 在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。

  • 网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等.

  • 在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等
    网关工作图

1.2 Gateway入门案例

1 创建网关模块api-gateway-server
2 在pom.xml中引入依赖:starter-gateway

 <dependencies>
        <!--引入gateway 网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

3 编写启动类

package com.cf.gateway;

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

@SpringBootApplication
@EnableEurekaClient
public class ApiGatewayApp {
    
    

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

4 编写配置文件application.yml

server:
  port: 80

spring:
  application:
    name: api-gateway-server

  cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合。
      # id: 唯一标识。默认是一个UUID
      # uri: 转发路径
      # predicates: 条件,用于请求网关路径的匹配规则
      - id: gateway-provider
        # 静态路由,路径固定,不方便修改
        uri: http://localhost:8001/
        predicates:
        - Path=/goods/**

5 访问测试http://localhost:80/goods/findOne/3

1.3 Gateway-动态路由

1 在启动类入口上添加@EnableEurekaClient(新版本不加也可以).

2 引入eureka-client配置,在application.yml中修改uri属性:uri: lb://服务名称.(lb,LoadBalanced负载均衡)

server:
  port: 80

spring:
  application:
    name: api-gateway-server

  cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合。
      # id: 唯一标识。默认是一个UUID
      # uri: 转发路径
      # predicates: 条件,用于请求网关路径的匹配规则
      # filters:配置局部过滤器的

      - id: gateway-provider
      	# 静态路由
        # uri: http://localhost:8001/
        # 动态路由
        uri: lb://GATEWAY-PROVIDER
        predicates:
        - Path=/goods/**

1.4 Gateway-微服务名称配置

application.yml配置文件中:

扫描二维码关注公众号,回复: 12658877 查看本文章
      # 微服务名称配置
      discovery:
        locator:
          enabled: true # 设置为true 请求路径前可以添加微服务名称
          lower-case-service-id: true # 允许为小写

1.5 局部过滤器

  • GatewayFilter 局部过滤器,是针对单个路由的过滤器。
  • 在Spring Cloud Gateway 组件中提供了大量内置的局部过滤器,对请求和响应做过滤操作。
  • 遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。

在api-gateway-server模块中application.yml

server:
  port: 80
spring:
  application:
    name: api-gateway-server
  cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合。
      # id: 唯一标识。默认是一个UUID
      # uri: 转发路径
      # predicates: 条件,用于请求网关路径的匹配规则
      # filters:配置局部过滤器的

      - id: gateway-provider
        # 静态路由
        # uri: http://localhost:8001/
        # 动态路由
        uri: lb://GATEWAY-PROVIDER
        predicates:
        - Path=/goods/**
        # 局部过滤器 添加请求头参数
        filters:
        - AddRequestParameter=username,zhangsan

在gateway-provider模块中GoodsController中的findOne添加username参数

 public Goods findOne(@PathVariable("id") int id,String username){
    
    
 
        System.out.println(username);
        //如果id == 1 ,则出现异常,id != 1 则正常访问
        if(id == 1){
    
    
            //1.造个异常
            int i = 3/0;
        }

        /*try {
            //2. 休眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
        return goods;
    }

总结:
局部过滤器之添加请求头,客户端发送请求,过滤器拦截,并添加请求头参数,转发到指定访问地址.

1.6 全局过滤器

  • GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。
  • Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。

全局过滤器
自定义全局过滤器步骤:
1 定义类实现 GlobalFilter 和 Ordered接口
2 复写方法
3 完成逻辑处理

package com.cf.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyFilter implements GlobalFilter, Ordered {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    

        System.out.println("自定义全局过滤器执行了~~~");
        return chain.filter(exchange);//放行
    }

    /**
     * 过滤器排序
     * @return 数值越小 越先执行
     */
    @Override
    public int getOrder() {
    
    
        return 0;
    }
}

1.7 路由前/后缀

添加路由前缀

  cloud:
    gateway:
      #路由,内部是一个数组类型
      routes:
      #provider生产者服务
        - id: gateway-provider #可以随意起,但是一般和应用名称保持一致
          #uri: http://localhost:8001/
          #以lb://开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称
          uri: lb://GATEWAY-PROVIDER
          predicates:
          #- Path=/goods/**
          - Path=/**
          filters:
          #- AddRequestParameter=username,lisi
          - PrefixPath=/goods #表示会自动在端口号之后加入该前缀

访问网关:
http://localhost/findOne/2

gateway网关会自动进行转发拼接成:http://localhost:8001/goods/findOne/2 从而获取数据

去除路由前缀:

  cloud:
    gateway:
      #路由,内部是一个数组类型
      routes:
      #provider生产者服务
        - id: gateway-provider #可以随意起,但是一般和应用名称保持一致
          #uri: http://localhost:8001/
          #以lb://开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称
          uri: lb://GATEWAY-PROVIDER
          predicates:
          - Path=/api/api2/goods/** #api和api2都是我们自己加的前缀
          #- Path=/**
          filters:
          #- AddRequestParameter=username,lisi
          #- PrefixPath=/goods  #添加的前缀
          - StripPrefix=2 #表示前缀去除的个数  

访问:http://localhost/api/api2/goods/findOne/2

最终gateway经过内部过滤器会去除前两个前缀,最终转发到 http://localhost:8001/goods/findOne/2

2 Config 分布式配置中心

创建configserver微服务,为了获取gitee仓库中的配置文件

1 导入pom.xml坐标

<!-- config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

2 配置application.yml

    # spring cloud config
spring:
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/lidengpan/itheima-config.git #改成给自己的仓库地址
      label: master #所处的分支

3 在入口类上加入注解说明是config服务端

//启用config server功能
@EnableConfigServer

4 通过config-server服务去访问git中仓库中的配置文件内容
http://localhost:9527/master/config-dev.yml

创建config-client客户端

1 导入pom.xml依赖

 <!--config client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

2 在客户端resource下创建一个bootstrap.yml文件(bootstrap.yml文件加载的优先级要高于application.yml,主要应用于加载配置文件)

# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
  cloud:
    config:
      # 配置config-server地址
      uri: http://localhost:9527
      # 配置获得配置文件的名称等信息
      name: config # 文件名
      profile: dev # profile指定,  config-dev.yml
      label: master # 分支
客户端刷新操作

1 导包pom.xml,只需要到actuator包,目的是为了监控springboot程序

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

2 添加注解@RefreshScope
(注解是谁调用远程配置文件,加载谁的头上,一般是在controller类之上)

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
@RefreshScope // 开启刷新功能
public class GoodsController {
    
    

    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;

    @Value("${cf}")
    private String cf;
    ...
    }

3 在配置文件中加入监控

management:
  endpoints:
    web:
      exposure:
        include: '*'

4 刷新

  • 利用post请求方式执行刷新请求 http://localhost:8001/actuator/refresh
    (可以使用postman工具来实现)

  • 可以使用在cmd 环境下:curl -X POST http://localhost:8001/actuator/refresh

config集成Eureka

config-server配置服务端
1 pom.xml中引入eureka-client 坐标

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

2 配置文件中配置eureka地址

eureka:
	client:
		service-url:
			defaultZone: http://localhost:8761/eureka/

3 启动类中添加注解

......
@SpringBootApplication
@EnableConfigServer // 启用config server功能
@EnableEurekaClient
public class ConfigServerApp {
    
    ......}

4 config-provider 工程中bootstrap.yaml中注掉写死的地址,改为从Eureka中获取

# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
  cloud:
    config:
      # 配置config-server地址
      #uri: http://localhost:9527
      # 配置获得配置文件的名称等信息
      name: config # 文件名
      profile: dev # profile指定,  config-dev.yml
      label: master # 分支
      #从注册中心获取config-server地址
      discovery:
      	enabled:true
      	service-id:CONFIG-SERVER

3 bus

3.1 bus概述

• Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相通信。

• Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka
bus工作图

3.2 bus入门案例

1 分别在 config-server 和 config-client的pom.xml中引入 bus依赖:bus-amqp

        <!-- bus -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

2 在 config-server 和 config-client的bootstrap.yml中配置 RabbitMQ

  #配置rabbitmq信息
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /

3 OrderController上添加@RefreshScope注解

@RestController
@RequestMapping("/order")
@RefreshScope
public class OrderController {
    
    

    @Value("${itheima}")
    private String itheima;
    ...
    }

4 在config-server中application.yml设置暴露监控断点:bus-refresh


# 暴露bus的刷新端点
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'

5 启动测试
单个客户端刷新:

  • curl -X POST http://localhost:8001/actuator/refresh

所有客户端刷新:

  • curl -X POST http://localhost:9527/actuator/bus-refresh

4 stream

4.1 stream概述

• Spring Cloud Stream 是一个构建消息驱动微服务应用的框架。
• Stream 解决了开发人员无感知的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件,使得微服务开发的高度解耦,服务可以关注更多自己的业务流程。
• Spring Cloud Stream目前支持两种消息中间件RabbitMQ和Kafka
stream工作图

4.2 stream-组件

• Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件的实现细节对应用程序来说是透明的。

• binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起.
• output:发送消息 Channel,内置 Source接口.
• input:接收消息 Channel,内置 Sink接口.
在这里插入图片描述

4.3 stream-入门案例

创建消息生产者模块

1 pom.xml引入依赖starter-stream-rabbit

        <!-- stream -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

2 application.yml编写配置,定义 binder,和 bingings

server:
  port: 8000
spring:
  cloud:
    stream:
      # 定义绑定器,绑定到哪个消息中间件上
      binders:
        itheima_binder: # 自定义的绑定器名称
          type: rabbit # 绑定器类型
          environment: # 指定mq的环境
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
                virtual-host: /
      bindings:
        output: # channel名称
          binder: itheima_binder #指定使用哪一个binder
          destination: itheima_exchange # 消息目的地

3 定义消息发送业务类。添加 @EnableBinding(Source.class),注入
MessageChannel output ,完成消息发送.

MessageProducer

  package com.cf.stream.producer;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.cloud.stream.annotation.EnableBinding;
  import org.springframework.cloud.stream.messaging.Source;
  import org.springframework.messaging.MessageChannel;
  import org.springframework.messaging.support.MessageBuilder;
  import org.springframework.stereotype.Component;
  
  @Component
  @EnableBinding(Source.class)
  public class MessageProducer {
    
    
  
      @Autowired
      private MessageChannel output;
  
      public void send(){
    
    
          String msessage = "hello stream~~~";
  
          //发送消息
          output.send(MessageBuilder.withPayload(msessage).build());
  
          System.out.println("消息发送成功~~~");
  
      }
  }

ProducerController

package com.cf.stream.producer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProducerController {
    
    

    @Autowired
    private MessageProducer producer;

    @RequestMapping("/send")
        public String sendMsg(){
    
    
        producer.send();
        return "success";
    }
}

4 启动启动类,测试

创建消费者模块

1 pom.xml引入依赖starter-stream-rabbit

        <!-- stream -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

2 编写配置,定义 binder,和 bingings

server:
  port: 9000
spring:
  cloud:
    stream:
      # 定义绑定器,绑定到哪个消息中间件上
      binders:
        itheima_binder: # 自定义的绑定器名称
          type: rabbit # 绑定器类型
          environment: # 指定mq的环境
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
                virtual-host: /
      bindings:
        output: # channel名称
          binder: itheima_binder #指定使用哪一个binder
          destination: itheima_exchange # 消息目的地

3 定义消息接收业务类。添加 @EnableBinding(Sink.class),使用
@StreamListener(Sink.INPUT),完成消息接收.

  package com.cf.stream.consumer;
  
  import org.springframework.cloud.stream.annotation.EnableBinding;
  import org.springframework.cloud.stream.annotation.StreamListener;
  import org.springframework.cloud.stream.messaging.Sink;
  import org.springframework.messaging.Message;
  import org.springframework.stereotype.Component;
  
  /**
   * 消息接收类
   */
  @EnableBinding({
    
    Sink.class})
  @Component
  public class MessageListener {
    
    
  
      @StreamListener(Sink.INPUT)
      public void receive(Message message){
    
    
  
          System.out.println(message);
          System.out.println(message.getPayload());
      }
  }

4 编写启动类,测试.

5 Sleuth+Zipkin

5.1 Sleuth+Zipkin-概述

• Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数
据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
• 耗时分析
• 可视化错误
• 链路优化
• Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。

5.2 Sleuth+Zipkin-入门

  • 安装启动zipkin。 java –jar zipkin.jar
  • 访问zipkin web界面。 http://localhost:9411/

-在服务提供方和消费方分别引入 sleuth 和 zipkin 依赖

        <!-- sleuth-zipkin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
  • 分别配置服务提供方和消费方的application.yml
    • sleuth-provider application.yaml
server:
  port: 8001

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: feign-provider
  zipkin:
    base-url: http://localhost:9411/  # 设置zipkin的服务端路径

  sleuth:
    sampler:
      probability: 1 # 采集率 默认 0.1 百分之十。
  • sleuth-consumer application.yaml
server:
  port: 9000


eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: feign-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
  zipkin:
    base-url: http://localhost:9411/  # 设置zipkin的服务端路径

  sleuth:
    sampler:
      probability: 1 # 采集率 默认 0.1 百分之十。
logging:
  level:
    com.itheima: debug
  • 启动,测试 http://localhost:9411/

猜你喜欢

转载自blog.csdn.net/ABestRookie/article/details/108305698