網關集羣能夠經過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
根據路由的相關配置,咱們設計數據庫表結構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匹配的路徑就能訪問了,每次修改數據庫的路由信息後,只要從新加載,就可以實現動態網關服務。