我们目前正在探索Netflix的磁通电容器,以研究其微服务架构的实现。目前,我们的兴趣集中在服务注册和动态查找功能上。
浏览代码、示例和配置,但有些地方不清楚;服务版本控制。如果eureka提供发现服务,而ribbon是基于eureka的REST客户端,那么客户端如何表示需要servicefooBar
的service1.2
?客户机在哪里存储/获取该版本号;从这样的本地配置文件,还是通过archaius动态获取?
服务1向Eureka注册v1和v2
服务2使用不同的Ribbon客户端发现并向服务1的v1和v2发送请求
我得到了这个演示使用Spring Cloud
虽然博客可以找到:http://tech.asimio.net/2017/03/06/Multi-version-Service-Discovery-using-Spring-Cloud-Netflix-Eureka-and-Ribbon.html
我遵循的想法是,对于每个版本,使用不同的Ribbon客户端,因为每个客户端都有自己的ServerListFilter。
多版本服务包括注册元数据中的版本。
服务1
应用yml
...
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8000/eureka/
instance:
hostname: ${hostName}
statusPageUrlPath: ${management.context-path}/info
healthCheckUrlPath: ${management.context-path}/health
preferIpAddress: true
metadataMap:
instanceId: ${spring.application.name}:${server.port}
---
spring:
profiles: v1
eureka:
instance:
metadataMap:
versions: v1
---
spring:
profiles: v1v2
eureka:
instance:
metadataMap:
versions: v1,v2
...
服务2
应用yml
...
eureka:
client:
registerWithEureka: false
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8000/eureka/
demo-multiversion-registration-api-1-v1:
ribbon:
# Eureka vipAddress of the target service
DeploymentContextBasedVipAddresses: demo-multiversion-registration-api-1
NIWSServerListClassName: com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# Interval to refresh the server list from the source (ms)
ServerListRefreshInterval: 30000
demo-multiversion-registration-api-1-v2:
ribbon:
# Eureka vipAddress of the target service
DeploymentContextBasedVipAddresses: demo-multiversion-registration-api-1
NIWSServerListClassName: com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# Interval to refresh the server list from the source (ms)
ServerListRefreshInterval: 30000
...
应用JAVA
...
@SpringBootApplication(scanBasePackages = {
"com.asimio.api.multiversion.demo2.config",
"com.asimio.api.multiversion.demo2.rest"
})
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
AppConfig。java(请参见功能区
客户端名称如何匹配application.yml中的功能区
键
...
@Configuration
@RibbonClients(value = {
@RibbonClient(name = "demo-multiversion-registration-api-1-v1", configuration = RibbonConfigDemoApi1V1.class),
@RibbonClient(name = "demo-multiversion-registration-api-1-v2", configuration = RibbonConfigDemoApi1V2.class)
})
public class AppConfig {
@Bean(name = "loadBalancedRestTemplate")
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
return new RestTemplate();
}
}
RibbonConfigDemoApi1V1.java
...
public class RibbonConfigDemoApi1V1 {
private DiscoveryClient discoveryClient;
@Bean
public ServerListFilter<Server> serverListFilter() {
return new VersionedNIWSServerListFilter<>(this.discoveryClient, RibbonClientApi.DEMO_REGISTRATION_API_1_V1);
}
@Autowired
public void setDiscoveryClient(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
}
RibbonConfigDemoApi1V2。java与之类似,但使用的是RibbonClientApi。演示\u注册\u API\u 1\u V2
彩带。JAVA
...
public enum RibbonClientApi {
DEMO_REGISTRATION_API_1_V1("demo-multiversion-registration-api-1", "v1"),
DEMO_REGISTRATION_API_1_V2("demo-multiversion-registration-api-1", "v2");
public final String serviceId;
public final String version;
private RibbonClientApi(String serviceId, String version) {
this.serviceId = serviceId;
this.version = version;
}
}
VersionedNIWSServerListFilter。JAVA
...
public class VersionedNIWSServerListFilter<T extends Server> extends DefaultNIWSServerListFilter<T> {
private static final String VERSION_KEY = "versions";
private final DiscoveryClient discoveryClient;
private final RibbonClientApi ribbonClientApi;
public VersionedNIWSServerListFilter(DiscoveryClient discoveryClient, RibbonClientApi ribbonClientApi) {
this.discoveryClient = discoveryClient;
this.ribbonClientApi = ribbonClientApi;
}
@Override
public List<T> getFilteredListOfServers(List<T> servers) {
List<T> result = new ArrayList<>();
List<ServiceInstance> serviceInstances = this.discoveryClient.getInstances(this.ribbonClientApi.serviceId);
for (ServiceInstance serviceInstance : serviceInstances) {
List<String> versions = this.getInstanceVersions(serviceInstance);
if (versions.isEmpty() || versions.contains(this.ribbonClientApi.version)) {
result.addAll(this.findServerForVersion(servers, serviceInstance));
}
}
return result;
}
private List<String> getInstanceVersions(ServiceInstance serviceInstance) {
List<String> result = new ArrayList<>();
String rawVersions = serviceInstance.getMetadata().get(VERSION_KEY);
if (StringUtils.isNotBlank(rawVersions)) {
result.addAll(Arrays.asList(rawVersions.split(",")));
}
return result;
}
...
聚合资源。JAVA
...
@RestController
@RequestMapping(value = "/aggregation", produces = "application/json")
public class AggregationResource {
private static final String ACTORS_SERVICE_ID_V1 = "demo-multiversion-registration-api-1-v1";
private static final String ACTORS_SERVICE_ID_V2 = "demo-multiversion-registration-api-1-v2";
private RestTemplate loadBalancedRestTemplate;
@RequestMapping(value = "/v1/actors/{id}", method = RequestMethod.GET)
public com.asimio.api.multiversion.demo2.model.v1.Actor findActorV1(@PathVariable(value = "id") String id) {
String url = String.format("http://%s/v1/actors/{id}", ACTORS_SERVICE_ID_V1);
return this.loadBalancedRestTemplate.getForObject(url, com.asimio.api.multiversion.demo2.model.v1.Actor.class, id);
}
@RequestMapping(value = "/v2/actors/{id}", method = RequestMethod.GET)
public com.asimio.api.multiversion.demo2.model.v2.Actor findActorV2(@PathVariable(value = "id") String id) {
String url = String.format("http://%s/v2/actors/{id}", ACTORS_SERVICE_ID_V2);
return this.loadBalancedRestTemplate.getForObject(url, com.asimio.api.multiversion.demo2.model.v2.Actor.class, id);
}
@Autowired
public void setLoadBalancedRestTemplate(RestTemplate loadBalancedRestTemplate) {
this.loadBalancedRestTemplate = loadBalancedRestTemplate;
}
}
在Eureka REST API的留档中,我看不到任何处理服务版本的内置方式。
因此,我认为最好的处理方法是将版本控制信息合并到服务ID中。
假设我们有4个服务:用户、统计、登录和oAuth。
我们刚刚更新了用户服务API,以更改登录服务中某些新需求所需的功能。然而,这些更改与oAuth正在使用的API不兼容,没有人有时间更新该服务。统计服务不使用任何此功能,因此它不关心使用哪个版本的API。这意味着我们需要同时运行用户服务的新版本(1.2)和旧版本(1.1)。
我们可以这样设置:
这样,oAuth服务将只与旧用户服务、登录服务与新用户服务以及统计服务与任何用户服务通信。
您应该能够使用Archaius将配置传播到服务器。
请注意,如果您发布的用户版本1.3引入了与统计服务正在使用的1.2和1.1部分不兼容的更改,则您必须告诉用户1.1和1.2服务也注册为其他服务(如“用户统计安全”),并告诉统计服务使用该ID,或者告诉统计服务使用“user-1.1”或“user-1.2”。
我对Netflix尤里卡和春靴很陌生。我构建了一个非常简单的Eureka服务器和客户端,以便了解它们如何获得发现的所有权。尤里卡服务器正常加载,因为我在转到本地主机时可以看到UI:8761/ 我正在用Eclipse的Tomcat运行这两个实例。 我构建的Eureka客户端没有代码,因为它只运行带有适当注释的SpringBoot应用程序。Eureka服务器也是如此。 当我运行客户机时,在运行服务器之
我正在使用带有 netflix 堆栈和 Spring 启动的微服务构建一个应用程序。困扰我的一件事是,我还没有集成测试,我可以在其中模拟周围的服务。 因此,我有一个服务 A,它是一个带有功能区的尤里卡客户端,用于在呼叫期间将尤里卡名称解析为已注册服务 B 的 URL。 所以理想情况下,我想用 spring boot 的 integrationtest 注释启动应用程序,使用 wiremock 模拟
我正在通过google play服务使用Google Cloud消息传递。问题是它仅适用于安装了上一个版本的play服务的设备,在其余设备中,我需要显示一个对话框以将用户发送到google play以安装新版本女巫我真的不想做! 那我怎么能避免呢?!我正在尝试使用较旧版本的play services(比如两年前的版本),以确保我的大多数用户不需要更新,但grade和android sdk似乎不可能
我在一个微服务体系结构中工作,其工作原理如下 我有两个服务Web应用程序(REST服务),在eureka服务器中正确注册自己,然后我有一个客户端应用程序,获取eureka注册表,并使用ribbon作为客户端负载均衡器,确定哪个服务应用程序去(目前,一个简单的正在使用圆形罗宾)。 我的问题是,当我停止其中一个服务应用程序(它们目前在docker容器中运行)时,eureka不会将它们从注册表中删除(似
我有一个客户端,它通过指定TLS 1.2发送握手请求到维基,但维基用TLS 1.0版回复。我如何让维基使用1.2版
因为我有一个长期运行的任务要在我的应用程序的后台执行,所以我正在尝试实现一个服务来完成一项工作。 此服务使用LocationClient实例中的位置数据,每个请求都会触发一个PendingEvent。最低目标版本阻止我使用新的LocationServices,Android文档建议我使用LocationClient的PendingEvent版本。requestLocationUpdates(…)方