假装注册 - Spring 云 - 不使用功能区更改目标 over-ride
Feign Registration - Spring Cloud - Change Target without ribbon over-ride
简介
我希望能够有两个不同的 spring 配置文件,并根据配置文件更改为我们的假装构建器的硬编码地址。
目前有以下内容:
return builder.target(cls, "http://" + serviceName);
但我实际上想执行以下操作和 over-ride 地址:
return builder.target(cls, "http://our-server:8009/" + serviceName);
为什么
有时我们不想 运行 我们开发环境中的所有服务。此外,某些服务有时只能通过 zuul 网关使用。
所以我们 运行 在不同的情况和条件下使用相同的代码。
技术细节
我们有以下用于构建 Feign 客户端的代码。
我们过去一直在使用 @FeignClient
注释,但最近我们决定开始手动构建 feignClients。
示例如下:
@FeignClient(name = "ab-document-store", configuration = MultiPartSupportConfiguration.class, fallback = DocumentStoreFallback.class)
我们使用以下命令调用 feignRegistrar class:
return registerFeignClient(DocumentStoreClient.class, true);
@RequiredArgsConstructor
//@Component
@Slf4j
public class FeignRegistrar {
@Autowired
private Decoder decoder;
@Autowired
private Encoder encoder;
@Autowired
private Client client;
@Autowired
private Contract feignContract;
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Autowired
private List<RequestInterceptor> interceptors;
public <T> T register(Class<T> cls, String serviceName, boolean isDocumentStore) {
if(isDocumentStore){
encoder = new MultipartFormEncoder(new SpringEncoder(messageConverters));
}
//Client trustSSLSockets = new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
Feign.Builder builder = Feign.builder()
.client(client)
.encoder(encoder)
.decoder(decoder)
.contract(feignContract)
.logger(new Slf4Logger())
.logLevel(Logger.Level.HEADERS);
builder.requestInterceptor(new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("X-Service-Name", serviceName);
}
});
for(RequestInterceptor interceptor : interceptors) {
builder.requestInterceptor(interceptor);
}
log.debug("Registering {} - as feign proxy ", serviceName);
return builder.target(cls, "http://" + serviceName);
}
public static class Slf4Logger extends Logger {
@Override
protected void log(String configKey, String format, Object... args) {
log.info("{} - {}", configKey, args);
}
}
}
Spring云属性Over-ride
我们也一直在使用 属性 文件,例如 application-ENV.property
的条目如下:
ab-document-store.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
ab-document-store.ribbon.listOfServers: localhost:8025
不幸的是,listOfServers
对我们来说还不够。我们也希望能够分配 directory/path。类似于:
ab-document-store.ribbon.listOfServers: localhost:8025/ab-document-store
其他解决方法
我考虑过使用伪装拦截器将 header 潜入所有请求,例如 X-SERVICE-NAME
。然后我们可以将所有服务指向一个地址(例如 localhost:9001),并将 forward/proxy 那些请求指向 localhost:9001/X-SERVICE-NAME。
但是,我更喜欢更简单的解决方案,例如:
ab-document-store.ribbon.listOfServers: localhost:8025/ab-document-store
但这行不通:(
简介
我使用检测 header 的代理找到了解决方案。
所以,我在 java-side 上有一个伪装拦截器,它将 header x-service-name
附加到每个 feign-request.
我还有一个 NodeJS 代理,它分析请求,发现 x-service-name
,re-writes 请求变成:x-service-name
/originalRequestPath
.
这使我可以将所有微服务置于 zuul 网关之后,还可以使用 eureka-over-ride.
访问它们
Java-Feign-Interceptor
Feign.Builder builder = Feign.builder()
.client(client)
.encoder(usedEncoder)
.decoder(decoder)
.contract(feignContract)
.logger(new Slf4Logger())
.logLevel(Logger.Level.HEADERS);
builder.requestInterceptor(new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("X-Service-Name", serviceName);
}
});
NodeJS 代理
在示例中,我的 zuul 网关(或另一个代理)在 localhost:9001 上。
我正在收听 localhost:1200
.
let enableProxyForJava = process.env.ENABLE_PROXY_FOR_JAVA;
if (enableProxyForJava != undefined && enableProxyForJava.toLowerCase() === 'true') {
var httpProxyJava = require('http-proxy');
var proxyJava = httpProxyJava.createProxy();
gutil.log( gutil.colors.green('Enabling Proxy for Java. Set your Eureka overrides to localhost:1200.') );
require('http').createServer(function(req, res) {
console.log("req.headers['x-service-name'] = " + req.headers['x-service-name']);
console.log("Before req.url:"+ req.url);
if( req.headers['x-service-name'] != undefined){
let change = req.headers['x-service-name'] +req.url;
console.log("After req.url:"+ change);
req.url = change;
}
proxyJava.web(req, res, {
target: 'http://localhost:9001/'
});
}).listen(1200);
}
属性 里面的文件 Java 有假装客户端的应用程序
mbak-microservice1.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-microservice1.ribbon.listOfServers: localhost:1200
mbak-microservice2.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-microservice2.ribbon.listOfServers: localhost:1200
mbak-document-store.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-document-store.ribbon.listOfServers: localhost:1200
简介
我希望能够有两个不同的 spring 配置文件,并根据配置文件更改为我们的假装构建器的硬编码地址。
目前有以下内容:
return builder.target(cls, "http://" + serviceName);
但我实际上想执行以下操作和 over-ride 地址:
return builder.target(cls, "http://our-server:8009/" + serviceName);
为什么
有时我们不想 运行 我们开发环境中的所有服务。此外,某些服务有时只能通过 zuul 网关使用。
所以我们 运行 在不同的情况和条件下使用相同的代码。
技术细节
我们有以下用于构建 Feign 客户端的代码。
我们过去一直在使用 @FeignClient
注释,但最近我们决定开始手动构建 feignClients。
示例如下:
@FeignClient(name = "ab-document-store", configuration = MultiPartSupportConfiguration.class, fallback = DocumentStoreFallback.class)
我们使用以下命令调用 feignRegistrar class:
return registerFeignClient(DocumentStoreClient.class, true);
@RequiredArgsConstructor
//@Component
@Slf4j
public class FeignRegistrar {
@Autowired
private Decoder decoder;
@Autowired
private Encoder encoder;
@Autowired
private Client client;
@Autowired
private Contract feignContract;
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Autowired
private List<RequestInterceptor> interceptors;
public <T> T register(Class<T> cls, String serviceName, boolean isDocumentStore) {
if(isDocumentStore){
encoder = new MultipartFormEncoder(new SpringEncoder(messageConverters));
}
//Client trustSSLSockets = new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
Feign.Builder builder = Feign.builder()
.client(client)
.encoder(encoder)
.decoder(decoder)
.contract(feignContract)
.logger(new Slf4Logger())
.logLevel(Logger.Level.HEADERS);
builder.requestInterceptor(new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("X-Service-Name", serviceName);
}
});
for(RequestInterceptor interceptor : interceptors) {
builder.requestInterceptor(interceptor);
}
log.debug("Registering {} - as feign proxy ", serviceName);
return builder.target(cls, "http://" + serviceName);
}
public static class Slf4Logger extends Logger {
@Override
protected void log(String configKey, String format, Object... args) {
log.info("{} - {}", configKey, args);
}
}
}
Spring云属性Over-ride
我们也一直在使用 属性 文件,例如 application-ENV.property
的条目如下:
ab-document-store.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
ab-document-store.ribbon.listOfServers: localhost:8025
不幸的是,listOfServers
对我们来说还不够。我们也希望能够分配 directory/path。类似于:
ab-document-store.ribbon.listOfServers: localhost:8025/ab-document-store
其他解决方法
我考虑过使用伪装拦截器将 header 潜入所有请求,例如 X-SERVICE-NAME
。然后我们可以将所有服务指向一个地址(例如 localhost:9001),并将 forward/proxy 那些请求指向 localhost:9001/X-SERVICE-NAME。
但是,我更喜欢更简单的解决方案,例如:
ab-document-store.ribbon.listOfServers: localhost:8025/ab-document-store
但这行不通:(
简介
我使用检测 header 的代理找到了解决方案。
所以,我在 java-side 上有一个伪装拦截器,它将 header x-service-name
附加到每个 feign-request.
我还有一个 NodeJS 代理,它分析请求,发现 x-service-name
,re-writes 请求变成:x-service-name
/originalRequestPath
.
这使我可以将所有微服务置于 zuul 网关之后,还可以使用 eureka-over-ride.
访问它们Java-Feign-Interceptor
Feign.Builder builder = Feign.builder()
.client(client)
.encoder(usedEncoder)
.decoder(decoder)
.contract(feignContract)
.logger(new Slf4Logger())
.logLevel(Logger.Level.HEADERS);
builder.requestInterceptor(new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("X-Service-Name", serviceName);
}
});
NodeJS 代理
在示例中,我的 zuul 网关(或另一个代理)在 localhost:9001 上。
我正在收听 localhost:1200
.
let enableProxyForJava = process.env.ENABLE_PROXY_FOR_JAVA;
if (enableProxyForJava != undefined && enableProxyForJava.toLowerCase() === 'true') {
var httpProxyJava = require('http-proxy');
var proxyJava = httpProxyJava.createProxy();
gutil.log( gutil.colors.green('Enabling Proxy for Java. Set your Eureka overrides to localhost:1200.') );
require('http').createServer(function(req, res) {
console.log("req.headers['x-service-name'] = " + req.headers['x-service-name']);
console.log("Before req.url:"+ req.url);
if( req.headers['x-service-name'] != undefined){
let change = req.headers['x-service-name'] +req.url;
console.log("After req.url:"+ change);
req.url = change;
}
proxyJava.web(req, res, {
target: 'http://localhost:9001/'
});
}).listen(1200);
}
属性 里面的文件 Java 有假装客户端的应用程序
mbak-microservice1.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-microservice1.ribbon.listOfServers: localhost:1200
mbak-microservice2.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-microservice2.ribbon.listOfServers: localhost:1200
mbak-document-store.ribbon.NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
mbak-document-store.ribbon.listOfServers: localhost:1200