前奏

最近公司需求网关,就选择了zuul。就使用了一下,在这里记录下使用过程中,遇到的一些常见的
问题和用法。并且本次使用注册中心是基于zk,所以和大路上使用eureka是不同的,并且网上关于
使用zk的资料相对较少!鉴于spring cloud 已经不再持续,建议大家选择gateway。

pom依赖

<properties>
	<java.version>1.8</java.version>
	<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>

主要依赖:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.zookeeper</groupId>
	<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
	<groupId>com.101tec</groupId>
	<artifactId>zkclient</artifactId>
	<optional>true</optional>
</dependency>
<!-- 除此外还需要springboot web 、mysql、mybatis、lombok等依赖自行添加 -->

注册中心

application.properties

spring.cloud.zookeeper.connect-string=zk地址
spring.cloud.zookeeper.discovery.instance-port=${server.port}
zuul.host.connection-request-timeout-millis=3000
#spring.cloud.zookeeper.base-sleep-time-ms=10
#不向zookeeper注册
#spring.cloud.zookeeper.discovery.register=false
# retry
zuul.retryable=false

# 超时设置,url生效
zuul.host.connect-timeout-millis=10000
zuul.host.socket-timeout-millis=10000
# 超时设置,serviceId生效
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
ribbon.ReadTimeout=30000
ribbon.SocketTimeout=30000

zuul.add-host-header=true
zuul.strip-prefix=true

动态加载路由规则

实体对象:

@Data
public class ZuulRouteRule implements Serializable {
    /**
     * 主键ID
     */
    private Integer id;

    /**
     * 请求路径
     */
    private String path;

    /**
     * 服务提供者编码
     */
    private String serviceId;

    /**
     * 路由地址
     */
    private String url;

    /**
     * 是否增加前缀,0:否 1:是
     */
    private Boolean stripPrefix;

    /**
     * 是否重试, 0:否 1:是
     */
    private Boolean retryable;

    /**
     * 是否生效,0:生效 1:失效
     */
    private Boolean enabled;

    /**
     * 规则说明
     */
    private String description;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 创建人
     */
    private String createUser;

    /**
     * 更新时间
     */
    private Date updateTime;

    /**
     * 更新人
     */
    private String updateUser;

    private static final long serialVersionUID = 1L;
}

DAO层:

public interface ZuulRouteRuleMapper{
    List<ZuulRouteRule> queryZuulRulesByCondition(ZuulRouteRule param);
}

Service接口

public interface ZuulRouteRuleService {
    Map<String, ZuulProperties.ZuulRoute> getAllEnabledRules();
}
@Service
public class ZuulRouteRuleServiceImpl implements ZuulRouteRuleService {

    @Autowired
    private ZuulRouteRuleMapper zuulRouteRuleMapper;

    @Override
    public Map<String, ZuulProperties.ZuulRoute> getAllEnabledRules() {
        Map<String, ZuulProperties.ZuulRoute> routes = new LinkedHashMap<>();

        ZuulRouteRule param = new ZuulRouteRule();
        param.setEnabled(true);
        List<ZuulRouteRule> zuulRouteRuleList = zuulRouteRuleMapper.queryZuulRulesByCondition(param);
        zuulRouteRuleList.forEach(routeRule -> {
            if (StringUtils.isEmpty(routeRule.getPath())) {
                return;
            }
            ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
            BeanUtils.copyProperties(routeRule, zuulRoute);
            zuulRoute.setId(String.valueOf(routeRule.getId()));
            routes.put(zuulRoute.getPath(), zuulRoute);
        });
        return routes;
    }
}

动态路由加载

@Slf4j
public class DynamicZuulRouteLocator  extends SimpleRouteLocator implements RefreshableRouteLocator {

    private static final String SLASH = "/";

    @Autowired
    private ZuulProperties properties;

    @Autowired
    private ZuulRouteRuleService zuulRouteRuleService;

    public DynamicZuulRouteLocator(String servletPath, ZuulProperties properties) {
        super(servletPath, properties);
        this.properties = properties;
    }

    @Override
    public void refresh() {
        doRefresh();
    }

    @Override
    protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
        LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<>();
        routesMap.putAll(super.locateRoutes());
        Map<String, ZuulProperties.ZuulRoute> dbRoutesMap = zuulRouteRuleService.getAllEnabledRules();
        if(log.isInfoEnabled()){
            log.info("加载数据条目:{}",dbRoutesMap.size());
        }

        if (null != dbRoutesMap && !dbRoutesMap.isEmpty()) {
            routesMap.putAll(dbRoutesMap);
        }

        LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
        routesMap.forEach((key, value) -> {
            String path = key;
            if (!path.startsWith(SLASH)) {
                path = SLASH + path;
            }
            if (StringUtils.hasText(this.properties.getPrefix())) {
                path = this.properties.getPrefix() + path;
                if (!path.startsWith(SLASH)) {
                    path = SLASH + path;
                }
            }
            values.put(path, value);
        });
        return values;
    }
}

JavaConfig 加载bean

@Configuration
public class DynamicZuulConfig {

    @Bean
    public DynamicZuulRouteLocator routeLocator(ZuulProperties zuulProperties,ServerProperties serverProperties) {
        return new DynamicZuulRouteLocator(
                serverProperties.getServlet().getContextPath(), zuulProperties);
    }
}

springboot启动类:

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.demo.gateway.dao")
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Bean
    public AuthenticationFilter getAuthFilter(){
        return new AuthenticationFilter();
    }

}

自动刷新

定时刷新

@Configuration
@Slf4j
public class ScheduleZuulRulesListener implements ApplicationListener<ContextRefreshedEvent> {

    private static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

    @Autowired
    private ZuulHandlerMapping zuulHandlerMapping;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
        service.scheduleAtFixedRate(() -> {
            if(log.isInfoEnabled()) {
                log.info("刷新zuul配置信息开始");
            }
            try {
                zuulHandlerMapping.setDirty(true);
            } catch (Exception e) {
                log.error("刷新Zuul规则配置报错:{}",e.getMessage());
            }

            if(log.isInfoEnabled()) {
                log.info("刷新zuul配置信息结束");
            }
        },10,10,TimeUnit.SECONDS);

    }
}

其他服务集成网关

待补充

集成swagger

待补充

posted on 2019-07-04 23:21  菜码农先生  阅读(135)  评论(0编辑  收藏  举报