Skip to content

Commit

Permalink
[1071] support affinity tag Service Instance Filter
Browse files Browse the repository at this point in the history
  • Loading branch information
provenceee committed Sep 19, 2023
1 parent 1190cf7 commit f69eb5f
Show file tree
Hide file tree
Showing 11 changed files with 253 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@

package com.huaweicloud.governance.adapters.loadbalancer;

import java.util.List;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.core.Ordered;

import java.util.List;

public interface ServiceInstanceFilter extends Ordered {
int ZONE_AWARE_ORDER = -2;

int CANARY_ORDER = -1;

int AFFINITY_TAG_ORDER = 0;

/**
* filter service instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.huaweicloud.common.configration.dynamic.GovernanceProperties;
import com.huaweicloud.nacos.authentication.NacosAuthenticationAdapter;
import com.huaweicloud.nacos.registry.MetadataNacosRegistrationCustomizer;
import com.huaweicloud.nacos.loadbalancer.NacosAffinityTagFilterAdapter;
import com.huaweicloud.nacos.loadbalancer.NacosCanaryFilterAdapter;
import com.huaweicloud.nacos.loadbalancer.NacosZoneAwareFilterAdapter;

Expand All @@ -47,4 +49,14 @@ public NacosCanaryFilterAdapter nacosCanaryFilterAdapter() {
public NacosZoneAwareFilterAdapter nacosZoneAwareFilterAdapter() {
return new NacosZoneAwareFilterAdapter();
}

@Bean
public NacosAffinityTagFilterAdapter nacosAffinityTagFilterAdapter() {
return new NacosAffinityTagFilterAdapter();
}

@Bean
public MetadataNacosRegistrationCustomizer metadataNacosRegistrationCustomizer() {
return new MetadataNacosRegistrationCustomizer();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huaweicloud.nacos.loadbalancer;

import com.huaweicloud.router.client.loadbalancer.AffinityTagFilterAdapter;

/**
* nacos affinity tag adapter
*
* @author provenceee
* @since 2023-09-19
*/
public class NacosAffinityTagFilterAdapter implements AffinityTagFilterAdapter {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huaweicloud.nacos.registry;

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.configuration.EnvironmentConfiguration;

import com.alibaba.cloud.nacos.registry.NacosRegistration;
import com.alibaba.cloud.nacos.registry.NacosRegistrationCustomizer;

/**
* add nacos metadata
*
* @author provenceee
* @since 2023-09-19
*/
public class MetadataNacosRegistrationCustomizer implements NacosRegistrationCustomizer {
private static final String INSTANCE_PROPS = "SERVICECOMB_INSTANCE_PROPS";

@Override
public void customize(NacosRegistration registration) {
EnvironmentConfiguration envConfig = new EnvironmentConfiguration();
String[] instancePropArray = envConfig.getStringArray(INSTANCE_PROPS);
if (instancePropArray.length != 0) {
registration.getMetadata().putAll(parseProps(instancePropArray));
}
}

private Map<String, String> parseProps(String... value) {
return Arrays.stream(value).map(v -> v.split(":"))
.filter(v -> v.length == 2)
.collect(Collectors.toMap(v -> v[0], v -> v[1]));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.huaweicloud.router.client.loadbalancer.AffinityTagFilterAdapter;
import com.huaweicloud.router.client.loadbalancer.AffinityTagServiceInstanceFilter;
import com.huaweicloud.router.client.loadbalancer.CanaryFilterAdapter;
import com.huaweicloud.router.client.loadbalancer.CanaryServiceInstanceFilter;
import com.huaweicloud.router.client.loadbalancer.SpringCloudRouterDistributor;
Expand Down Expand Up @@ -59,4 +61,12 @@ public ZoneAwareServiceInstanceFilter zoneAwareServiceInstanceFilter(Registratio
ZoneAwareFilterAdapter adapter) {
return new ZoneAwareServiceInstanceFilter(registration, adapter);
}

@Bean
@ConditionalOnMissingBean(AffinityTagServiceInstanceFilter.class)
@ConditionalOnProperty(value = "spring.cloud.servicecomb.discovery.enabledAffinityTag", havingValue = "true")
public AffinityTagServiceInstanceFilter affinityTagServiceInstanceFilter(Registration registration,
AffinityTagFilterAdapter adapter) {
return new AffinityTagServiceInstanceFilter(registration, adapter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huaweicloud.router.client.loadbalancer;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;

/**
* affinity tag adapter
*
* @author provenceee
* @since 2023-09-19
*/
public interface AffinityTagFilterAdapter {
String AFFINITY_TAG = "affinity-tag";

default String getAffinityTag(ServiceInstance serviceInstance) {
return serviceInstance.getMetadata().get(AFFINITY_TAG);
}

default String getAffinityTag(Registration registration) {
return registration.getMetadata().get(AFFINITY_TAG);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huaweicloud.router.client.loadbalancer;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.util.CollectionUtils;

import com.huaweicloud.governance.adapters.loadbalancer.ServiceInstanceFilter;

/**
* affinity tag instance filter
* @author provenceee
* @since 2023-09-19
*/
public class AffinityTagServiceInstanceFilter implements ServiceInstanceFilter {
private final Registration registration;

private final AffinityTagFilterAdapter adapter;

public AffinityTagServiceInstanceFilter(Registration registration, AffinityTagFilterAdapter adapter) {
this.registration = registration;
this.adapter = adapter;
}

@Override
public List<ServiceInstance> filter(ServiceInstanceListSupplier supplier, List<ServiceInstance> instances,
Request<?> request) {
String affinityTag = adapter.getAffinityTag(registration);
List<ServiceInstance> serviceInstances = instances.stream().filter(
instance -> Objects.equals(affinityTag, adapter.getAffinityTag(instance))).collect(Collectors.toList());
return CollectionUtils.isEmpty(serviceInstances) ? instances : serviceInstances;
}

@Override
public int getOrder() {
return AFFINITY_TAG_ORDER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@ public List<ServiceInstance> filter(ServiceInstanceListSupplier supplier, List<S

@Override
public int getOrder() {
return -1;
return CANARY_ORDER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public List<ServiceInstance> filter(ServiceInstanceListSupplier supplier, List<S

@Override
public int getOrder() {
return -2;
return ZONE_AWARE_ORDER;
}

private List<ServiceInstance> zoneAwareDiscoveryFilter(List<ServiceInstance> instances) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.huaweicloud.service.engine.common.disovery.ServiceCenterUtils;
import com.huaweicloud.servicecomb.discovery.authentication.ServiceCombAuthenticationAdapter;
import com.huaweicloud.servicecomb.discovery.discovery.DiscoveryProperties;
import com.huaweicloud.servicecomb.discovery.loadbalancer.ServiceCombAffinityTagFilterAdapter;
import com.huaweicloud.servicecomb.discovery.loadbalancer.ServiceCombCanaryFilterAdapter;
import com.huaweicloud.servicecomb.discovery.loadbalancer.ServiceCombZoneAwareFilterAdapter;

Expand Down Expand Up @@ -73,4 +74,9 @@ public ServiceCombCanaryFilterAdapter serviceCombCanaryFilterAdapter() {
public ServiceCombZoneAwareFilterAdapter serviceCombZoneAwareFilterAdapter() {
return new ServiceCombZoneAwareFilterAdapter();
}

@Bean
public ServiceCombAffinityTagFilterAdapter serviceCombAffinityTagFilterAdapter() {
return new ServiceCombAffinityTagFilterAdapter();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huaweicloud.servicecomb.discovery.loadbalancer;

import org.apache.servicecomb.service.center.client.model.MicroserviceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;

import com.huaweicloud.router.client.loadbalancer.AffinityTagFilterAdapter;
import com.huaweicloud.servicecomb.discovery.registry.ServiceCombRegistration;

/**
* serviceComb affinity tag adapter
*
* @author provenceee
* @since 2023-09-19
*/
public class ServiceCombAffinityTagFilterAdapter implements AffinityTagFilterAdapter {
@Override
public String getAffinityTag(Registration registration) {
ServiceCombRegistration serviceCombRegistration = (ServiceCombRegistration) registration;
MicroserviceInstance microserviceInstance = serviceCombRegistration.getMicroserviceInstance();
if (microserviceInstance.getProperties() == null) {
return null;
}
return microserviceInstance.getProperties().get(AFFINITY_TAG);
}
}

0 comments on commit f69eb5f

Please sign in to comment.