parent
d721d27441
commit
0ed97436d5
@ -1,2 +1,4 @@
|
||||
# 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