我问自己一个问题而没有找到答案。也许这里有人会对此有所了解;-) 使用Spring Cloud中的服务注册表(Eureka)与RestTemplate和Feign客户端,我有相同服务的不同构建版本。构建版本通过Actuator的/ info端点记录。
var checkArray = [Int]()
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if show_delete == true {
if checkArray.contains(indexPath.row) {
let index = checkArray.index(of: indexPath.row)
checkArray.remove(at: index!)
collectionView.reloadItems(at: [indexPath])
} else {
checkArray.append(indexPath.row)
collectionView.reloadItems(at: [indexPath])
}
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! V_Cell
// Configure the cell
let data = valves_[indexPath.row]
cell.v_name.text = data
if show_delete == true {
cell.img_delete.isHidden = false
} else if show_delete == false {
cell.img_delete.isHidden = true
}
if checkArray.contains(indexPath.row) {
cell.img_delete.image = UIImage(named: "checked_n")
} else {
cell.img_delete.image = UIImage(named: "unchecked")
}
return cell
}
在客户的电话中有任何意思要求特定的构建版本吗? 我应该使用网关的路由过滤器来管理吗?但是我觉得版本检测仍然是个问题......
嗯,任何建议都表示赞赏。
答案 0 :(得分:1)
服务1 使用 Eureka
注册 v1 和 v2服务2 使用不同的功能区客户端发现并向服务1 的v1和v2发送请求
我让这个演示工作,并将在接下来的几天内发布博客。
我遵循的想法是RestTemplate
为每个版本使用不同的Ribbon
客户端,因为每个客户端都有自己的ServerListFilter
。
服务1
<强> application.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
<强> application.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
...
<强> Application.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 (请参阅Ribbon
客户名称与 application.yml
Ribbon
密钥的匹配方式
...
@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.DEMO_REGISTRATION_API_1_V2
<强> RibbonClientApi.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;
}
...
<强> AggregationResource.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;
}
}
答案 1 :(得分:0)
这是黑客Eureka Dashboard的伎俩。 将此AspectJ方面(因为EurekaController中使用的InstanceInfo不是Spring Bean)添加到@EnableEurekaServer项目中:
@Configuration
@Aspect
public class EurekaDashboardVersionLabeler {
@Value("${eureka.instance.metadata.keys.version:instanceBuildVersion}")
private String versionMetadataKey;
@Around("execution(public * com.netflix.appinfo.InstanceInfo.getId())")
public String versionLabelAppInstances(ProceedingJoinPoint jp) throws Throwable {
String instanceId = (String) jp.proceed();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
// limit to EurekaController#populateApps in order to avoid side effects
if (ste.getClassName().contains("EurekaController")) {
InstanceInfo info = (InstanceInfo) jp.getThis();
String version = info.getMetadata().get(versionMetadataKey);
if (StringUtils.hasText(version)) {
return String.format("%s [%s]", instanceId, version);
}
break;
}
}
return instanceId;
}
@Bean("post-construct-labeler")
public EurekaDashboardVersionLabeler init() {
return EurekaDashboardVersionLabeler.aspectOf();
}
private static EurekaDashboardVersionLabeler instance = new EurekaDashboardVersionLabeler();
/** Singleton pattern used by LTW then Spring */
public static EurekaDashboardVersionLabeler aspectOf() {
return instance;
}
}
您还必须添加初学者未提供的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
使用VM arg激活LTW运行时,当然:
-javaagent:D:\.m2\repository\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar