一、前言

在微服务项目的实际开发中,可能会存在多个程序员同学开发同一个项目的情况,此时,像gateway等网关服务会在Eureka或nacos这些注册中心中默认轮询的去访问各个ip的微服务,这是我们不想看到的,因为对方微服务的业务上没有实现我们需要的业务接口等,所以我们需要提醒一下gateway只访问自己的微服务。

二、具体实施

这里稍微多说两句: 简单介绍下吧,这个方法适用于所以基于Ribbon来实现负载均衡的网关或者请求工具,包括Ribbon本身和Fegin之类的一样可以使用。通过修改继承PredicateBasedRule这个抽象类来进行服务器的访问选择。

  1. 创建基本配置实体类,用于获取关键数据
/**
 * Ribbon 配置
 *
 * @author 李建
 */
@Getter
@Setter
@RefreshScope
@ConfigurationProperties("ribbon.rule")
@Component
public class RibbonRuleProperties {
    /**
     * 是否开启,默认:true
     */
    private boolean enabled = Boolean.TRUE;
    /**
     * 优先的ip列表,支持通配符,例如:10.20.0.8*、10.20.0.*
     * 
     */
    private List<String> priorIpPattern = new ArrayList<>();
}
  1. 继承【PredicateBasedRule】并重写 choose方法,过滤服务器ip,选择本地服务。
/**
 * ribbon路由过滤规则 优先本地主机服务
 * @Author 李建
 * @Date 2021/5/10 10:56
 * @Version 1.0
 **/
@Slf4j
public class LocalHostAwareRule extends PredicateBasedRule {

    @Autowired
    private RibbonRuleProperties ribbonRuleProperties;

    @Override
    public AbstractServerPredicate getPredicate() {
        return AbstractServerPredicate.alwaysTrue();
    }

    @Override
    public Server choose(Object key) {
        ILoadBalancer lb = getLoadBalancer();

        List<Server> allServers = lb.getAllServers();
        // 过滤服务列表
        List<Server> serverList = this.filterServers(allServers);

        return getPredicate().chooseRoundRobinAfterFiltering(serverList, key).orNull();
    }

    private List<Server> filterServers(List<Server> serverList) {
        List<String> priorIpPattern = ribbonRuleProperties.getPriorIpPattern();
        // 1. 查找本机ip,此处我用的是HuTool工具类,可以自己替换成相同功用的方法
        HostInfo hostInfo = SystemUtil.getHostInfo();
        String hostIp = hostInfo.getAddress();

        // 优先的 ip 规则
        boolean hasPriorIpPattern = !priorIpPattern.isEmpty();
        String[] priorIpPatterns = priorIpPattern.toArray(new String[0]);

        List<Server> priorServerList = new ArrayList<>();
        for (Server server : serverList) {
            String host = server.getHost();
            // 2. 优先本地ip的服务 某些服务使用主机名注册为host,所以要同时判断ip和主机名
            // 此处我用的是HuTool工具类,可以自己替换成相同功用的方法
            if (ObjectUtil.equal(hostIp, host) || ObjectUtil.equal(hostInfo.getName(), host)) {
                log.debug("[{}]请求转发至本地路由[{}]", hostInfo, host);
                return Collections.singletonList(server);
            }
            // 3. 优先的 ip 服务
            if (hasPriorIpPattern && PatternMatchUtils.simpleMatch(priorIpPatterns, host)) {
                priorServerList.add(server);
            }
        }

        // 4. 如果优先的有数据直接返回
        if (!priorServerList.isEmpty()) {
            return priorServerList;
        }

        return Collections.unmodifiableList(serverList);
    }
}
  1. 定义过滤规则
/**
 * Ribbon路由规则自动配置器
 * @Author 李建
 * @Date 2021/5/10 10:58
 * @Version 1.0
 **/
@Configuration
@RequiredArgsConstructor
//启用自定义的配置文件
@EnableConfigurationProperties(RibbonRuleProperties.class)
//一定要在ribbon默认的配置器之前加载
@AutoConfigureBefore(RibbonClientConfiguration.class)
//当ribbon.rule.enabled为false时不启用自定义过滤规则
@ConditionalOnProperty(value = "ribbon.rule.enabled", matchIfMissing = true)
public class RibbonRuleAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    //这里一定要配置为多例
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public PredicateBasedRule localHostAwareRule() {
        return new LocalHostAwareRule();
    }
}

完成以上三个类之后大概就是这么个样子的结构,给大家做个参考吧

在这里插入图片描述

  1. 这一步很重要,在yml中写出你本地微服务的ip以及其他配置
ribbon:
  rule:
   # 是否开启优先级ip策略
    enabled: true
    # 这里可以写多个ip
    prior-ip-pattern:
      - 172.16.156.219

完成。

喜欢的同学给个免费的点赞吧,Thanks♪(・ω・)ノ

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐