最近看《深入理解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