最近看《深入理解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 注解
首先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界面
之所以写这个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); }相关配置文件
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网关的搭建
整合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