基于springboot2.1.4springcloudGreenwich版本中整合 网关gateway实现服务链路追踪Spring Cloud Sleuth集成ZipKin实现

    xiaoxiao2022-07-03  115

     

           最近看《深入理解Spring Cloud微服务构建》是一书之中,发现书中所讲网关是Zuul实现的,由于笔者学习的版本基本上是在spring5.0,springboot2.0以上实现,进而发现了spring官方网关gateway ,因此替代了书中所用Zuul网关,想知道gateway网关和Zuul区别的,网上自行查阅即可。

    话不多说 上demo 结构目录

    由上而下依次是 eureka服务端,feign,网关服务,user-service,sleuth zipkin链路追踪服务端,

    整个核心流程图大概如下

    请求首先经过网关  gateway   ----A----> feign   ----B---- > user-service

    A:  gateway从eureka-server列表里面拿到server_id再分发请求)

    B:  feign得到请求后 执行到feignclient,发现feignclient调用了user-service ,则feign再通过eureka-server去具体得到

          user-service再去访问。

    zipkin-server 监听跟踪该请求的每个服务的响应情况,zipkin可采用http形式上传消息,也可用rabbitmq ,kafka等。

    都是基于springboot2.1.4版本,springcloud Greenwich 版本 ,笔者的上一篇博客《spring cloud Bus 代理 rabbitMQ 自动刷新配置》也是基于该版本,不过忘记贴入pom依赖,再次全部贴出

    <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> <zipkin-server.version>2.11.4</zipkin-server.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

    1 eureka-server eureka服务端

        eureka的搭建,话不多说

        pom依赖

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

       resources 下面application.yml配置

    server: port: 8761 eureka: instance: hostname: localhost client: register-with-eureka: false fetch-registry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ spring: application: name: eureka-server

      启动类上加入   @EnableEurekaServer  注解

     2 zipkin-server  链路追踪的服务端

     首先poml引入相关zipkin的依赖

    <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 链路追踪的依赖服务 采用http上传的模式,也可采用RabbitMq kafka来传输--> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <version>${zipkin-server.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </exclusion> </exclusions> </dependency> <!-- zipkinServer的ui依赖界面--> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>${zipkin-server.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> </dependencies>

       在application.yml里面写入相关配置

    server: port: 9411 spring: application: name: zipkin-server #允许bean被重写 main: allow-bean-definition-overriding: true eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ #zipkin的ui界面配置 management: metrics: web: server: auto-time-requests: false

       在启动类上面加入  @EnableEurekaClient   @EnableZipkinServer 注解表示开启eureka客户端 ,链路追踪服务端

       此时zipkin-serve 搭建完毕在浏览器访问 http://localhost:9411  会发现如下ui界面

     3 feign-client  

       之所以写这个model其实也就是为了复习一下feign组件,并且gateway网关model去请求调用feign 再由feign去转发调用user-service model

      pom依赖

    <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 开启监控中心--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 使用Hystrix dashboard 监控熔断器状态,配合上面actuator使用 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <!-- feign自带的hystrix并不是启动依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 引入eureka 客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 被zipkin服务追踪的启动依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> </dependencies>

       资源文件配置

    eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ server: port: 8762 spring: application: name: feign-client #链路服务的地址 zipkin: base-url: http://localhost:9411 #被追踪的可能性,默认是0.1 表示百分之10 sleuth: sampler: probability: 1.0 #开启hystrix服务保护熔断降级 feign: hystrix: enabled: true #开启全局监控 management: endpoints: web: exposure: include: "*"

      在启动类上加入相关的注解

     在启动类同包下新建controller services  feignclient三个包

    新建UserController.java文件

    import com.example.userservice.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/hi") public String hi(@RequestParam("name") String name){ return userService.sayHi(name); } }

      UserService.java文件

    import com.example.userservice.feignclient.UserFeignClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserFeignClient userFeignClient; public String sayHi(String name){ return userFeignClient.sayHi(name); } }

     UserFeignClient.java文件

    import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; /** * @FeignClient 是一个请求的feign调用客户端 * value 表示请求的相关的server_id 暴露到eureka里面的 * path 是请求的相关路径 * contextId 表示相关的feign client模块 * */ @FeignClient(value ="user-service",path = "/user",contextId = "userFeignClient") public interface UserFeignClient { @GetMapping(value = "/hi") String sayHi(@RequestParam("name") String name); }

    4  user-service  测试的service model

    <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 被zipkin服务追踪的启动依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <!-- web应用 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>

     相关配置文件

    server: port: 8763 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: user-service sleuth: sampler: probability: 1.0 zipkin: base-url: http://localhost:9411

       启动类上加入  @EnableEurekaClient 注解,在同包下新建controller包,并且新建 UserController.java,为了方便直接输出

    import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @Value("${server.port}") String port; @GetMapping("/hi") public String home (@RequestParam String name) { return "hi "+name+", i am port :"+port; } }

      此时启动完毕之后 依次启动eureka ,zipkin ,feign ,user-service

      在浏览器输入 http://localhost:8762/user/hi?name=hello world   会发现输出

    此时重新进入刚才打开的zipkin的UI界面  点击find Traces 会发现有服务跟踪,自此本文已经实现了链路跟踪

     点击导航栏的dependencies 会发现链路跟踪的相关服务依赖 

      很显然,在实际开发过程中我们会有很多很多服务,在目前前后端分离的主流情况下,前台不会记住后端每个服务的具体请求路径,很显然这就需要网关来帮助我们进行请求的统一分发,并且网关不仅仅只有这点重用,还有身份验证,过滤请求,服务器保护,服务限流,防止攻击,黑白名单的配置  等作用,在下期博客中,会写入使用JWT来进行身份校验和过滤不合法请求,很显然网关必不可少,所以进入下面 gateway网关的搭建

    5 gateway-server 网关的搭建 

      整合demo的请求逻辑见上,现在搭建网关pom.xml

    <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 引入eureka 客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- 被zipkin服务追踪的启动依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> </dependencies>

       配置文件

    spring: cloud: gateway: # gateway 运行从注册中心发现服务 discovery: locator: enabled: true #服务serviceId不分区大小写 lowerCaseServiceId: true routes: #网关路由的转发 lb:// 表示是从注册中心发现serviceId - id: feign-client uri: lb://feign-client predicates: - Path=/feign-client/** filters: - StripPrefix=1 application: name: gateway-server sleuth: sampler: probability: 1.0 zipkin: base-url: http://localhost:9411 server: port: 5000 feign: hystrix: enabled: true logging: level: org.springframework.cloud.gateway: debug

       启动gateway 

        

       浏览器上面请求 http://localhost:5000/feign-client/user/hi?name=hello world  

       请求结果和直接请求feign一样 ,但是比对url会发现该请求是从网关分发的,如果你不信,觉得我再胡说,那我们去看服务跟踪

       链路跟踪界面上点击find traces 会发现刚才请求的服务已经被跟踪到

       接着点击跟踪traces  会发现每一个服务处理耗时

       

     

       同时点击依赖会发现    会发现依赖关系图

     

     自此,本章博客结束 ,如果有不正确的,欢迎在评论区中指正

      demo 源码地址      https://github.com/xzjayx/zipkin

    最新回复(0)