当前位置:网站首页>Zuul implements dynamic routing
Zuul implements dynamic routing
2022-06-26 04:53:00 【Hejjon】
demand :SpringCloud Integrate zuul route , Realize the modification in the database serviceId Field to switch the calling service . for example : Suppose in the local environment ,zuul The running port of is 8081. Now there is ServiceA, ServiceB In normal operation , stay zuul The routing addresses configured in are /service-a/** and /service-b/** . Now access A, The access address can be written as http://localhost:8081/service-a/xxx. Now I want to change the routing table in the database serviceId, Make the original access service A To access B Service .
The implementation steps are as follows :
1. build zuul project
1.1 Import dependence
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>1.2 Core code
Custom routing processor is the core of dynamic routing , Need to inherit
org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator class
And the implementation org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator Interface
package com.atguigu.springcloud.filter;
import com.atguigu.springcloud.entity.ZuulRouteEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Created by caoshi at 21:21 2022-05-04
*/
public class CustomRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
private static Logger logger = LoggerFactory.getLogger(CustomRouteLocator.class);
private JdbcTemplate jdbcTemplate;
private ZuulProperties properties;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public CustomRouteLocator(String servletPath, ZuulProperties properties) {
super(servletPath, properties);
this.properties = properties;
logger.info("servletPath:{}", servletPath);
}
@Override
public void refresh() {
doRefresh();
}
@Override
protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<>();
routesMap.putAll(super.locateRoutes());
routesMap.putAll(locateRoutesFromDB());
Map<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
for (Map.Entry<String, ZuulProperties.ZuulRoute> entry : routesMap.entrySet()) {
String path = entry.getKey();
if (!path.startsWith("/")) {
path = "/" + path;
}
if (StringUtils.hasText(this.properties.getPrefix())) {
path = this.properties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
}
values.put(path, entry.getValue());
}
return values;
}
private Map<String, ZuulProperties.ZuulRoute> locateRoutesFromDB() {
logger.info("============= Start loading db Routing table configuration ==============");
Map<String, ZuulProperties.ZuulRoute> routes = new LinkedHashMap<>();
try {
List<ZuulRouteEntity> results =
this.jdbcTemplate.query("select * from x_gw_route where enabled = 1",
new BeanPropertyRowMapper<>(ZuulRouteEntity.class));
for (ZuulRouteEntity result : results) {
if (StringUtils.isEmpty(result.getPath())) {
continue;
}
ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
copy2ZuulRoute(result, zuulRoute);
routes.put(zuulRoute.getPath(), zuulRoute);
}
} catch (DataAccessException e) {
logger.error("============= load db Error in the configuration of the middle routing table ==============", e);
}
return routes;
}
/**
*
* @param zuulRouteEntity
* @param zuulRoute
*/
private void copy2ZuulRoute(ZuulRouteEntity zuulRouteEntity, ZuulProperties.ZuulRoute zuulRoute) {
if (zuulRouteEntity == null || zuulRoute == null) {
return;
}
zuulRoute.setId(zuulRouteEntity.getId());
zuulRoute.setServiceId(zuulRouteEntity.getService_id());
zuulRoute.setPath(zuulRouteEntity.getPath());
zuulRoute.setStripPrefix(zuulRouteEntity.getStrip_prefix() == 1);
zuulRoute.setUrl(zuulRouteEntity.getUrl());
zuulRoute.setRetryable(zuulRouteEntity.getRetryable() == 1);
}
}
Routing table mapping entity class :
package com.atguigu.springcloud.entity;
/**
* Created by caoshi at 20:53 2022-06-16
*/
public class ZuulRouteEntity {
private String id; // Primary key id
private String path; // Access path /xxx/**
private String service_id; // service id It's usually made into spring.application.name
private String url; //
private int strip_prefix; // Whether to remove the prefix ,zuul Own prefix /zuul, So set it to 1 Is to remove the prefix
private int retryable; // Whether to re request after failure
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getService_id() {
return service_id;
}
public void setService_id(String service_id) {
this.service_id = service_id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getStrip_prefix() {
return strip_prefix;
}
public void setStrip_prefix(int strip_prefix) {
this.strip_prefix = strip_prefix;
}
public int getRetryable() {
return retryable;
}
public void setRetryable(int retryable) {
this.retryable = retryable;
}
}
Configuration class , To configure CustomRouteLocator Leave it to Spring Container management .
package com.atguigu.springcloud.config;
import com.atguigu.springcloud.filter.CustomRouteLocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Created by caoshi at 20:51 2022-06-16
*/
@Configuration
public class CustomZuulConfig {
private static Logger logger = LoggerFactory.getLogger(CustomZuulConfig.class);
private ZuulProperties zuulProperties = new ZuulProperties();
@Autowired
private ServerProperties server;
@Autowired
private JdbcTemplate jdbcTemplate;
@Bean
public CustomRouteLocator routeLocator() {
String contextPath = server.getServlet().getContextPath();
logger.info("=========== servlet contextPath {}", contextPath);
CustomRouteLocator routeLocator = new CustomRouteLocator(contextPath, zuulProperties);
routeLocator.setJdbcTemplate(jdbcTemplate);
return routeLocator;
}
}
Database routing table structure
CREATE TABLE `x_gw_route` (
`id` varchar(50) NOT NULL COMMENT ' Primary key ',
`path` varchar(255) NOT NULL COMMENT ' Access path ',
`service_id` varchar(50) DEFAULT NULL COMMENT ' service id',
`url` varchar(255) DEFAULT NULL,
`retryable` tinyint(1) DEFAULT NULL COMMENT ' Whether to re request after failure 1 yes 0 no ',
`enabled` tinyint(1) NOT NULL COMMENT ' Whether to use 1 normal 0 Don't use ',
`strip_prefix` int(11) DEFAULT NULL COMMENT ' Whether to remove the prefix 1 yes 0 no ',
`api_name` varchar(255) DEFAULT NULL COMMENT ' The service name ',
`c_desc` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT ' describe ',
`c_createuserid` varchar(60) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT ' Create user id',
`c_createtime` datetime DEFAULT NULL,
`c_updateuserid` varchar(60) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT ' The last reviser id',
`c_updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;So far, the function of dynamic routing ,zuul The configuration of is complete .
If you want to implement request filtering , Like verification token Information, etc . Filters can be customized
package com.atguigu.springcloud.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
/**
* Created by caoshi at 22:43 2022-06-04
*/
@Component
public class AuthHeaderFilter extends ZuulFilter {
private static Logger logger = LoggerFactory.getLogger(AuthHeaderFilter.class);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
Object serviceIdKey = requestContext.get(FilterConstants.SERVICE_ID_KEY);
Object request_uri_key = requestContext.get(FilterConstants.REQUEST_URI_KEY);
System.out.println(serviceIdKey + " " + request_uri_key);
String servletPath = requestContext.getRequest().getServletPath();
System.out.println("servletPath = " + servletPath);
logger.info(" Gateway received routing request {} ", requestContext.getRequest().getRequestURI());
return null;
}
}
Can be rewritten run() Method , You can get it. RequestContext Object to filter requests .
Record on pit :
The default is in the routing table strip_prefix The value of the field is 0, Lead to zull The prefix will not be removed , and zuul It contains a prefix by default /zuul


This causes the prefix to be added to the actual request /zuul. And I set it on the controller method of the service provider The matching path does not contain Prefix /zuul Of , Therefore, the request fails , newspaper 404 error .
The final solution is In the routing table strip_prefix Set to 1, Means to remove the prefix .
边栏推荐
- Multipass Chinese document - use instance command alias
- 08_ Spingboot integrated redis
- 2.22.2.14
- 广和通联合安提国际为基于英伟达 Jetson Xavier NX的AI边缘计算平台带来5G R16强大性能
- 条件查询
- [H5 development] 03- take you hand in hand to improve H5 development - single submission vs batch submission with a common interface
- 0622 horse palm fell 9%
- Jenkins introduces custom jars
- 基础查询
- Multipass Chinese document - use packer to package multipass image
猜你喜欢

Database design (3): database maintenance and optimization

图像翻译/GAN:Unsupervised Image-to-Image Translation with Self-Attention Networks基于自我注意网络的无监督图像到图像的翻译

1.24 learning summary

Essential foundation of programming - Summary of written interview examination sites - computer network (1) overview

2022.2.11

File upload and security dog

1.16 learning summary

ROS notes (07) - Implementation of client and server

天才制造者:獨行俠、科技巨頭和AI|深度學習崛起十年

How to carry out word-of-mouth marketing for enterprises' products and services? Can word of mouth marketing be done on behalf of others?
随机推荐
Astype conversion data type
记录一次循环引用的问题
What is the best way to store chat messages in a database? [Close] - best way to store chat messages in a database? [closed]
A new paradigm for large model application: unified feature representation optimization (UFO)
Nabicat连接:本地Mysql&&云服务Mysql以及报错
Svn error command revert error previous operation has not finished; run ‘ cleanup‘ if
dijkstra
0622 horse palm fell 9%
2022 talent strategic transformation under the development trend of digital economy
numpy 随机数
DBeaver 安装及配置离线驱动
Numpy general function
numpy 索引及切片
torchvision_transform(图像增强)
1.12 learning summary
Zhongshanshan: engineers after being blasted will take off | ONEFLOW u
#微信小程序# 在小程序里面退出退出小程序(navigator以及API--wx.exitMiniProgram)
How to use the configured slave data source for the scheduled task configuration class scheduleconfig
Problem follow up - PIP source change
Créateur de génie: cavalier solitaire, magnat de la technologie et ai | dix ans d'apprentissage profond