当前位置:网站首页>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 .
边栏推荐
- Zhongshanshan: engineers after being blasted will take off | ONEFLOW u
- Is education important or ability important in software testing
- mysql高级学习(跟着尚硅谷老师周阳学习)
- Sixtool- source code of multi-functional and all in one generation hanging assistant
- 2022.2.13
- Use shell script to analyze system CPU, memory and network throughput
- 5. <tag-栈和常规问题>补充: lt.946. 验证栈序列(同剑指 Offer 31. 栈的压入、弹出序列)
- Create a binary response variable using the cut sub box operation
- 202.2.9
- PHP installation SSH2 extension
猜你喜欢

Yolov5 super parameter setting and data enhancement analysis

Image translation /gan:unsupervised image-to-image translation with self attention networks

UWB超高精度定位系统原理图

1.18 learning summary

A new paradigm for large model application: unified feature representation optimization (UFO)

MySql如何删除所有多余的重复数据

Créateur de génie: cavalier solitaire, magnat de la technologie et ai | dix ans d'apprentissage profond

Database design (I)

Zhimeng CMS will file a lawsuit against infringing websites

图像翻译/GAN:Unsupervised Image-to-Image Translation with Self-Attention Networks基于自我注意网络的无监督图像到图像的翻译
随机推荐
numpy 索引及切片
JWT token authentication verification
1.13 learning summary
Motivational skills for achieving goals
1.11 learning summary
MySql如何删除所有多余的重复数据
1.21 learning summary
Be a hard worker from today on
企业的产品服务怎么进行口碑营销?口碑营销可以找人代做吗?
Large numbers (C language)
LeetCode 94. Middle order traversal of binary tree
Text horizontal alignment attribute text align and element vertical alignment attribute vertical align
Comment enregistrer une image dans une applet Wechat
Create a binary response variable using the cut sub box operation
2020-12-18
Jenkins introduces custom jars
Nabicat connection: local MySQL & cloud service MySQL and error reporting
Simple use of redis in laravel
Install Damon database
Multipass中文文档-与实例共享数据