基于springCloud Gateway ,自定义路由规则的方式实现跨区域集群部署。
API 服务 指定 spring.cloud.consul.discovery.instanceZone参数指定 zone 注册到 consul
Oauth2ApiApplication server.port=9501;spring.cloud.consul.discovery.instanceZone=zone1
Oauth2ApiApplication-2 server.port=9502;spring.cloud.consul.discovery.instanceZone=zone2
Oauth2ApiApplication-3 server.port=9503;spring.cloud.consul.discovery.instanceZone=zone1
gateway 服务同样通过 指定 spring.cloud.consul.discovery.instanceZone参数指定 zone 从 consul 获取服务
Oauth2GatewayApplication server.port=8080;spring.cloud.consul.discovery.instanceZone=zone1
Oauth2GatewayApplication-2 server.port=8081;spring.cloud.consul.discovery.instanceZone=zone2
spring:
cloud:
gateway:
routes: #配置路由路径
- id: jxlg-gateway-api
uri: lb://jxlg-gateway-api
predicates:
- Path=/api/**
filters:
- StripPrefix=1
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能
lower-case-service-id: true #使用小写服务名,默认是大写
jxlg-gateway-api:
ribbon:
NFLoadBalancerRuleClassName: com.jxlg.gateway.server.config.GateWayLoadBalanceRule
GateWayLoadBalanceRule 参考 com.netflix.loadbalancer.RandomRule 实现一个随机获取的 方法 ,通过
spring.cloud.consul.discovery.instanceZone 对 zone 进行过滤,只路由到相同zone 的区域,后续可以扩展。
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;
import org.springframework.beans.factory.annotation.Value;
/**
* @author admin
* @date 2020/12/17 10:27
*/
public class GateWayLoadBalanceRule extends AbstractLoadBalancerRule {
@Value("${spring.cloud.consul.discovery.instanceZone}")
private String zone;
private static final Log log = LogFactory.getLog(GateWayLoadBalanceRule.class);
@Override
public Server choose(Object key) {
log.info("key is " + key);
List<Server> servers = this.getLoadBalancer().getReachableServers();
servers = servers.stream().filter(server -> zone.equals(server.getZone())).collect(Collectors.toList());;
log.info("servers " + servers);
if (servers.isEmpty()) {
return null;
}
if (servers.size() == 1) {
return servers.get(0);
}
return randomChoose(servers);
}
/**
*
* <p>随机返回一个服务实例 </p>
* @param servers 服务列表
*/
private Server randomChoose(List<Server> servers) {
int randomIndex = RandomUtils.nextInt(servers.size());
return servers.get(randomIndex);
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
api 接口 指定方式
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试接口
* Created by admin on 2020/12/09.
*/
@RestController
public class HelloController {
@Value("${spring.cloud.consul.discovery.instanceZone}")
private String zone;
@GetMapping("/hello")
public String hello() {
return "{\"zone\"=\"" + zone + "\"}";
}
}
使用 postman 测试,应用只会通过 gateway 路由到 相同 zone 区域下的应用。
来源:oschina
链接:https://my.oschina.net/zhongwenhao/blog/4812869