Micro current level of service so popular, if you can not learn a micro-service framework technology. How can promotion and pay rise, increasing the chips resume? spring cloud and Dubbo to learn alone. That there is no time? No energy? To learn both a framework? The Spring Cloud alibaba you only need to learn a'll have two kinds of micro-technology service management framework. why not? Come on! Sao ape years
Before the zuul we talk about it. How to get dynamic routing. As the son of pro-exist Spring Cloud gateway could not support dynamic routing. Preliminary Today we look at the dynamic routing gateway.
Demand front. In the understanding of the dynamic routing. You might be able to expect our data to be stored in a database or redis them. There are also stored in the entity classes.
Thinking:
配置中心刷新routes配置信息。路由信息刷新改变。利用事件发布,利用配置中心完成动态刷新路由。本次改造我们使用自定义存储方式达到手动触发动态路由
InMemoryRouteDefinitionRepository 默认使用。这个类就是把握们当前的所有的路由routes 存储在内存当中。当服务重启或者刷新,内存就不复存在。ps: 因为本项目是用nacos 注册中心也是配置中心。可以存储在nacos 配置中心里面。
RouteDefinitionRepository 接口是InMemoryRouteDefinitionRepository 是它的接口类 继承了 RouteDefinitionLocator 、RouteDefinitionWriter俩个接口。
RouteDefinitionLocator Interface
RouteDefinitionWriter used to implement add and delete routes.
Thinking:
基于这个原则我们在动态添加或者删除路由的时候,就可以根据这个接口实现去满足我们动态的控制路由规则。
RouteDefinitionRepository This interface has become the key point we have to re-routing is actually based on the dynamic interface to achieve
Entity class
package com.xian.cloud.model;
import lombok.Data;
/**
* @Author: xlr
* @Date: Created in 5:10 PM 2019/9/29
*/
@Data
public class GatewayRoutesEntity {
private Long id;
private String serviceId;
private String uri;
private String predicates;
private String filters;
}
GatewayRoutesService Interface
package com.xian.cloud.service;
import com.xian.cloud.model.GatewayRoutesEntity;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import java.util.List;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 16:08
*/
public interface GatewayRoutesService {
List<GatewayRoutesEntity> findAll() throws Exception;
String loadRouteDefinition() throws Exception;
GatewayRoutesEntity save(GatewayRoutesEntity gatewayDefine) throws Exception;
void deleteById(String id) throws Exception;
boolean existsById(String id)throws Exception;
List<PredicateDefinition> getPredicateDefinition(String predicates) ;
List<FilterDefinition> getFilterDefinition(String filters) ;
}
GatewayRoutesService implementation class
package com.xian.cloud.service.impl;
import com.alibaba.fastjson.JSON;
import com.xian.cloud.model.GatewayRoutesEntity;
import com.xian.cloud.service.GatewayRoutesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.List;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 16:09
*/
@Service
@Slf4j
public class GatewayRoutesServiceImpl implements GatewayRoutesService {
public static final String GATEWAY_DEFINE_LIST_KEY = "gateway_routes_list_key";
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
@Override
public List <GatewayRoutesEntity> findAll() throws Exception {
Long size = redisTemplate.opsForList().size( GATEWAY_DEFINE_LIST_KEY );
List<GatewayRoutesEntity> list = redisTemplate.opsForList().range( GATEWAY_DEFINE_LIST_KEY, 0, size );
return list;
}
@Override
public String loadRouteDefinition() {
try {
List <GatewayRoutesEntity> gatewayDefineServiceAll = findAll();
if (gatewayDefineServiceAll == null) {
return "none route defined";
}
for (GatewayRoutesEntity gatewayDefine : gatewayDefineServiceAll) {
RouteDefinition definition = new RouteDefinition();
definition.setId( gatewayDefine.getServiceId() );
definition.setUri( new URI( gatewayDefine.getUri() ) );
List <PredicateDefinition> predicateDefinitions = getPredicateDefinition(gatewayDefine.getPredicates());
if (predicateDefinitions != null) {
definition.setPredicates( predicateDefinitions );
}
List <FilterDefinition> filterDefinitions = getFilterDefinition(gatewayDefine.getFilters());
if (filterDefinitions != null) {
definition.setFilters( filterDefinitions );
}
routeDefinitionWriter.save( Mono.just( definition ) ).subscribe();
publisher.publishEvent( new RefreshRoutesEvent( this ) );
}
return "success";
} catch (Exception e) {
e.printStackTrace();
return "failure";
}
}
/**
* 获取所有的 自定义路由规则
* @param gatewayDefine
* @return
* @throws Exception
*/
@Override
public GatewayRoutesEntity save(GatewayRoutesEntity gatewayDefine) throws Exception {
log.info( "save RouteDefinition : {}",gatewayDefine );
redisTemplate.opsForList().rightPush( GATEWAY_DEFINE_LIST_KEY, gatewayDefine );
return gatewayDefine;
}
@Override
public void deleteById(String id) throws Exception {
List <GatewayRoutesEntity> all = findAll();
for (GatewayRoutesEntity gatewayDefine : all) {
if(gatewayDefine.getServiceId().equals( id )){
redisTemplate.opsForList().remove( GATEWAY_DEFINE_LIST_KEY,0, gatewayDefine);
}
}
}
@Override
public boolean existsById(String id) throws Exception {
List <GatewayRoutesEntity> all = findAll();
for (GatewayRoutesEntity gatewayDefine : all) {
if(gatewayDefine.getServiceId().equals( id )){
return true;
}
}
return false;
}
@Override
public List<PredicateDefinition> getPredicateDefinition(String predicates) {
if ( StringUtils.isNotBlank( predicates )) {
List<PredicateDefinition> predicateDefinitionList = JSON.parseArray(predicates, PredicateDefinition.class);
return predicateDefinitionList;
} else {
return null;
}
}
@Override
public List<FilterDefinition> getFilterDefinition(String filters) {
if (StringUtils.isNotBlank( filters )) {
List<FilterDefinition> filterDefinitionList = JSON.parseArray(filters, FilterDefinition.class);
return filterDefinitionList;
} else {
return null;
}
}
}
Then we conduct RouteDefinitionLocator, RouteDefinitionWriter both a declaration in the interface configuration file
package com.xian.cloud.config;
import com.xian.cloud.repository.GatewayRoutesRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* <Description> 动态更新路由
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 17:12
*/
@Configuration
@Slf4j
public class GatewayRoutesDefinitionConfig {
@Bean
RouteDefinitionLocator routeDefinitionLocator(){
return new GatewayRoutesRepository();
}
@Bean
@Primary
RouteDefinitionWriter routeDefinitionWriter(){
return new GatewayRoutesRepository();
}
}
RefreshRoutesEvent events publishing refresh routes event notification gateway. This event is the gateway event.
package com.xian.cloud.event;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 17:20
*/
@Component
@Slf4j
public class RefreshRouteService implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
/**
* 刷新路由表
*/
public void refreshRoutes() {
publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
Then we are still a manual trigger interface, create GatewayRoutesController
package com.xian.cloud.controller;
import com.xian.cloud.event.RefreshRouteService;
import com.xian.cloud.model.RestResult;
import com.xian.cloud.model.RestResultBuilder;
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.RestController;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 17:18
*/
@RestController
@RequestMapping("/gateway")
public class GatewayRoutesController {
@Autowired
private RefreshRouteService refreshRouteService;
@GetMapping("/refreshRoutes")
public RestResult refreshRoutes(){
refreshRouteService.refreshRoutes();
return RestResultBuilder.builder().success().build();
}
}
So far, all the code is complete.
Start Service
In fact, there is a very simple and direct wording. Reference to redefine Spring Cloud combat the wording.
Create an event to increase class DynamicRouteServiceImpl
package com.xian.cloud.event;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/09 10:40
*/
@Slf4j
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
@Qualifier("routeDefinitionRepositor")
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
/**
* 添加路由实体类
* @param definition
* @return
*/
public boolean add(RouteDefinition definition){
routeDefinitionWriter.save((Mono<RouteDefinition>) Mono.just(definition).subscribe());
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return true;
}
/**
*
* @param definition 路由实体类
* @return
*/
public boolean update(RouteDefinition definition){
try {
routeDefinitionWriter.delete(Mono.just(definition.getId()));
}catch (Exception e){
log.error("update 失败。没有找到对应的路由ID :{}",definition.getId());
}
routeDefinitionWriter.save((Mono<RouteDefinition>) (Mono.just(definition)).subscribe());
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return true;
}
/**
* serviceId
* @param id
* @return
*/
public boolean del(String id){
routeDefinitionWriter.delete(Mono.just(id));
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return true;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}
Add three methods to modify controller
package com.xian.cloud.controller;
import com.xian.cloud.event.DynamicRouteServiceImpl;
import com.xian.cloud.event.RefreshRouteService;
import com.xian.cloud.model.RestResult;
import com.xian.cloud.model.RestResultBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.web.bind.annotation.*;
/**
* <Description>
*
* @author [email protected]
* @version 1.0
* @createDate 2019/11/08 17:18
*/
@RestController
@RequestMapping("/gateway")
public class GatewayRoutesController {
@Autowired
private RefreshRouteService refreshRouteService;
@Autowired
private DynamicRouteServiceImpl dynamicRouteService;
@GetMapping("/refreshRoutes")
public RestResult refreshRoutes(){
refreshRouteService.refreshRoutes();
return RestResultBuilder.builder().success().build();
}
/**
*
* @param definition
* @return
*/
@RequestMapping(value = "routes/add",method = RequestMethod.POST)
public RestResult add(@RequestBody RouteDefinition definition){
boolean flag = dynamicRouteService.add(definition);
if(flag){
return RestResultBuilder.builder().success().build();
}
return RestResultBuilder.builder().failure().build();
}
/**
*
* @param definition
* @return
*/
@RequestMapping(value = "routes/update",method = RequestMethod.POST)
public RestResult update(@RequestBody RouteDefinition definition){
boolean flag = dynamicRouteService.add(definition);
if(flag){
return RestResultBuilder.builder().success().build();
}
return RestResultBuilder.builder().failure().build();
}
/**
*
* @param serviceId
* @return
*/
@RequestMapping(value = "routes/del",method = RequestMethod.POST)
public RestResult update(@RequestParam("serviceId") String serviceId){
boolean flag = dynamicRouteService.del(serviceId);
if(flag){
return RestResultBuilder.builder().success().build();
}
return RestResultBuilder.builder().failure().build();
}
}
Additions and deletions. Three interfaces of external exposure.
These are dynamic refresh the routing gateway.
Think
Dynamic refresh to meet us in the service management to facilitate operation and maintenance. But because this whole nacos distribution center used to do. Consider the cost of doing so. Dynamic refresh is not really necessary to do so. Configuration can then refresh in the configuration center. You can trigger overall refresh route. If you need to build your own operation and maintenance center. It has its own management system enables dynamic routing.
Taken reference spring cloud official documents
Nacos server address http://47.99.209.72:8848/nacos
Past addresses spring cloud article addresses
Spring Cloud Alibaba (nacos registration center set up)
Spring Cloud Alibaba use nacos registry
Spring Cloud Alibaba nacos configuration centers
Spring Cloud zuul a gateway service
Spring Cloud Gateway Services zuul two
Spring Cloud Gateway Services zuul three dynamic routing
Spring Cloud alibaba gateway sentinel zuul four current-limiting fuse
Spring Cloud gateway gateway services a
Spring Cloud gateway gateway service two assertions, filter
Spring Cloud gateway three custom filter GatewayFilter
How like you can share this concern public number.
Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement. Reprinted please include public two-dimensional code number