概述
重写feign使用serviceId调用
有时候需要在feign接口请求前.在url上拼接一些固定字符串.但是又不想在每个方法上都加一段.重写下面方法可以做到在feign构建httpclient后动态修改请求路径,相当于feign请求前URL处理拦截器
重写httpclient工厂类
package com.wmang.ext.client.feign;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.util.ConcurrentReferenceHashMap;
import java.util.Map;
/**
* Factory for SpringLoadBalancer instances that caches the entries created.
*
* @author Spencer Gibb
* @author Dave Syer
* @author Ryan Baxter
* @author Gang Li
* @author wmang
*/
public class ExampleCachingSpringLoadBalancerFactory {
protected final SpringClientFactory factory;
protected final ExampleLoadBalancerExtend loadBalancerExtend;
protected LoadBalancedRetryFactory loadBalancedRetryFactory = null;
private Map<String, ExampleFeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
public ExampleCachingSpringLoadBalancerFactory(SpringClientFactory factory, ExampleLoadBalancerExtend loadBalancerExtend) {
this.factory = factory;
this.loadBalancerExtend = loadBalancerExtend;
}
public ExampleCachingSpringLoadBalancerFactory(SpringClientFactory factory, LoadBalancedRetryFactory loadBalancedRetryPolicyFactory, ExampleLoadBalancerExtend loadBalancerExtend) {
this.factory = factory;
this.loadBalancerExtend = loadBalancerExtend;
this.loadBalancedRetryFactory = loadBalancedRetryPolicyFactory;
}
public ExampleFeignLoadBalancer create(String clientName) {
ExampleFeignLoadBalancer client = this.cache.get(clientName);
if (client != null) {
return client;
}
IClientConfig config = this.factory.getClientConfig(clientName);
ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
client = loadBalancedRetryFactory != null ? new ExampleRetryableFeignLoadBalancer(lb, config, serverIntrospector,
loadBalancedRetryFactory, loadBalancerExtend) : new ExampleFeignLoadBalancer(lb, config, serverIntrospector, loadBalancerExtend);
this.cache.put(clientName, client);
return client;
}
}
重写FeignLoadBalancedConfiguration
package com.wmang.ext.client.feign;
import feign.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* @author wmang
*/
@Configuration
public class ExampleFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean
public ExampleLoadBalancerExtend getExampleLoadBalancerExtend() {
return new ExampleLoadBalancerExtend(null);
}
@Bean
@Primary
@ConditionalOnMissingBean
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
public ExampleCachingSpringLoadBalancerFactory ExampleCachingLBClientFactory(
SpringClientFactory factory,ExampleLoadBalancerExtend loadBalancerExtend) {
return new ExampleCachingSpringLoadBalancerFactory(factory,loadBalancerExtend);
}
@Bean
@Primary
@ConditionalOnMissingBean
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
public ExampleCachingSpringLoadBalancerFactory ExampleRetryabeCachingLBClientFactory(
SpringClientFactory factory,
LoadBalancedRetryFactory retryFactory,
ExampleLoadBalancerExtend loadBalancerExtend) {
return new ExampleCachingSpringLoadBalancerFactory(factory, retryFactory,loadBalancerExtend);
}
@Bean
@Primary
@ConditionalOnMissingBean
public Client feignClient(ExampleCachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new ExampleLoadBalancerFeignClient(new Client.Default(null, null),
cachingFactory, clientFactory);
}
}
重写loadBalance实现
package com.wmang.ext.client.feign;
import com.netflix.client.*;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import feign.Client;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.ribbon.RibbonProperties;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import java.io.IOException;
import java.net.URI;
import java.util.*;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToSecureConnectionIfNeeded;
/**
* @author wmang
*/
@Slf4j
public class ExampleFeignLoadBalancer extends
AbstractLoadBalancerAwareClient<ExampleFeignLoadBalancer.RibbonRequest, ExampleFeignLoadBalancer.RibbonResponse> {
private final RibbonProperties ribbon;
protected int connectTimeout;
protected int readTimeout;
protected IClientConfig clientConfig;
protected ServerIntrospector serverIntrospector;
private ExampleLoadBalancerExtend loadBalancerExtend;
public ExampleFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
ServerIntrospector serverIntrospector,ExampleLoadBalancerExtend loadBalancerExtend) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.ribbon = RibbonProperties.from(clientConfig);
RibbonProperties ribbon = this.ribbon;
this.connectTimeout = ribbon.getConnectTimeout();
this.readTimeout = ribbon.getReadTimeout();
this.serverIntrospector = serverIntrospector;
this.loadBalancerExtend = loadBalancerExtend;
}
public ExampleFeignLoadBalancer(ILoadBalancer lb, RibbonProperties ribbon) {
super(lb);
this.ribbon = ribbon;
}
@Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
throws IOException {
Request.Options options;
if (configOverride != null) {
RibbonProperties override = RibbonProperties.from(configOverride);
options = new Request.Options(
override.connectTimeout(this.connectTimeout),
override.readTimeout(this.readTimeout));
}
else {
options = new Request.Options(this.connectTimeout, this.readTimeout);
}
Response response = request.client().execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (this.ribbon.isOkToRetryOnAllOperations()) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
if (!request.toRequest().httpMethod().name().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
requestConfig);
}
else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
}
@Override
public URI reconstructURIWithServer(Server server, URI original) {
URI uri = updateToSecureConnectionIfNeeded(original, this.clientConfig, this.serverIntrospector, server);
return loadBalancerExtend.reconstructURIWithServer(server, uri);
}
protected static class RibbonRequest extends ClientRequest implements Cloneable {
private final Request request;
private final Client client;
protected RibbonRequest(Client client, Request request, URI uri) {
this.client = client;
setUri(uri);
this.request = toRequest(request);
}
private Request toRequest(Request request) {
Map<String, Collection<String>> headers = new LinkedHashMap<>(
request.headers());
return Request.create(request.httpMethod(), getUri().toASCIIString(), headers,
request.requestBody());
}
Request toRequest() {
return toRequest(this.request);
}
Client client() {
return this.client;
}
HttpRequest toHttpRequest() {
return new HttpRequest() {
@Override
public HttpMethod getMethod() {
return HttpMethod
.resolve(RibbonRequest.this.toRequest().httpMethod().name());
}
@Override
public String getMethodValue() {
return getMethod().name();
}
@Override
public URI getURI() {
return RibbonRequest.this.getUri();
}
@Override
public HttpHeaders getHeaders() {
Map<String, List<String>> headers = new HashMap<>();
Map<String, Collection<String>> feignHeaders = RibbonRequest.this.toRequest().headers();
for (Iterator<String> iterator = feignHeaders.keySet().iterator(); iterator.hasNext(); ) {
String key = iterator.next();
headers.put(key, new ArrayList<>(feignHeaders.get(key)));
}
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(headers);
return httpHeaders;
}
};
}
public Request getRequest() {
return request;
}
public Client getClient() {
return client;
}
@Override
public Object clone() {
return new RibbonRequest(this.client, this.request, getUri());
}
}
protected static class RibbonResponse implements IResponse {
private final URI uri;
private final Response response;
protected RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
@Override
public Object getPayload() throws ClientException {
return this.response.body();
}
@Override
public boolean hasPayload() {
return this.response.body() != null;
}
@Override
public boolean isSuccess() {
return this.response.status() == 200;
}
@Override
public URI getRequestedURI() {
return this.uri;
}
@Override
public Map<String, Collection<String>> getHeaders() {
return this.response.headers();
}
Response toResponse() {
return this.response;
}
@Override
public void close() throws IOException {
if (this.response != null && this.response.body() != null) {
this.response.body().close();
}
}
}
}
重写LoadBalancerURI重组方法
package com.wmang.ext.client.feign;
import com.google.common.base.Strings;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.LoadBalancerContext;
import com.netflix.loadbalancer.Server;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import com.netflix.util.Pair;
import lombok.extern.slf4j.Slf4j;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
/**
* @author: wmang
* @date: 2020/3/27 13:35
* @description:
*/
@Slf4j
public class ExampleLoadBalancerExtend extends LoadBalancerContext {
public static final String METADATA_PUBLISH_VERSION = "pub-version";
public static final String METADATA_PUBLISH_CODE = "pub-code";
public static final String METADATA_PUBLISH_MICROSERVICE_NAME = "pub-service_name";
public static final String URL_SPLIT_GANG = "/";
public ExampleLoadBalancerExtend(ILoadBalancer lb) {
super(lb);
}
@Override
public URI reconstructURIWithServer(Server server, URI original) {
log.info("自定义feignUrl解析开始处理【feignUrl】...");
String host = server.getHost();
int port = server.getPort();
String scheme = server.getScheme();
if (host.equals(original.getHost())
&& port == original.getPort()
&& scheme.equals(original.getScheme())) {
return original;
}
if (scheme == null) {
scheme = original.getScheme();
}
if (scheme == null) {
scheme = deriveSchemeAndPortFromPartialUri(original).first();
}
try {
StringBuilder sb = new StringBuilder();
sb.append(scheme).append("://");
if (!Strings.isNullOrEmpty(original.getRawUserInfo())) {
sb.append(original.getRawUserInfo()).append("@");
}
sb.append(host);
if (port >= 0) {
sb.append(":").append(port);
}
if (isIssueService(server)) {
sb.append(URL_SPLIT_GANG)
.append(getProviderCode(server))
.append(URL_SPLIT_GANG)
.append(getServiceName(server))
.append(URL_SPLIT_GANG)
.append(getServiceVersion(server));
}
sb.append(original.getRawPath());
if (!Strings.isNullOrEmpty(original.getRawQuery())) {
sb.append("?").append(original.getRawQuery());
}
if (!Strings.isNullOrEmpty(original.getRawFragment())) {
sb.append("#").append(original.getRawFragment());
}
URI newURI = new URI(sb.toString());
return newURI;
} catch (URISyntaxException e) {
log.error("feign url append error:{}", e.getMessage());
throw new RuntimeException("feign url append error:"+e.getMessage());
}
}
private String getServiceVersion(Server server) {
DiscoveryEnabledServer discoveryEnabledServer = getDiscoveryServer(server);
Map<String, String> metadata = discoveryEnabledServer.getInstanceInfo().getMetadata();
return metadata.get(METADATA_PUBLISH_VERSION);
}
private String getServiceName(Server server) {
DiscoveryEnabledServer discoveryEnabledServer = getDiscoveryServer(server);
Map<String, String> metadata = discoveryEnabledServer.getInstanceInfo().getMetadata();
return metadata.get(METADATA_PUBLISH_MICROSERVICE_NAME);
}
private String getProviderCode(Server server) {
DiscoveryEnabledServer discoveryEnabledServer = getDiscoveryServer(server);
Map<String, String> metadata = discoveryEnabledServer.getInstanceInfo().getMetadata();
return metadata.get(METADATA_PUBLISH_CODE);
}
private boolean isIssueService(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer discoveryEnabledServer = getDiscoveryServer(server);
Map<String, String> metadata = discoveryEnabledServer.getInstanceInfo().getMetadata();
if (!metadata.containsKey(METADATA_PUBLISH_CODE)) {
return false;
}
if (!metadata.containsKey(METADATA_PUBLISH_VERSION)) {
return false;
}
if (!metadata.containsKey(METADATA_PUBLISH_MICROSERVICE_NAME)) {
return false;
}
return true;
}
return false;
}
private DiscoveryEnabledServer getDiscoveryServer(Server server) {
return (DiscoveryEnabledServer) server;
}
/**
* Derive scheme and port from a partial URI. For example, for HTTP based client, the URI with
* only path "/" should return "http" and 80, whereas the URI constructed with scheme "https" and
* path "/" should return "https" and 443.
* This method is called by {@link #getServerFromLoadBalancer(URI, Object)} and
* {@link #reconstructURIWithServer(Server, URI)} methods to get the complete executable URI.
*/
@Override
protected Pair<String, Integer> deriveSchemeAndPortFromPartialUri(URI uri) {
boolean isSecure = false;
String scheme = uri.getScheme();
if (scheme != null) {
isSecure = scheme.equalsIgnoreCase("https");
}
int port = uri.getPort();
if (port < 0 && !isSecure) {
port = 80;
} else if (port < 0 && isSecure) {
port = 443;
}
if (isSecure) {
scheme = "https";
} else {
scheme = "http";
}
return new Pair<String, Integer>(scheme, port);
}
}
重写feign默认的httpClient对象(照搬,基本没改动)
package com.wmang.ext.client.feign;
import com.netflix.client.ClientException;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import feign.Client;
import feign.Request;
import feign.Response;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import java.io.IOException;
import java.net.URI;
/**
* @author wmang
*/
public class ExampleLoadBalancerFeignClient implements Client {
static final Request.Options DEFAULT_OPTIONS = new Request.Options();
private final Client delegate;
private ExampleCachingSpringLoadBalancerFactory lbClientFactory;
private SpringClientFactory clientFactory;
public ExampleLoadBalancerFeignClient(Client delegate,
ExampleCachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
this.delegate = delegate;
this.lbClientFactory = lbClientFactory;
this.clientFactory = clientFactory;
}
@Override
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);
ExampleFeignLoadBalancer.RibbonRequest ribbonRequest = new ExampleFeignLoadBalancer.RibbonRequest(
this.delegate, request, uriWithoutHost);
IClientConfig requestConfig = getClientConfig(options, clientName);
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest,
requestConfig).toResponse();
} catch (ClientException e) {
IOException io = findIOException(e);
if (io != null) {
throw io;
}
throw new RuntimeException(e);
}
}
IClientConfig getClientConfig(Request.Options options, String clientName) {
IClientConfig requestConfig;
if (options == DEFAULT_OPTIONS) {
requestConfig = this.clientFactory.getClientConfig(clientName);
} else {
requestConfig = new FeignOptionsClientConfig(options);
}
return requestConfig;
}
protected IOException findIOException(Throwable t) {
if (t == null) {
return null;
}
if (t instanceof IOException) {
return (IOException) t;
}
return findIOException(t.getCause());
}
public Client getDelegate() {
return this.delegate;
}
static URI cleanUrl(String originalUrl, String host) {
String newUrl = originalUrl;
if (originalUrl.startsWith("https://")) {
newUrl = originalUrl.substring(0, 8) + originalUrl.substring(8 + host.length());
} else if (originalUrl.startsWith("http")) {
newUrl = originalUrl.substring(0, 7) + originalUrl.substring(7 + host.length());
}
StringBuffer buffer = new StringBuffer(newUrl);
if ((newUrl.startsWith("https://") && newUrl.length() == 8) ||
(newUrl.startsWith("http://") && newUrl.length() == 7)) {
buffer.append("/");
}
return URI.create(buffer.toString());
}
private ExampleFeignLoadBalancer lbClient(String clientName) {
return this.lbClientFactory.create(clientName);
}
static class FeignOptionsClientConfig extends DefaultClientConfigImpl {
public FeignOptionsClientConfig(Request.Options options) {
setProperty(CommonClientConfigKey.ConnectTimeout,
options.connectTimeoutMillis());
setProperty(CommonClientConfigKey.ReadTimeout, options.readTimeoutMillis());
}
@Override
public void loadProperties(String clientName) {
}
@Override
public void loadDefaultValues() {
}
}
}
重写feign原生的自动重试机制(照搬,基本没改动)
/*
*
*
* Copyright 2013-2016 the original author or authors.
*
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
*
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
*
*
* Unless required by applicable law or agreed to in writing, software
*
* distributed under the License is distributed on an "AS IS" BASIS,
*
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
*
* limitations under the License.
*
*/
package com.wmang.ext.client.feign;
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import feign.Request;
import feign.Response;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.RibbonProperties;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.openfeign.ribbon.FeignRetryPolicy;
import org.springframework.cloud.openfeign.ribbon.RibbonResponseStatusCodeException;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.NoBackOffPolicy;
import org.springframework.retry.policy.NeverRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.net.URI;
/**
* A {@link ExampleFeignLoadBalancer} that leverages Spring Retry to retry failed requests.
*
* @author Ryan Baxter
* @author Gang Li
* @author wmang
*/
public class ExampleRetryableFeignLoadBalancer extends ExampleFeignLoadBalancer implements ServiceInstanceChooser {
private final LoadBalancedRetryFactory loadBalancedRetryFactory;
public ExampleRetryableFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector,
LoadBalancedRetryFactory loadBalancedRetryFactory,ExampleLoadBalancerExtend loadBalancerExtend) {
super(lb, clientConfig, serverIntrospector,loadBalancerExtend);
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
}
@Override
public RibbonResponse execute(final RibbonRequest request, IClientConfig configOverride)
throws IOException {
final Request.Options options;
if (configOverride != null) {
RibbonProperties ribbon = RibbonProperties.from(configOverride);
options = new Request.Options(
ribbon.connectTimeout(this.connectTimeout),
ribbon.readTimeout(this.readTimeout));
} else {
options = new Request.Options(this.connectTimeout, this.readTimeout);
}
final LoadBalancedRetryPolicy retryPolicy = loadBalancedRetryFactory.createRetryPolicy(this.getClientName(), this);
RetryTemplate retryTemplate = new RetryTemplate();
BackOffPolicy backOffPolicy = loadBalancedRetryFactory.createBackOffPolicy(this.getClientName());
retryTemplate.setBackOffPolicy(backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
RetryListener[] retryListeners = this.loadBalancedRetryFactory.createRetryListeners(this.getClientName());
if (retryListeners != null && retryListeners.length != 0) {
retryTemplate.setListeners(retryListeners);
}
retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
: new FeignRetryPolicy(request.toHttpRequest(), retryPolicy, this, this.getClientName()));
return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
@Override
public RibbonResponse doWithRetry(RetryContext retryContext) throws IOException {
Request feignRequest = null;
//on retries the policy will choose the server and set it in the context
//extract the server and update the request being made
if (retryContext instanceof LoadBalancedRetryContext) {
ServiceInstance service = ((LoadBalancedRetryContext) retryContext).getServiceInstance();
if (service != null) {
feignRequest = ((RibbonRequest) request.replaceUri(reconstructURIWithServer(new Server(service.getHost(), service.getPort()), request.getUri()))).toRequest();
}
}
if (feignRequest == null) {
feignRequest = request.toRequest();
}
Response response = request.client().execute(feignRequest, options);
if (retryPolicy != null && retryPolicy.retryableStatusCode(response.status())) {
byte[] byteArray = response.body() == null ? new byte[]{} : StreamUtils.copyToByteArray(response.body().asInputStream());
response.close();
throw new RibbonResponseStatusCodeException(ExampleRetryableFeignLoadBalancer.this.clientName, response,
byteArray, request.getUri());
}
return new RibbonResponse(request.getUri(), response);
}
}, new LoadBalancedRecoveryCallback<RibbonResponse, Response>() {
@Override
protected RibbonResponse createResponse(Response response, URI uri) {
return new RibbonResponse(uri, response);
}
});
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
ExampleFeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {
return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(), requestConfig);
}
@Override
public ServiceInstance choose(String serviceId) {
return new RibbonLoadBalancerClient.RibbonServer(serviceId,
this.getLoadBalancer().chooseServer(serviceId));
}
}
最后
以上就是无聊老虎为你收集整理的重写feign使用serviceId调用重写feign使用serviceId调用的全部内容,希望文章能够帮你解决重写feign使用serviceId调用重写feign使用serviceId调用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复