parent
d721d27441
commit
0ed97436d5
@ -1,2 +1,4 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- [feat: support lossless register and deregister](https://github.com/Tencent/spring-cloud-tencent/issues/977)
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the BSD 3-Clause License (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*
|
|
||||||
* 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.tencent.cloud.plugin.lossless;
|
|
||||||
|
|
||||||
import com.tencent.cloud.common.util.ReflectionUtils;
|
|
||||||
import com.tencent.cloud.plugin.lossless.config.LosslessProperties;
|
|
||||||
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
|
|
||||||
import com.tencent.polaris.api.pojo.BaseInstance;
|
|
||||||
import com.tencent.polaris.api.pojo.DefaultBaseInstance;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap Spring Bean and proxy for serviceRegistry.
|
|
||||||
*
|
|
||||||
* @author Shedfree Wu
|
|
||||||
*/
|
|
||||||
public class LosslessBeanPostProcessor implements BeanPostProcessor {
|
|
||||||
|
|
||||||
private PolarisSDKContextManager polarisSDKContextManager;
|
|
||||||
|
|
||||||
private LosslessProperties losslessProperties;
|
|
||||||
|
|
||||||
private Registration registration;
|
|
||||||
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
public LosslessBeanPostProcessor(PolarisSDKContextManager polarisSDKContextManager,
|
|
||||||
LosslessProperties losslessProperties, Registration registration, Integer port) {
|
|
||||||
this.polarisSDKContextManager = polarisSDKContextManager;
|
|
||||||
this.losslessProperties = losslessProperties;
|
|
||||||
this.registration = registration;
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
|
||||||
if (bean instanceof AbstractAutoServiceRegistration) {
|
|
||||||
wrap(bean, polarisSDKContextManager, losslessProperties, registration, port);
|
|
||||||
}
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void wrap(Object bean, PolarisSDKContextManager polarisSDKContextManager,
|
|
||||||
LosslessProperties losslessProperties, Registration registration, Integer port) {
|
|
||||||
LosslessProxyServiceRegistry proxyServiceRegistry;
|
|
||||||
String clsName = bean.getClass().getCanonicalName();
|
|
||||||
if (clsName.contains("org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration")) {
|
|
||||||
ServiceRegistry<Registration> registry =
|
|
||||||
(ServiceRegistry<Registration>) ReflectionUtils.
|
|
||||||
getObjectByFieldName(bean, "serviceRegistry");
|
|
||||||
proxyServiceRegistry = new LosslessProxyServiceRegistry(registry, polarisSDKContextManager, registration);
|
|
||||||
ReflectionUtils.setValueByFieldName(bean, "serviceRegistry", proxyServiceRegistry);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ServiceRegistry<Registration> registry =
|
|
||||||
(ServiceRegistry<Registration>) ReflectionUtils.
|
|
||||||
getSuperObjectByFieldName(bean, "serviceRegistry");
|
|
||||||
proxyServiceRegistry = new LosslessProxyServiceRegistry(registry, polarisSDKContextManager, registration);
|
|
||||||
ReflectionUtils.setSuperValueByFieldName(bean, "serviceRegistry", proxyServiceRegistry);
|
|
||||||
}
|
|
||||||
SpringCloudLosslessActionProvider losslessActionProvider =
|
|
||||||
new SpringCloudLosslessActionProvider(proxyServiceRegistry, losslessProperties);
|
|
||||||
polarisSDKContextManager.getLosslessAPI().setLosslessActionProvider(
|
|
||||||
getBaseInstance(registration, port), losslessActionProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseInstance getBaseInstance(Registration registration, Integer port) {
|
|
||||||
// registration 通用,不设置 ns
|
|
||||||
DefaultBaseInstance baseInstance = new DefaultBaseInstance();
|
|
||||||
baseInstance.setService(registration.getServiceId());
|
|
||||||
// 由于 PolarisRegistration 的 port 在 web 启动后才能生成,需从外部传入
|
|
||||||
baseInstance.setPort(port);
|
|
||||||
baseInstance.setHost(registration.getHost());
|
|
||||||
return baseInstance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the BSD 3-Clause License (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*
|
|
||||||
* 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.tencent.cloud.plugin.lossless;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
|
|
||||||
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lossless proxy for {@link ServiceRegistry}.
|
|
||||||
*
|
|
||||||
* @author Shedfree Wu
|
|
||||||
*/
|
|
||||||
public class LosslessProxyServiceRegistry implements ServiceRegistry<Registration> {
|
|
||||||
|
|
||||||
private final ServiceRegistry<Registration> target;
|
|
||||||
|
|
||||||
private Registration registration;
|
|
||||||
|
|
||||||
private PolarisSDKContextManager polarisSDKContextManager;
|
|
||||||
|
|
||||||
private final AtomicBoolean doneDeregister = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
public LosslessProxyServiceRegistry(ServiceRegistry<Registration> target,
|
|
||||||
PolarisSDKContextManager polarisSDKContextManager, Registration registration) {
|
|
||||||
this.target = target;
|
|
||||||
this.polarisSDKContextManager = polarisSDKContextManager;
|
|
||||||
this.registration = registration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(Registration registration) {
|
|
||||||
this.registration = registration;
|
|
||||||
// web started, get port from registration
|
|
||||||
polarisSDKContextManager.getLosslessAPI().losslessRegister(
|
|
||||||
LosslessBeanPostProcessor.getBaseInstance(registration, registration.getPort()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deregister(Registration registration) {
|
|
||||||
if (doneDeregister.compareAndSet(false, true)) {
|
|
||||||
target.deregister(registration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deregister() {
|
|
||||||
// 需要兼容其他 discovery, spring cloud deregister 统一幂等处理
|
|
||||||
if (registration != null && doneDeregister.compareAndSet(false, true)) {
|
|
||||||
target.deregister(registration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceRegistry<Registration> getTarget() {
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Registration getRegistration() {
|
|
||||||
return registration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
target.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStatus(Registration registration, String status) {
|
|
||||||
target.setStatus(registration, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T getStatus(Registration registration) {
|
|
||||||
return target.getStatus(registration);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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.tencent.cloud.plugin.lossless;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.lossless.config.LosslessProperties;
|
||||||
|
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
|
||||||
|
import com.tencent.polaris.api.pojo.BaseInstance;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercept for of register and deregister.
|
||||||
|
*
|
||||||
|
* @author Shedfree Wu
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
public class LosslessRegistryAspect {
|
||||||
|
|
||||||
|
private ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
|
private Registration registration;
|
||||||
|
|
||||||
|
private LosslessProperties losslessProperties;
|
||||||
|
|
||||||
|
private PolarisSDKContextManager polarisSDKContextManager;
|
||||||
|
|
||||||
|
private final AtomicBoolean doneDeregister = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
|
||||||
|
public LosslessRegistryAspect(ServiceRegistry serviceRegistry, Registration registration,
|
||||||
|
LosslessProperties losslessProperties, PolarisSDKContextManager polarisSDKContextManager) {
|
||||||
|
this.serviceRegistry = serviceRegistry;
|
||||||
|
this.registration = registration;
|
||||||
|
this.losslessProperties = losslessProperties;
|
||||||
|
this.polarisSDKContextManager = polarisSDKContextManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pointcut("execution(public * org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(..))")
|
||||||
|
public void registerPointcut() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pointcut("execution(public * org.springframework.cloud.client.serviceregistry.ServiceRegistry.deregister(..))")
|
||||||
|
public void deregisterPointcut() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("registerPointcut()")
|
||||||
|
public Object invokeRegister(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
|
||||||
|
// web started, get port from registration
|
||||||
|
BaseInstance instance = SpringCloudLosslessActionProvider.getBaseInstance(registration);
|
||||||
|
|
||||||
|
Runnable registerAction = () -> executeJoinPoint(joinPoint);
|
||||||
|
|
||||||
|
SpringCloudLosslessActionProvider losslessActionProvider =
|
||||||
|
new SpringCloudLosslessActionProvider(serviceRegistry, registration, losslessProperties, registerAction);
|
||||||
|
|
||||||
|
polarisSDKContextManager.getLosslessAPI().setLosslessActionProvider(instance, losslessActionProvider);
|
||||||
|
polarisSDKContextManager.getLosslessAPI().losslessRegister(instance);
|
||||||
|
// return void
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("deregisterPointcut()")
|
||||||
|
public Object invokeDeregister(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
if (doneDeregister.compareAndSet(false, true)) {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeJoinPoint(ProceedingJoinPoint joinPoint) {
|
||||||
|
try {
|
||||||
|
joinPoint.proceed();
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessServiceRegistryTest.java → spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java
8
spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessServiceRegistryTest.java → spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java
Loading…
Reference in new issue