1.ZUUL静态路由的实现
1.1 示例微服务代码
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
yml
# 单个微服务端口
server:
port: 8090
controller
@RestController
@SpringBootApplication
public class ServiceExampleApplication {
@RequestMapping(value = "/hello")
public String available() {
System.out.println("Spring in Hello Service");
return "Spring in Hello Service";
}
public static void main(String[] args) {
SpringApplication.run(ServiceExampleApplication.class, args);
}
}
启动此示例微服务后:
1.2 zuul静态网关配置
另起一个工程
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
yml
server:
port: 1000
#配置在配置文件中的路由信息
zuul:
routes:
books:
path: /example/**
url: http://localhost:8090
主类添加注解:@EnableZuulProxy
通过zuul网关访问微服务:http://localhost:1000/example/hello
2.ZUUL动态路由的实现
原理:
使用源码的路由定位器:CompositeRouteLocator,最终使用的也是 DiscoveryClientRouteLocator
使用事件监听器,通过接口/定时发布事件,然后监听此事件,监听事件后调用compositeRouteLocator.refresh(); 来刷新自己定义的数据表中的路由
新建一个工程
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<!--JDBC依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--MySQL依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- lombok依赖,减少 getter、setter 等方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
yml
server:
port: 10010
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
预定义路由数据表
create table zuul_route
(
id varchar(25) not null comment '表id(route id)'
primary key,
path varchar(25) not null comment '路由的路径,例子:/foo/**.',
service_id varchar(25) null comment '微服务ID,与url不能同时存在',
url varchar(255) null comment '要映射到路由的完整物理URL',
strip_prefix tinyint(1) default 1 null comment '默认为true,代理前缀默认会从请求路径中移除',
retryable tinyint(1) default 0 null comment '指示此路由应可重试(如果支持)的标志,需要服务ID和ribbon',
sensitive_headers set ('*') null comment '后为空或为*,允许所有信息传至后台,不拦截任何请求头信息'
)
comment 'zuul路由表' charset = utf8;
insert into zuul_route values ('1','/example/**',null,'http://localhost:8090',true,false,'*');
定义事件
public class ZuulRoutesRefreshedEvent extends ApplicationEvent {
private RouteLocator locator;
public ZuulRoutesRefreshedEvent(RouteLocator locator, Object source) {
super(source);
this.locator = locator;
}
public RouteLocator getLocator() {
return this.locator;
}
}
发布事件:手工调接口触发
@Slf4j
@RestController
public class ZuulRouteController {
@Autowired
RoutesPublishEventSevice publishService;
/**
* 手动调接口发布zuul动态路由事件
*
*/
@GetMapping("/zuulRouteRefresh")
public void zuulRoutePublish() {
log.info("[zuul动态路由] 手动触发接口发布事件");
publishService.publish();
}
}
发布事件:定时任务触发
@Slf4j
@Async // 表示是异步事件的定时任务
@Component
public class ScheduleZuulRoutesPublishEvent {
@Autowired
RoutesPublishEventSevice publishService;
@Scheduled(fixedRate = 5000)
public void schedulePublishEvent() {
log.info("[zuul动态路由] 定时任务, 定时发布事件时间:{}", LocalDateTime.now());
publishService.publish();
}
}
【发布事件】发布事件具体逻辑
@Slf4j
@Service
public class RoutesPublishEventImpl implements RoutesPublishEventSevice, ApplicationEventPublisherAware {
@Autowired
private CompositeRouteLocator compositeRouteLocator;
@Autowired
private ApplicationEventPublisher eventPublisher;
/**
* 发布动态路由事件
*/
@Override
public void publish() {
log.info("[zuul动态路由] 开始发布");
eventPublisher.publishEvent(new ZuulRoutesRefreshedEvent(compositeRouteLocator, this));
log.info("[zuul动态路由] 完成发布\n");
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
log.info("[zuul动态路由] 初始化启动时发布");
this.eventPublisher = applicationEventPublisher;
}
}
监听事件
【监听事件】定义事件监听器
@Slf4j
@Component
public class ZuulRefreshRoutesEventListener implements ApplicationListener<ZuulRoutesRefreshedEvent> {
@Autowired
DynamicRouteService dynamicRouteService;
@Override
public void onApplicationEvent(ZuulRoutesRefreshedEvent routesRefreshedEvent) {
if (routesRefreshedEvent.getSource() instanceof PublishRoutesEventImpl) {
dynamicRouteService.refreshRoutes();
}
}
}
【监听事件】刷新动态路由
@Slf4j
@Service
public class DynamicRouteServiceImpl implements DynamicRouteService, InitializingBean {
@Autowired
private CompositeRouteLocator compositeRouteLocator;
@Autowired
private ZuulProperties zuulProperties;
@Autowired
private ZuulRouteMapper zuulRouteMapper;
/**
* 刷新zuul路由
* 数据来源:
* 数据库zuul路由表
*/
@Override
public void refreshRoutes() {
//读取原配置文件的路由配置
Map<String, ZuulProperties.ZuulRoute> routes = zuulProperties.getRoutes();
//读取数据库zuul路由表配置
List<ZuulRouteModel> routeList = zuulRouteMapper.selectList(null);
//routeList数据并添加到routes中
routes.clear(); // 首先应清除原来路由信息,否则残留原来路由数据
for (ZuulRouteModel route : routeList) {
ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
zuulRoute.setId(route.getId());
zuulRoute.setPath(route.getPath());
zuulRoute.setServiceId(route.getServiceId());
zuulRoute.setUrl(route.getUrl());
zuulRoute.setStripPrefix(route.getStripPrefix());
zuulRoute.setRetryable(route.getRetryable());
// zuulRoute.setSensitiveHeaders(route.getSensitiveHeaders());
routes.put(route.getId(), zuulRoute);
}
//刷新zuul路由
zuulProperties.setRoutes(routes);
compositeRouteLocator.refresh();
log.info("[zuul动态路由] 刷新动态路由完成,现在的路由信息是:" + compositeRouteLocator.getRoutes());
}
/**
* 初始化路由信息
*/
@Override
public void afterPropertiesSet() {
this.refreshRoutes();
}
}
通过动态路由访问
http://localhost:10010/example/hello
该Demo源码下载地址:zuul-gateway-route.rar-Web开发文档类资源-优快云下载
https://download.youkuaiyun.com/download/yhn1992/75815426
有需要的可以下载学习参考