【开发经验】gateway网关开发调试优先选择本地服务

背景
在微服务开发时,本地要启动太多的服务,比如基本服务,注册中心、网关、鉴权等等。还要启动当前代码所在的服务。这样,本地环境会特别卡,影响开发效率。

在这里插入图片描述
如下图所示:
在局域网内搭建一套开发环境,在开发时,这个开发环境启动的服务用来做“备胎”。
1.客户端访问的时候,携带自己想要优先访问的ip。
2.网关在转发时,发现客户端有想要优先访问的ip,则优先转发。

在整个微服务转发过程中,设计到进入网关时转发RPC调用时转发;此只介绍网关转发时锁定远程ip。
如果是dubbo调用时想锁定远程ip可参考文章dubbo多服务本地开发调试

代码思路

网关层面在进行服务选择时,肯定会加载所有的服务,然后根据随机、轮训、权重等规则进行分发。只要自定义自己的路由规则即可。新建远程锁定ip负载均衡类LockRemoteIpLoadBalancer.java


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.loadbalancer.core.*;
import org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class LockRemoteIpLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    private static final Log log = LogFactory.getLog(LockRemoteIpLoadBalancer.class);
    private static final String LockIp="lock-remote—ip";
    ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    final String serviceId;

    public LockRemoteIpLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.serviceId = serviceId;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
                .getIfAvailable(NoopServiceInstanceListSupplier::new);
        return supplier.get(request).next()
                .map(serviceInstances -> processInstanceResponse(supplier, serviceInstances, request));
    }

    private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,
                                                              List<ServiceInstance> serviceInstances,
                                                              Request request) {
        Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances, request);
        if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
            ((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
        }
        return serviceInstanceResponse;
    }

    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, Request request) {

        if (instances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + serviceId);
            }
            return new EmptyResponse();
        }
        int index = ThreadLocalRandom.current().nextInt(instances.size());

        ServiceInstance instance = instances.get(index);
        //锁定远程ip逻辑
        //在请求头添加想要访问的ip
        if (request instanceof DefaultRequest) {
            DefaultRequest defaultRequest = (DefaultRequest) request;
            if (defaultRequest.getContext() instanceof RequestDataContext) {
                RequestDataContext requestDataContext = (RequestDataContext) defaultRequest.getContext();
                HttpHeaders headers = requestDataContext.getClientRequest().getHeaders();
                if (headers.containsKey(LockIp)){
                    ServiceInstance lockIpInstance = this.chooseLockIpInstance(instances,headers.get(LockIp));
                    instance = lockIpInstance!=null?lockIpInstance:instance;
                }

            }
        }
        return new DefaultResponse(instance);
    }

    private ServiceInstance chooseLockIpInstance(List<ServiceInstance> instances, List<String> strings) {
        //获取想要访问的ip
        String ip = strings.get(0);
        // 循环所有服务器,查看是否有符合规则的服务
        for(ServiceInstance instance:instances){
            if(ip.equals(instance.getHost())){
                return instance;
            }
        }
        return null;
    }
}

添加配置类,选用自己的负责均衡规则

@Configuration
@LoadBalancerClients(
                                   //远程服务名称,比如订单服务、商品服务。如果哪个服务想要使用此规则,在这边添加即可
        @LoadBalancerClient(name = "order-application", configuration = GatewayConfig.class)
)
public class GatewayConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,
                                                                                   LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new LockRemoteIpLoadBalancer(
                loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}

然后在请求头添加如下:
lock-remote—ip:192.168.1.50
即可优先访问这个ip。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叁滴水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值