7、Gateway高可用集羣與動態網關

基於Nginx部署GateWay集羣

網關集羣能夠經過Nginx與lvs實現,這裏基於Nginx,實現比較簡單。爲nginx添加以下配置便可java

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/;
	}
	...
}

動態網關

任何配置不用重啓網關服務器均可以實現及時刷新網關配置。mysql

實現方式:nginx

  1. 分佈式配置中心,不推薦
  2. 數據庫,推薦,閱讀性好

根據路由的相關配置,咱們設計數據庫表結構git

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是註冊中心上的服務,可替換成本身的github

根據數據庫設計實體類sql

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方法加載路由。mybatis

@RestController
public class GateWayController {

    @Autowired
    private GatewayService gatewayService;

    @GetMapping("/load")
    public String loadRoutes() {
        gatewayService.getAllRoutes();
        return "success";
    }

}

訪問一下/load路徑加載路由信息,在route_pattern匹配的路徑就能訪問了,每次修改數據庫的路由信息後,只要從新加載,就可以實現動態網關服務。

相關文章
相關標籤/搜索