• 七、Gateway高可用集群与动态网关


    基于Nginx部署GateWay集群

    网关集群可以通过Nginx与lvs实现,这里基于Nginx,实现比较简单。为nginx添加如下配置即可

    upstream gateways {
    	server 127.0.0.1:81;
    	server 127.0.0.1:82;
    }
    
    server {
    	listen       80;
    	server_name  localhost;
    	logs/host.access.log  main;
    
    ...
    
    	location / {
    		proxy_pass http://gateways/;
    	}
    	...
    }
    

    动态网关

    任何配置不用重启网关服务器都可以实现及时刷新网关配置。

    实现方式:

    1. 分布式配置中心,不推荐
    2. 数据库,推荐,阅读性好

    根据路由的相关配置,我们设计数据库表结构

    CREATE TABLE `gateway_route`  (
       `id` int(11) primary key,
      `route_id` varchar(255) DEFAULT NULL,#路由id
      `route_name` varchar(255) DEFAULT NULL,
      `route_pattern` varchar(255) DEFAULT NULL,#路径匹配规则
      `route_type` varchar(255) DEFAULT NULL,#跳转类型,0时从注册中心获取地址,1直接跳转网络地址
      `route_uri` varchar(255) DEFAULT NULL #与route_type相对应的地址
    )
    

    插入如下的路由信息,member-service是注册中心上的服务,可替换成自己的

    根据数据库设计实体类

    public class GateWayEntity {
        private Long id;
        private String routeId;
        private String routeName;
        private String routeType;
        private String routeUri;
        private String routePattern;
       ...
    }
    

    因为要从数据库获取路由信息,这里使用mybatis来访问数据库,接口如下

    @Mapper
    public interface GatewayRouteMapper {
    	//获取全部路由
        List<GateWayEntity> getAllRoutes();
    }
    

    对应xml如下

    <resultMap id="GateWay" type="com.github.zyq.entity.GateWayEntity">
        <id column="id" property="id" ></id>
        <result column="route_id" property="routeId"></result>
        <result column="route_name" property="routeName"></result>
        <result column="route_type" property="routeType"></result>
        <result column="route_uri" property="routeUri"></result>
        <result column="route_pattern" property="routePattern"></result>
    </resultMap>
    
    <select id="getAllRoutes" resultMap="GateWay">
        select id,route_id,route_name,route_type,route_uri,route_pattern
        from gateway_route
    </select>
    

    重点便是加载路由信息了,创建一个类实现ApplicationEventPublisherAware接口

    @Service
    public class GatewayService implements ApplicationEventPublisherAware {
    
        private ApplicationEventPublisher publisher;
    
        @Autowired
        private RouteDefinitionWriter routeDefinitionWriter;
    
        @Autowired
        private GatewayRouteMapper gatewayRouteMapper;
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
            this.publisher = applicationEventPublisher;
        }
    
    
        //从数据库获取全部路由,在将每个路由加载
        public void getAllRoutes() {
            List<GateWayEntity> routes = gatewayRouteMapper.getAllRoutes();
            for (GateWayEntity route : routes) {
                loadRoute(route);
            }
        }
    	//根据实体类加载路由
        public String loadRoute(GateWayEntity gateWayEntity) {
            //路由相关的配置
            RouteDefinition routeDefinition = new RouteDefinition();
            PredicateDefinition predicateDefinition = new PredicateDefinition();
            FilterDefinition filterDefinition = new FilterDefinition();
    
            Map<String,String> predicateParams = new HashMap<>(8);
    
            URI uri = null;
            //根据路由类型来决定如何跳转
            if ("0".equals(gateWayEntity.getRouteType())) {
                uri  = UriComponentsBuilder.fromUriString("lb://"+gateWayEntity.getRouteUri()+"/").build().toUri();
            } else {
                uri = UriComponentsBuilder.fromHttpUrl(gateWayEntity.getRouteUri()).build().toUri();
            }
    
    
    
            //路由唯一id
            routeDefinition.setId(gateWayEntity.getRouteId());
            predicateDefinition.setName("Path");
            //路由转发地址
            predicateParams.put("pattern",gateWayEntity.getRoutePattern());
            predicateDefinition.setArgs(predicateParams);
    
    
            routeDefinition.setPredicates(Arrays.asList(predicateDefinition));
            routeDefinition.setUri(uri);
    
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
    
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "seccess";
        }
    

    每次路由更改时,只要访问一下数据库,将路由信息加载即可。书写一个controller,调用一下service的getAllRoutes方法加载路由。

    @RestController
    public class GateWayController {
    
        @Autowired
        private GatewayService gatewayService;
    
        @GetMapping("/load")
        public String loadRoutes() {
            gatewayService.getAllRoutes();
            return "success";
        }
    
    }
    

    访问一下/load路径加载路由信息,在route_pattern匹配的路径就能访问了,每次修改数据库的路由信息后,只要重新加载,就能够实现动态网关服务。

  • 相关阅读:
    day22 os模块
    开始 Dojo 开发
    Java 多线程编程
    Oracle 中常用数据字典大总结
    使用Java API的5个技巧
    Java 守护线程概述
    给Java新手的一些建议——Java知识点归纳(Java基础部分)
    消息中间件收录集
    2017年Java面试题整理
    Java 9 新特性快速预览
  • 原文地址:https://www.cnblogs.com/ylcc-zyq/p/13156526.html
Copyright © 2020-2023  润新知