• openfeign、nacos获取接口提供方真实IP


    源码分析

    client 是 LoadBalancerFeignClient
    org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute

    public Response execute(Request request, Request.Options options) throws IOException {
    		try {
    			URI asUri = URI.create(request.url());
    			String clientName = asUri.getHost();
    			URI uriWithoutHost = cleanUrl(request.url(), clientName);
    			
    			// 封装 ribbon 请求组件
    			FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
    					this.delegate, request, uriWithoutHost);
    
    			IClientConfig requestConfig = getClientConfig(options, clientName);
    			// 这行是关键
    			return 
    					// 获取 FeignLoadBalancer
    					lbClient(clientName)
    					// 负载之后请求真实的url
    					// com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer(....)
    					.executeWithLoadBalancer(ribbonRequest,requestConfig)
    					.toResponse();
    		}
    		catch (ClientException e) {
    			....
    			throw new RuntimeException(e);
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer

    public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
            LoadBalancerCommand command = buildLoadBalancerCommand(request, requestConfig);
    
            try {
            	// 在com.netflix.loadbalancer.reactive.LoadBalancerCommand#submit 中会根据 负载均衡算法之后获取到真实的ip地址
    
                return command.submit(
                    new ServerOperation() {
                        @Override
                        // 传入的server 就是真实的ip
                        public Observable call(Server server) {
    
                            URI finalUri = reconstructURIWithServer(server, request.getUri());
                            // 路径替换把原本 http://client-name/xxxx 地址改为 http://127.0.0.1:9090/xxxx
                            S requestForServer = (S) request.replaceUri(finalUri);
                            try {
                            	// 请求父类中的 execute 方法,也就是 上面 lbClient(clientName) 返回的 FeignLoadBalancer
                                return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));
                            } 
                            catch (Exception e) {
                                return Observable.error(e);
                            }
                        }
                    })
                    .toBlocking()
                    .single();
            } catch (Exception e) {
                Throwable t = e.getCause();
                if (t instanceof ClientException) {
                    throw (ClientException) t;
                } else {
                    throw new ClientException(e);
                }
            }
            
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer#execute

    @Override
    	public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
    			throws IOException {
    		Request.Options options;
    		.....
    		// 这里的 request 就是 `org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute` 
    		// 封装的FeignLoadBalancer.RibbonRequest
    		// request.client() 返回就是 feign.Client.Default
    		
    		Response response = request.client().execute(request.toRequest(), options);
    		return new RibbonResponse(request.getUri(), response);
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    feign.Client.Default#execute

     @Override
        public Response execute(Request request, Options options) throws IOException {
          HttpURLConnection connection = convertAndSend(request, options);
          return convertResponse(connection).toBuilder().request(request).build();
        }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里的request 中 url 就是真实的url资源路径了
    现在屡屡逻辑

    org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient和feign.Client.Default
    都实现了 feign.Client 接口,但是 LoadBalancerFeignClient 实际上调用的还是 feign.Client.Default,无非做了自己处理(负载),有些类似于静态代理

  • 相关阅读:
    useEffect、useMemo、useCallback使用场景分析
    【数据结构】栈
    2023-9-8 阿里健康2024校招java-体检及泛医疗部门一面
    【概率论基础进阶】随机变量及其分布-随机变量函数的分布
    python+django+vue酒店入住客房管理系统
    MyBatis-plus 代码生成器配置
    Spring Boot 常见面试题
    牛客小白月赛79
    HDMI 基于 4 层 PCB 的布线指南
    MetaGPT-DataInterpreter源码解读
  • 原文地址:https://blog.csdn.net/zhmi_1015/article/details/134433279