diff --git a/client/all/pom.xml b/client/all/pom.xml index ede8b8508..efd3d7917 100644 --- a/client/all/pom.xml +++ b/client/all/pom.xml @@ -6,7 +6,7 @@ com.alipay.sofa registry-client-all - 5.2.1 + 5.3.0-SNAPSHOT ${project.groupId}:${project.artifactId} http://github.com/alipay/sofa-registry diff --git a/client/api/pom.xml b/client/api/pom.xml index fd492459c..a546a370c 100644 --- a/client/api/pom.xml +++ b/client/api/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-client-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/client/impl/pom.xml b/client/impl/pom.xml index 9b4b475e2..8631db0d6 100644 --- a/client/impl/pom.xml +++ b/client/impl/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-client-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/DefaultRegistryClientTest.java b/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/DefaultRegistryClientTest.java index 183ebb4ec..aba3677dc 100644 --- a/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/DefaultRegistryClientTest.java +++ b/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/DefaultRegistryClientTest.java @@ -16,6 +16,17 @@ */ package com.alipay.sofa.registry.client.provider; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.After; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.alipay.sofa.registry.client.api.ConfigDataObserver; import com.alipay.sofa.registry.client.api.Configurator; import com.alipay.sofa.registry.client.api.Publisher; @@ -31,16 +42,6 @@ import com.alipay.sofa.registry.core.model.PublisherRegister; import com.alipay.sofa.registry.core.model.ScopeEnum; import com.alipay.sofa.registry.core.model.SubscriberRegister; -import org.junit.After; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; /** * The type Default registry client test. @@ -89,7 +90,7 @@ public void registerPublisher() throws InterruptedException { defaultPublisher.republish("republish test"); - Thread.sleep(500L); + Thread.sleep(2000L); // register success when republish assertTrue(defaultPublisher.isRegistered()); } @@ -111,7 +112,7 @@ public void handleData(String dataId, UserData data) { assertNotNull(subscriber); assertEquals(dataId, subscriber.getDataId()); - Thread.sleep(500L); + Thread.sleep(2000L); RegisterCache registerCache = registryClient.getRegisterCache(); @@ -142,7 +143,7 @@ public void handleData(String dataId, ConfigData configData) { assertNotNull(configurator); assertEquals(dataId, configurator.getDataId()); - Thread.sleep(500L); + Thread.sleep(2000L); RegisterCache registerCache = registryClient.getRegisterCache(); @@ -164,7 +165,7 @@ public void unregisterSinglePublisherTest() throws InterruptedException { int unregisterCount = registryClient.unregister(dataId, null, RegistryType.PUBLISHER); assertEquals(1, unregisterCount); - Thread.sleep(500L); + Thread.sleep(2000L); Publisher temp = registryClient.getRegisterCache().getPublisherByRegistId( publisher.getRegistId()); @@ -185,7 +186,7 @@ public void unregisterSingleSubscriberTest() throws InterruptedException { int unregisterCount = registryClient.unregister(dataId, null, RegistryType.SUBSCRIBER); assertEquals(1, unregisterCount); - Thread.sleep(500L); + Thread.sleep(2000L); Subscriber temp = registryClient.getRegisterCache().getSubscriberByRegistId( subscriber.getRegistId()); @@ -206,7 +207,7 @@ public void unregisterSingleConfiguratorTest() throws InterruptedException { int unregisterCount = registryClient.unregister(dataId, null, RegistryType.CONFIGURATOR); assertEquals(1, unregisterCount); - Thread.sleep(500L); + Thread.sleep(2000L); Subscriber temp = registryClient.getRegisterCache().getSubscriberByRegistId( configurator.getRegistId()); @@ -236,13 +237,13 @@ public void unregisterMultiTest() throws InterruptedException { Subscriber subscriber2 = registryClient.register(subscriberRegistration2); - Thread.sleep(500L); + Thread.sleep(2000L); // 2. unregister publisher int unregisterCount = registryClient.unregister(dataId, null, RegistryType.PUBLISHER); assertEquals(2, unregisterCount); - Thread.sleep(500L); + Thread.sleep(2000L); // 3. check publisher register cache RegisterCache registerCache = registryClient.getRegisterCache(); @@ -256,7 +257,7 @@ public void unregisterMultiTest() throws InterruptedException { unregisterCount = registryClient.unregister(dataId, null, RegistryType.SUBSCRIBER); assertEquals(2, unregisterCount); - Thread.sleep(500L); + Thread.sleep(2000L); // 5. check subscriber register cache Subscriber tempSub = registerCache.getSubscriberByRegistId(subscriber1.getRegistId()); diff --git a/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/RegisterOrderTest.java b/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/RegisterOrderTest.java index 90117a8aa..2e23dd731 100644 --- a/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/RegisterOrderTest.java +++ b/client/impl/src/test/java/com/alipay/sofa/registry/client/provider/RegisterOrderTest.java @@ -16,6 +16,20 @@ */ package com.alipay.sofa.registry.client.provider; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.After; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.alipay.sofa.registry.client.api.Publisher; import com.alipay.sofa.registry.client.api.Subscriber; import com.alipay.sofa.registry.client.api.SubscriberDataObserver; @@ -26,19 +40,6 @@ import com.alipay.sofa.registry.core.model.DataBox; import com.alipay.sofa.registry.core.model.PublisherRegister; import com.alipay.sofa.registry.core.model.SubscriberRegister; -import org.junit.After; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; /** * @@ -126,7 +127,7 @@ public void publishAndUnregister() throws InterruptedException { // step 1 Publisher publisher = registryClient.register(new PublisherRegistration(dataId), data); - Thread.sleep(500L); + Thread.sleep(2000L); String registId = publisher.getRegistId(); PublisherRegister publisherRegister = mockServer.queryPubliser(registId); @@ -137,7 +138,7 @@ public void publishAndUnregister() throws InterruptedException { // step 2 publisher.unregister(); - Thread.sleep(500L); + Thread.sleep(2000L); assertNull(mockServer.queryPubliser(registId)); @@ -151,7 +152,7 @@ public void publishAndRefused() throws InterruptedException { // step 1 Publisher publisher = registryClient.register(new PublisherRegistration(data), data); - Thread.sleep(500L); + Thread.sleep(2000L); String registId = publisher.getRegistId(); PublisherRegister publisherRegister = mockServer.queryPubliser(registId); @@ -182,7 +183,7 @@ public void handleData(String dataId, UserData data) { Subscriber subscriber = registryClient.register(new SubscriberRegistration(dataId, dataObserver)); - Thread.sleep(500L); + Thread.sleep(2000L); String registId = subscriber.getRegistId(); SubscriberRegister subscriberRegister = mockServer.querySubscriber(registId); @@ -191,7 +192,7 @@ public void handleData(String dataId, UserData data) { // step 2 subscriber.unregister(); - Thread.sleep(500L); + Thread.sleep(2000L); assertNull(mockServer.queryPubliser(registId)); @@ -211,7 +212,7 @@ public void handleData(String dataId, UserData data) { Subscriber subscriber = registryClient.register(new SubscriberRegistration( "subscribeAndRefused", dataObserver)); - Thread.sleep(500L); + Thread.sleep(2000L); String registId = subscriber.getRegistId(); SubscriberRegister subscriberRegister = mockServer.querySubscriber(registId); diff --git a/client/log/pom.xml b/client/log/pom.xml index 3a4fadafe..04d11fb22 100644 --- a/client/log/pom.xml +++ b/client/log/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-client-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/client/pom.xml b/client/pom.xml index 81e03c0ee..06f6a72a6 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -7,7 +7,7 @@ com.alipay.sofa registry-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml diff --git a/core/pom.xml b/core/pom.xml index eb3274277..8b9bf5306 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 06131c07f..19d72061d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,11 +2,11 @@ - 4.0.0 + com.alipay.sofa registry-parent - 5.2.1 + 5.3.0-SNAPSHOT pom ${project.groupId}:${project.artifactId} @@ -307,6 +307,12 @@ ${metrics.version} + + commons-collections + commons-collections + 3.2.2 + + junit @@ -396,6 +402,9 @@ org.apache.maven.plugins maven-surefire-plugin 2.21.0 + + once + org.jacoco diff --git a/server/common/model/pom.xml b/server/common/model/pom.xml index 3c1143ac3..48974de3d 100644 --- a/server/common/model/pom.xml +++ b/server/common/model/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-common - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/CommonResponse.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/CommonResponse.java index e85455adf..72f7d5591 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/CommonResponse.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/CommonResponse.java @@ -108,4 +108,16 @@ public String getMessage() { public void setMessage(String message) { this.message = message; } + + /** + * @see Object#toString() + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("CommonResponse{"); + sb.append("success=").append(success); + sb.append(", message='").append(message).append('\''); + sb.append('}'); + return sb.toString(); + } } \ No newline at end of file diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/DatumSnapshotRequest.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/DatumSnapshotRequest.java new file mode 100644 index 000000000..0b517fa61 --- /dev/null +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/DatumSnapshotRequest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.common.model; + +import java.io.Serializable; +import java.util.List; + +import com.alipay.sofa.registry.common.model.store.Publisher; + +/** + * + * @author shangyu.wh + * @version $Id: DatumSnapshotRequest.java, v 0.1 2019-05-30 11:09 shangyu.wh Exp $ + */ +public class DatumSnapshotRequest implements Serializable { + + private static final long serialVersionUID = 2193212935059863551L; + + private final String connectId; + + private final String dataServerIp; + + private final List publishers; + + public DatumSnapshotRequest(String connectId, String dataServerIp, List publishers) { + this.connectId = connectId; + this.dataServerIp = dataServerIp; + this.publishers = publishers; + } + + /** + * Getter method for property connectId. + * + * @return property value of connectId + */ + public String getConnectId() { + return connectId; + } + + /** + * Getter method for property dataServerIp. + * + * @return property value of dataServerIp + */ + public String getDataServerIp() { + return dataServerIp; + } + + /** + * Getter method for property publishers. + * + * @return property value of publishers + */ + public List getPublishers() { + return publishers; + } + + /** + * @see Object#toString() + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("DatumSnapshotRequest{"); + sb.append("connectId='").append(connectId).append('\''); + sb.append(", dataServerIp='").append(dataServerIp).append('\''); + sb.append(", publishers.size=").append(publishers.size()); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/PublisherDigestUtil.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/PublisherDigestUtil.java new file mode 100644 index 000000000..67ad72236 --- /dev/null +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/PublisherDigestUtil.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.common.model; + +import java.util.Collection; + +import com.alipay.sofa.registry.common.model.store.Publisher; + +/** + * + * @author kezhu.wukz + * @author shangyu.wh + * @version $Id: PublisherDigestUtil.java, v 0.1 2019-05-30 20:58 shangyu.wh Exp $ + */ +public class PublisherDigestUtil { + + public static long getDigestValueSum(Collection publishers) { + long digest = 0L; + if (publishers != null && !publishers.isEmpty()) { + for (Publisher publisher : publishers) { + digest += getDigestValue(publisher); + } + } + return digest; + } + + public static long getDigestValue(Publisher publisher) { + String registerId = publisher.getRegisterId(); + Long version = publisher.getVersion(); + long registerTimestamp = publisher.getRegisterTimestamp(); + long result = registerId != null ? registerId.hashCode() : 0; + result = 31 * result + (version != null ? version.hashCode() : 0); + result = 31 * result + (int) (registerTimestamp ^ (registerTimestamp >>> 32)); + return result; + } +} \ No newline at end of file diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/RenewDatumRequest.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/RenewDatumRequest.java new file mode 100644 index 000000000..603c40fb3 --- /dev/null +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/RenewDatumRequest.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.common.model; + +import java.io.Serializable; + +/** + * + * @author shangyu.wh + * @author kezhu.wukz + * @version $Id: RenewRequest.java, v 0.1 2019-05-30 10:58 shangyu.wh Exp $ + */ +public class RenewDatumRequest implements Serializable { + + private static final long serialVersionUID = 683097441984338311L; + + private final String connectId; + + private final String dataServerIP; + + private final String digestSum; + + public RenewDatumRequest(String connectId, String dataServerIP, String digestSum) { + this.connectId = connectId; + this.dataServerIP = dataServerIP; + this.digestSum = digestSum; + } + + /** + * Getter method for property connectId. + * + * @return property value of connectId + */ + public String getConnectId() { + return connectId; + } + + /** + * Getter method for property dataServerIP. + * + * @return property value of dataServerIP + */ + public String getDataServerIP() { + return dataServerIP; + } + + /** + * Getter method for property digestSum. + * + * @return property value of digestSum + */ + public String getDigestSum() { + return digestSum; + } + + /** + * @see Object#toString() + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("RenewDatumRequest{"); + sb.append("connectId='").append(connectId).append('\''); + sb.append(", dataServerIP='").append(dataServerIP).append('\''); + sb.append(", digestSum='").append(digestSum).append('\''); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/constants/ValueConstants.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/constants/ValueConstants.java index bd6f20409..005127563 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/constants/ValueConstants.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/constants/ValueConstants.java @@ -56,4 +56,12 @@ public class ValueConstants { public static final String STOP_PUSH_DATA_SWITCH_DATA_ID = "session.stop.push.data.switch#@#9600#@#CONFIG"; + public static final String BLACK_LIST_DATA_ID = "session.blacklist.data#@#9600#@#CONFIG"; + + public static final String ENABLE_DATA_RENEW_SNAPSHOT = "session.enable.datum.renew.switch#@#9600#@#CONFIG"; + + public static final String ENABLE_DATA_DATUM_EXPIRE = "data.enable.datum.expire.switch#@#9600#@#CONFIG"; + + public static final String LOGGER_NAME_RENEW = "RENEW-LOGGER"; + } diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/Datum.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/Datum.java index 61044ea8f..246363fa0 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/Datum.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/Datum.java @@ -16,13 +16,14 @@ */ package com.alipay.sofa.registry.common.model.dataserver; -import com.alipay.sofa.registry.common.model.store.Publisher; -import com.alipay.sofa.registry.common.model.store.WordCache; - import java.io.Serializable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.common.model.store.WordCache; +import com.alipay.sofa.registry.util.DatumVersionUtil; + /** * datum store in dataserver * @@ -96,7 +97,7 @@ public Datum(Publisher publisher, String dataCenter, long version) { } public void updateVersion() { - this.version = System.currentTimeMillis(); + this.version = DatumVersionUtil.nextId(); } /** diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/SessionServerRegisterRequest.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/SessionServerRegisterRequest.java index 16f00f56b..b852aa3ef 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/SessionServerRegisterRequest.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/SessionServerRegisterRequest.java @@ -30,16 +30,16 @@ public class SessionServerRegisterRequest implements Serializable { private String processId; - private Set clientHosts; + private Set connectIds; /** * constructor * @param processId - * @param clientHosts + * @param connectIds */ - public SessionServerRegisterRequest(String processId, Set clientHosts) { + public SessionServerRegisterRequest(String processId, Set connectIds) { this.processId = processId; - this.clientHosts = clientHosts; + this.connectIds = connectIds; } /** @@ -61,17 +61,17 @@ public void setProcessId(String processId) { } /** - * Getter method for property clientHosts. + * Getter method for property connectIds. * - * @return property value of clientHosts + * @return property value of connectIds */ - public Set getClientHosts() { - return clientHosts; + public Set getConnectIds() { + return connectIds; } @Override public String toString() { return new StringBuilder("[SessionServerRegisterRequest] processId=") - .append(this.processId).append(", clientHosts=").append(this.clientHosts).toString(); + .append(this.processId).append(", connectIds=").append(this.connectIds).toString(); } } \ No newline at end of file diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/UnPublishDataRequest.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/UnPublishDataRequest.java index cfa8554ac..33fbdbf0c 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/UnPublishDataRequest.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/dataserver/UnPublishDataRequest.java @@ -34,12 +34,6 @@ public class UnPublishDataRequest implements Serializable { private long registerTimestamp; - /** - * constructor - */ - public UnPublishDataRequest() { - } - /** * construtor * @param dataInfoId diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/NotifyProvideDataChange.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/NotifyProvideDataChange.java index ad14df8f0..a72d16d12 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/NotifyProvideDataChange.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/NotifyProvideDataChange.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.common.model.metaserver; +import com.alipay.sofa.registry.common.model.Node.NodeType; + import java.io.Serializable; /** @@ -31,6 +33,8 @@ public class NotifyProvideDataChange implements Serializable { private DataOperator dataOperator; + private NodeType nodeType = NodeType.SESSION; + /** * constructor * @param dataInfoId @@ -97,12 +101,31 @@ public void setDataOperator(DataOperator dataOperator) { this.dataOperator = dataOperator; } + /** + * Getter method for property nodeType. + * + * @return property value of nodeType + */ + public NodeType getNodeType() { + return nodeType; + } + + /** + * Setter method for property nodeType. + * + * @param nodeType value to be assigned to property nodeType + */ + public void setNodeType(NodeType nodeType) { + this.nodeType = nodeType; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder("NotifyProvideDataChange{"); sb.append("dataInfoId='").append(dataInfoId).append('\''); sb.append(", version=").append(version); sb.append(", dataOperator=").append(dataOperator); + sb.append(", nodeType=").append(nodeType); sb.append('}'); return sb.toString(); } diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/ReNewNodesRequest.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/RenewNodesRequest.java similarity index 92% rename from server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/ReNewNodesRequest.java rename to server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/RenewNodesRequest.java index 50485e65c..0794e5152 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/ReNewNodesRequest.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/metaserver/RenewNodesRequest.java @@ -16,16 +16,16 @@ */ package com.alipay.sofa.registry.common.model.metaserver; -import com.alipay.sofa.registry.common.model.Node; - import java.io.Serializable; +import com.alipay.sofa.registry.common.model.Node; + /** * * @author shangyu.wh * @version $Id: RenewNodesRequest.java, v 0.1 2018-03-30 19:51 shangyu.wh Exp $ */ -public class ReNewNodesRequest implements Serializable { +public class RenewNodesRequest implements Serializable { private int duration; @@ -35,7 +35,7 @@ public class ReNewNodesRequest implements Serializable { * constructor * @param node */ - public ReNewNodesRequest(T node) { + public RenewNodesRequest(T node) { this.node = node; } @@ -68,7 +68,7 @@ public T getNode() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("ReNewNodesRequest{"); + final StringBuilder sb = new StringBuilder("RenewNodesRequest{"); sb.append("duration=").append(duration); sb.append(", node=").append(node); sb.append('}'); diff --git a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/store/StoreData.java b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/store/StoreData.java index 1ec2d9a66..5746a45f8 100644 --- a/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/store/StoreData.java +++ b/server/common/model/src/main/java/com/alipay/sofa/registry/common/model/store/StoreData.java @@ -27,7 +27,7 @@ public interface StoreData { * DataType enum */ enum DataType { - SUBSCRIBER, PUBLISHER, WATCHER, UNPUBLISHER + SUBSCRIBER, PUBLISHER, WATCHER, UN_PUBLISHER } /** diff --git a/server/common/pom.xml b/server/common/pom.xml index 7b6197896..0c4e482e3 100644 --- a/server/common/pom.xml +++ b/server/common/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/common/util/pom.xml b/server/common/util/pom.xml index 620f9a2cd..a41fc6708 100644 --- a/server/common/util/pom.xml +++ b/server/common/util/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-common - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/common/util/src/main/java/com/alipay/sofa/registry/metrics/ReporterUtils.java b/server/common/util/src/main/java/com/alipay/sofa/registry/metrics/ReporterUtils.java index fb5f24e36..7cc79bc33 100644 --- a/server/common/util/src/main/java/com/alipay/sofa/registry/metrics/ReporterUtils.java +++ b/server/common/util/src/main/java/com/alipay/sofa/registry/metrics/ReporterUtils.java @@ -16,12 +16,13 @@ */ package com.alipay.sofa.registry.metrics; +import java.util.concurrent.TimeUnit; + import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Slf4jReporter; -import java.util.concurrent.TimeUnit; - /** * * @author shangyu.wh @@ -29,6 +30,8 @@ */ public class ReporterUtils { + private static final Logger METRIC_LOGGER = LoggerFactory.getLogger("REGISTRY-METRICS"); + /** * start slf4j reporter * @param period @@ -46,4 +49,13 @@ public static void startSlf4jReporter(long period, MetricRegistry registry, Logg } } + + /** + * start slf4j reporter + * @param period + * @param registry + */ + public static void startSlf4jReporter(long period, MetricRegistry registry) { + startSlf4jReporter(period, registry, METRIC_LOGGER); + } } \ No newline at end of file diff --git a/server/common/util/src/main/java/com/alipay/sofa/registry/task/listener/TaskEvent.java b/server/common/util/src/main/java/com/alipay/sofa/registry/task/listener/TaskEvent.java index 3e1d354a4..d081446b9 100644 --- a/server/common/util/src/main/java/com/alipay/sofa/registry/task/listener/TaskEvent.java +++ b/server/common/util/src/main/java/com/alipay/sofa/registry/task/listener/TaskEvent.java @@ -16,12 +16,12 @@ */ package com.alipay.sofa.registry.task.listener; -import com.alipay.sofa.registry.task.TaskClosure; - import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import com.alipay.sofa.registry.task.TaskClosure; + /** * * @author shangyu.wh @@ -43,9 +43,12 @@ public enum TaskType { "SyncPublisherTask"), SYNC_SUBSCRIBER_TASK( "SyncSubscriberTask"), SESSION_REGISTER_DATA_TASK( "SessionRegisterDataTask"), PROVIDE_DATA_CHANGE_FETCH_TASK( - "ProvideDataChangeFetchTask"), - - SUBSCRIBER_MULTI_FETCH_TASK("SubscriberMultiFetchTask"), + "ProvideDataChangeFetchTask"), SUBSCRIBER_MULTI_FETCH_TASK( + "SubscriberMultiFetchTask"), PUBLISH_DATA_TASK( + "PublishDataTask"), UN_PUBLISH_DATA_TASK( + "UnPublishDataTask"), RENEW_DATUM_TASK( + "RenewDatumTask"), DATUM_SNAPSHOT_TASK( + "DatumSnapshotTask"), //Session Adapter task USER_DATA_ELEMENT_PUSH_TASK("UserDataElementPushTask"), USER_DATA_ELEMENT_MULTI_PUSH_TASK( @@ -55,7 +58,7 @@ public enum TaskType { SESSION_NODE_CHANGE_PUSH_TASK("SessionNodeChangePushTask"), DATA_NODE_CHANGE_PUSH_TASK( "DataNodeChangePushTask"), RECEIVE_STATUS_CONFIRM_NOTIFY_TASK( "ReceiveStatusConfirmNotifyTask"), PERSISTENCE_DATA_CHANGE_NOTIFY_TASK( - "PersistenceDataChangeNotifyTask"); + "PersistenceDataChangeNotifyTask"), ; private String name; diff --git a/server/common/util/src/main/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimer.java b/server/common/util/src/main/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimer.java index f6cd4d206..7119a88a8 100644 --- a/server/common/util/src/main/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimer.java +++ b/server/common/util/src/main/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimer.java @@ -16,45 +16,66 @@ */ package com.alipay.sofa.registry.timer; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timeout; -import io.netty.util.TimerTask; - import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.TimerTask; + /** * based on HashedWheelTimer, add function: exec TimerTask async * - * @author kezhu.wukz + * @author kezhu.wukz * @version $Id: AsyncHashedWheelTimer.java, v 0.1 2019-01-11 10:54 AM kezhu.wukz Exp $ */ public class AsyncHashedWheelTimer extends HashedWheelTimer { /** */ - private final Executor executor; + protected final Executor executor; /** */ - private final TaskFailedCallback taskFailedCallback; + protected final TaskFailedCallback taskFailedCallback; /** - * * @param threadFactory * @param tickDuration * @param unit * @param ticksPerWheel + * @param threadSize + * @param queueSize * @param asyncThreadFactory */ public AsyncHashedWheelTimer(ThreadFactory threadFactory, long tickDuration, TimeUnit unit, - int ticksPerWheel, ThreadFactory asyncThreadFactory, + int ticksPerWheel, int threadSize, int queueSize, + ThreadFactory asyncThreadFactory, TaskFailedCallback taskFailedCallback) { super(threadFactory, tickDuration, unit, ticksPerWheel); - this.executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), asyncThreadFactory); + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(threadSize, threadSize, + 300L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(queueSize), asyncThreadFactory); + threadPoolExecutor.allowCoreThreadTimeOut(true); + this.executor = threadPoolExecutor; + this.taskFailedCallback = taskFailedCallback; + } + + /** + * + * @param threadFactory + * @param tickDuration + * @param unit + * @param ticksPerWheel + * @param asyncExecutor + */ + public AsyncHashedWheelTimer(ThreadFactory threadFactory, long tickDuration, TimeUnit unit, + int ticksPerWheel, Executor asyncExecutor, + TaskFailedCallback taskFailedCallback) { + super(threadFactory, tickDuration, unit, ticksPerWheel); + + this.executor = asyncExecutor; this.taskFailedCallback = taskFailedCallback; } @@ -85,14 +106,14 @@ public AsyncTimerTask(TimerTask timerTask) { /** */ @Override - public void run(Timeout timeout) throws Exception { + public void run(Timeout timeout) { this.timeout = timeout; try { AsyncHashedWheelTimer.this.executor.execute(this); } catch (RejectedExecutionException e) { taskFailedCallback.executionRejected(e); } catch (Throwable e) { - taskFailedCallback.executionRejected(e); + taskFailedCallback.executionFailed(e); } } diff --git a/server/common/util/src/main/java/com/alipay/sofa/registry/timer/RecycleAsyncHashedWheelTimer.java b/server/common/util/src/main/java/com/alipay/sofa/registry/timer/RecycleAsyncHashedWheelTimer.java new file mode 100644 index 000000000..fb3a0bd63 --- /dev/null +++ b/server/common/util/src/main/java/com/alipay/sofa/registry/timer/RecycleAsyncHashedWheelTimer.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.timer; + +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; + +import io.netty.util.Timeout; +import io.netty.util.TimerTask; + +/** + * + * @author kezhu.wukz + * @version $Id: RecycleAsyncHashedWheelTimer.java, v 0.1 2019-07-27 10:54 kezhu.wukz Exp $ + */ +public class RecycleAsyncHashedWheelTimer extends AsyncHashedWheelTimer { + + public RecycleAsyncHashedWheelTimer(ThreadFactory threadFactory, long tickDuration, + TimeUnit unit, int ticksPerWheel, int threadSize, + int queueSize, ThreadFactory asyncThreadFactory, + TaskFailedCallback taskFailedCallback) { + super(threadFactory, tickDuration, unit, ticksPerWheel, threadSize, queueSize, + asyncThreadFactory, taskFailedCallback); + } + + public RecycleAsyncHashedWheelTimer(ThreadFactory threadFactory, long tickDuration, + TimeUnit unit, int ticksPerWheel, Executor asyncExecutor, + TaskFailedCallback taskFailedCallback) { + super(threadFactory, tickDuration, unit, ticksPerWheel, asyncExecutor, taskFailedCallback); + } + + public Timeout newTimeout(TimerTask task, long firstDelay, long recycleDelay, TimeUnit unit, + BooleanSupplier checkCondition) { + + return super.newTimeout( + new RecycleAsyncTimerTask(task, recycleDelay, unit, checkCondition), firstDelay, unit); + } + + public Timeout newTimeout(TimerTask task, long recycleDelay, TimeUnit unit, + BooleanSupplier checkCondition) { + + return super + .newTimeout(new RecycleAsyncTimerTask(task, recycleDelay, unit, checkCondition), + recycleDelay, unit); + } + + /** + * + */ + class RecycleAsyncTimerTask implements TimerTask, Runnable { + /** */ + private final TimerTask timerTask; + + private final long recycleDelay; + + private final TimeUnit delayUnit; + + private final BooleanSupplier checkCondition; + + /** */ + private Timeout timeout; + + /** + * @param timerTask + */ + public RecycleAsyncTimerTask(TimerTask timerTask, long recycleDelay, TimeUnit unit, + BooleanSupplier checkCondition) { + super(); + this.timerTask = timerTask; + this.recycleDelay = recycleDelay; + this.delayUnit = unit; + this.checkCondition = checkCondition; + } + + /** + */ + @Override + public void run(Timeout timeout) { + this.timeout = timeout; + try { + RecycleAsyncHashedWheelTimer.super.executor.execute(this); + } catch (RejectedExecutionException e) { + taskFailedCallback.executionRejected(e); + } catch (Throwable e) { + taskFailedCallback.executionFailed(e); + } + } + + /** + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + this.timerTask.run(this.timeout); + } catch (Throwable e) { + taskFailedCallback.executionFailed(e); + } finally { + if (checkCondition.getAsBoolean()) { + RecycleAsyncHashedWheelTimer.this.newTimeout(timerTask, recycleDelay, + delayUnit, checkCondition); + } + } + } + + } + +} \ No newline at end of file diff --git a/server/common/util/src/main/java/com/alipay/sofa/registry/util/DatumVersionUtil.java b/server/common/util/src/main/java/com/alipay/sofa/registry/util/DatumVersionUtil.java new file mode 100644 index 000000000..78112433b --- /dev/null +++ b/server/common/util/src/main/java/com/alipay/sofa/registry/util/DatumVersionUtil.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.util; + +/** + * generates ID: 49 bit millisecond timestamp + 15 bit incremental ID + * + * refer to: https://github.com/twitter/snowflake + * + * @author kezhu.wukz + * @version $Id: DatumVersionUtil.java, v 0.1 2019-07-04 22:05 kezhu.wukz Exp $ + */ +public class DatumVersionUtil { + + private static long sequence = 0L; + + /** Tue Jan 01 00:00:00 CST 2019 */ + private static long twepoch = 1546272000000L; + + private static long sequenceBits = 15L; + private static long timestampLeftShift = sequenceBits; + private static long sequenceMask = -1L ^ (-1L << sequenceBits); + + private static long lastTimestamp = -1L; + + public synchronized static long nextId() { + long timestamp = timeGen(); + + if (timestamp < lastTimestamp) { + throw new RuntimeException(String.format( + "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp + - timestamp)); + } + + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + timestamp = untilNextMillis(lastTimestamp); + } + } else { + sequence = 0L; + } + + lastTimestamp = timestamp; + + return ((timestamp - twepoch) << timestampLeftShift) | sequence; + } + + public static long getRealTimestamp(long id) { + return (id >> timestampLeftShift) + twepoch; + } + + private static long untilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private static long timeGen() { + return System.currentTimeMillis(); + } + +} \ No newline at end of file diff --git a/server/common/util/src/test/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimerTest.java b/server/common/util/src/test/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimerTest.java index 11b63f53b..dbabd7faf 100644 --- a/server/common/util/src/test/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimerTest.java +++ b/server/common/util/src/test/java/com/alipay/sofa/registry/timer/AsyncHashedWheelTimerTest.java @@ -16,13 +16,15 @@ */ package com.alipay.sofa.registry.timer; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.netty.util.Timer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import org.junit.Assert; import org.junit.Test; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import io.netty.util.Timer; /** * @author xuanbei @@ -40,7 +42,7 @@ public void doTest() throws InterruptedException { ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); threadFactoryBuilder.setDaemon(true); final Timer timer = new AsyncHashedWheelTimer(threadFactoryBuilder.setNameFormat( - "AsyncHashedWheelTimerTest").build(), 50, TimeUnit.MILLISECONDS, 10, + "AsyncHashedWheelTimerTest").build(), 50, TimeUnit.MILLISECONDS, 10, 5, 10, threadFactoryBuilder.setNameFormat("Registry-DataNodeServiceImpl-WheelExecutor-%d") .build(), new AsyncHashedWheelTimer.TaskFailedCallback() { @Override diff --git a/server/consistency/pom.xml b/server/consistency/pom.xml index 46013874e..9c52b6b98 100644 --- a/server/consistency/pom.xml +++ b/server/consistency/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/distribution/data/pom.xml b/server/distribution/data/pom.xml index ca808857c..444cabe65 100644 --- a/server/distribution/data/pom.xml +++ b/server/distribution/data/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-distribution - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/distribution/integration/pom.xml b/server/distribution/integration/pom.xml index c76f59ed8..8118951ca 100644 --- a/server/distribution/integration/pom.xml +++ b/server/distribution/integration/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-distribution - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/distribution/meta/pom.xml b/server/distribution/meta/pom.xml index 3cdc41546..512053820 100644 --- a/server/distribution/meta/pom.xml +++ b/server/distribution/meta/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-distribution - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/distribution/pom.xml b/server/distribution/pom.xml index 67cf7b9ba..ec4b3de52 100644 --- a/server/distribution/pom.xml +++ b/server/distribution/pom.xml @@ -6,7 +6,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/distribution/session/pom.xml b/server/distribution/session/pom.xml index 7f9fdd96d..ca9f732ec 100644 --- a/server/distribution/session/pom.xml +++ b/server/distribution/session/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-distribution - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/pom.xml b/server/pom.xml index c06d833c3..d2f9f1782 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -7,7 +7,7 @@ com.alipay.sofa registry-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml diff --git a/server/remoting/api/pom.xml b/server/remoting/api/pom.xml index 68ef027a5..620b1f1e2 100644 --- a/server/remoting/api/pom.xml +++ b/server/remoting/api/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-remoting - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/Server.java b/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/Server.java index 7452bb4f4..900bedbcd 100644 --- a/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/Server.java +++ b/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/Server.java @@ -16,11 +16,11 @@ */ package com.alipay.sofa.registry.remoting; -import com.alipay.sofa.registry.common.model.store.URL; - import java.net.InetSocketAddress; import java.util.Collection; +import com.alipay.sofa.registry.common.model.store.URL; + /** * * @author shangyu.wh @@ -57,4 +57,6 @@ public interface Server extends Endpoint { * @return channel */ Channel getChannel(URL url); + + int getChannelCount(); } \ No newline at end of file diff --git a/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/exchange/RequestException.java b/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/exchange/RequestException.java index 3340bbf4b..6f00d8edb 100644 --- a/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/exchange/RequestException.java +++ b/server/remoting/api/src/main/java/com/alipay/sofa/registry/remoting/exchange/RequestException.java @@ -77,14 +77,14 @@ public RequestException(Throwable cause) { * get requestInfo from Request * @return */ - public String getRequestMessage() { + @Override + public String getMessage() { StringBuilder sb = new StringBuilder(); if (request != null) { - sb.append("Request url:").append(request.getRequestUrl()).append(" body:") - .append(request.getRequestBody()); - } else { - sb.append("Request data can not be null!"); + sb.append("request url: ").append(request.getRequestUrl()).append(", body: ") + .append(request.getRequestBody()).append(", "); } + sb.append(super.getMessage()); return sb.toString(); } } \ No newline at end of file diff --git a/server/remoting/api/src/test/java/com/alipay/sofa/registry/remoting/RequestExceptionTest.java b/server/remoting/api/src/test/java/com/alipay/sofa/registry/remoting/RequestExceptionTest.java index 7f98cc690..03c7f8526 100644 --- a/server/remoting/api/src/test/java/com/alipay/sofa/registry/remoting/RequestExceptionTest.java +++ b/server/remoting/api/src/test/java/com/alipay/sofa/registry/remoting/RequestExceptionTest.java @@ -16,11 +16,12 @@ */ package com.alipay.sofa.registry.remoting; +import org.junit.Assert; +import org.junit.Test; + import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.remoting.exchange.RequestException; import com.alipay.sofa.registry.remoting.exchange.message.Request; -import org.junit.Assert; -import org.junit.Test; /** * @author xuanbei @@ -31,18 +32,16 @@ public class RequestExceptionTest { public void doTest() { RequestException exception = new RequestException("error message"); Assert.assertEquals("error message", exception.getMessage()); - Assert.assertEquals("Request data can not be null!", exception.getRequestMessage()); RuntimeException runtimeException = new RuntimeException("error message"); exception = new RequestException(runtimeException); Assert.assertEquals("java.lang.RuntimeException: error message", exception.getMessage()); Assert.assertEquals(runtimeException, exception.getCause()); - Assert.assertEquals("Request data can not be null!", exception.getRequestMessage()); + Assert.assertEquals("java.lang.RuntimeException: error message", exception.getMessage()); exception = new RequestException("error message", runtimeException); Assert.assertEquals("error message", exception.getMessage()); Assert.assertEquals(runtimeException, exception.getCause()); - Assert.assertEquals("Request data can not be null!", exception.getRequestMessage()); Request request = new Request() { @Override @@ -56,11 +55,11 @@ public URL getRequestUrl() { } }; exception = new RequestException("error message", request); - Assert.assertEquals("error message", exception.getMessage()); - Assert.assertEquals("Request url:null body:request body", exception.getRequestMessage()); + Assert.assertEquals("request url: null, body: request body, error message", + exception.getMessage()); exception = new RequestException("error message", request, runtimeException); - Assert.assertEquals("error message", exception.getMessage()); - Assert.assertEquals("Request url:null body:request body", exception.getRequestMessage()); + Assert.assertEquals("request url: null, body: request body, error message", + exception.getMessage()); } } diff --git a/server/remoting/bolt/pom.xml b/server/remoting/bolt/pom.xml index f8ce4f01b..2f7d8a849 100644 --- a/server/remoting/bolt/pom.xml +++ b/server/remoting/bolt/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-remoting - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/remoting/bolt/src/main/java/com/alipay/sofa/registry/remoting/bolt/BoltServer.java b/server/remoting/bolt/src/main/java/com/alipay/sofa/registry/remoting/bolt/BoltServer.java index e9fc9ed38..af2c3d71a 100644 --- a/server/remoting/bolt/src/main/java/com/alipay/sofa/registry/remoting/bolt/BoltServer.java +++ b/server/remoting/bolt/src/main/java/com/alipay/sofa/registry/remoting/bolt/BoltServer.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.remoting.bolt; +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; + import com.alipay.remoting.Connection; import com.alipay.remoting.ConnectionEventType; import com.alipay.remoting.InvokeCallback; @@ -33,16 +43,6 @@ import com.alipay.sofa.registry.remoting.ChannelHandler.InvokeType; import com.alipay.sofa.registry.remoting.Server; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; - /** * * @author shangyu.wh @@ -342,4 +342,9 @@ public void removeChannel(Channel channel) { public RpcServer getRpcServer() { return boltServer; } + + @Override + public int getChannelCount() { + return channels.size(); + } } \ No newline at end of file diff --git a/server/remoting/http/pom.xml b/server/remoting/http/pom.xml index 10ba2a2df..bff60eaf9 100644 --- a/server/remoting/http/pom.xml +++ b/server/remoting/http/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-remoting - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/remoting/http/src/main/java/com/alipay/sofa/registry/remoting/jersey/JerseyJettyServer.java b/server/remoting/http/src/main/java/com/alipay/sofa/registry/remoting/jersey/JerseyJettyServer.java index 680384881..9907c2f31 100644 --- a/server/remoting/http/src/main/java/com/alipay/sofa/registry/remoting/jersey/JerseyJettyServer.java +++ b/server/remoting/http/src/main/java/com/alipay/sofa/registry/remoting/jersey/JerseyJettyServer.java @@ -16,14 +16,15 @@ */ package com.alipay.sofa.registry.remoting.jersey; -import com.alipay.sofa.registry.common.model.store.URL; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; -import com.alipay.sofa.registry.remoting.CallbackHandler; -import com.alipay.sofa.registry.remoting.Channel; -import com.alipay.sofa.registry.remoting.ChannelHandler; -import com.alipay.sofa.registry.remoting.Server; -import com.alipay.sofa.registry.remoting.jersey.jetty.server.HttpConnectionCustomFactory; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.ws.rs.ProcessingException; + import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -35,13 +36,14 @@ import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.spi.Container; -import javax.ws.rs.ProcessingException; -import java.net.InetSocketAddress; -import java.net.URI; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicBoolean; +import com.alipay.sofa.registry.common.model.store.URL; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.CallbackHandler; +import com.alipay.sofa.registry.remoting.Channel; +import com.alipay.sofa.registry.remoting.ChannelHandler; +import com.alipay.sofa.registry.remoting.Server; +import com.alipay.sofa.registry.remoting.jersey.jetty.server.HttpConnectionCustomFactory; /** * @@ -224,4 +226,9 @@ public URI getBaseUri() { return baseUri; } + @Override + public int getChannelCount() { + return 0; + } + } \ No newline at end of file diff --git a/server/remoting/pom.xml b/server/remoting/pom.xml index 9a2d45c9c..29e168179 100644 --- a/server/remoting/pom.xml +++ b/server/remoting/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/server/data/pom.xml b/server/server/data/pom.xml index 6eb886b28..cefa28648 100644 --- a/server/server/data/pom.xml +++ b/server/server/data/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 @@ -73,6 +73,10 @@ commons-lang commons-lang + + commons-collections + commons-collections + junit junit diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBeanConfiguration.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBeanConfiguration.java index 776982906..155861aab 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBeanConfiguration.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBeanConfiguration.java @@ -16,17 +16,35 @@ */ package com.alipay.sofa.registry.server.data.bootstrap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + import com.alipay.sofa.registry.remoting.bolt.exchange.BoltExchange; import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.remoting.jersey.exchange.JerseyExchange; +import com.alipay.sofa.registry.server.data.cache.CacheDigestTask; import com.alipay.sofa.registry.server.data.cache.DataServerCache; +import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.data.change.DataChangeHandler; import com.alipay.sofa.registry.server.data.change.event.DataChangeEventCenter; import com.alipay.sofa.registry.server.data.change.notify.BackUpNotifier; import com.alipay.sofa.registry.server.data.change.notify.IDataChangeNotifier; import com.alipay.sofa.registry.server.data.change.notify.SessionServerNotifier; +import com.alipay.sofa.registry.server.data.change.notify.SnapshotBackUpNotifier; import com.alipay.sofa.registry.server.data.change.notify.TempPublisherNotifier; -import com.alipay.sofa.registry.server.data.correction.LocalDataServerCleanHandler; import com.alipay.sofa.registry.server.data.datasync.AcceptorStore; import com.alipay.sofa.registry.server.data.datasync.SyncDataService; import com.alipay.sofa.registry.server.data.datasync.sync.LocalAcceptorStore; @@ -53,12 +71,13 @@ import com.alipay.sofa.registry.server.data.remoting.dataserver.handler.SyncDataHandler; import com.alipay.sofa.registry.server.data.remoting.dataserver.task.AbstractTask; import com.alipay.sofa.registry.server.data.remoting.dataserver.task.ConnectionRefreshTask; -import com.alipay.sofa.registry.server.data.remoting.dataserver.task.ReNewNodeTask; +import com.alipay.sofa.registry.server.data.remoting.dataserver.task.RenewNodeTask; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractClientHandler; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.DefaultMetaServiceImpl; import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; import com.alipay.sofa.registry.server.data.remoting.metaserver.MetaServerConnectionFactory; +import com.alipay.sofa.registry.server.data.remoting.metaserver.handler.NotifyProvideDataChangeHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.handler.ServerChangeHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.handler.StatusConfirmHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.task.ConnectionRefreshMetaTask; @@ -68,26 +87,20 @@ import com.alipay.sofa.registry.server.data.remoting.sessionserver.forward.ForwardServiceImpl; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.ClientOffHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.DataServerConnectionHandler; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.DatumSnapshotHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.GetDataHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.GetDataVersionsHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.PublishDataHandler; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.RenewDatumHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.SessionServerRegisterHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.handler.UnPublishDataHandler; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; +import com.alipay.sofa.registry.server.data.renew.LocalDataServerCleanHandler; import com.alipay.sofa.registry.server.data.resource.DataDigestResource; import com.alipay.sofa.registry.server.data.resource.HealthResource; +import com.alipay.sofa.registry.server.data.util.ThreadPoolExecutorDataServer; +import com.alipay.sofa.registry.util.NamedThreadFactory; import com.alipay.sofa.registry.util.PropertySplitter; -import org.glassfish.jersey.jackson.JacksonFeature; -import org.glassfish.jersey.server.ResourceConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; /** * @@ -114,7 +127,8 @@ public CommonConfig commonConfig() { } @Bean - public DataServerConfig dataServerBootstrapConfig(CommonConfig commonConfig) { + @ConditionalOnMissingBean(name = "dataServerConfig") + public DataServerConfig dataServerConfig(CommonConfig commonConfig) { return new DataServerConfig(commonConfig); } @@ -123,10 +137,26 @@ public DataNodeStatus dataNodeStatus() { return new DataNodeStatus(); } + @Bean + public DatumCache datumCache() { + return new DatumCache(); + } + @Bean(name = "PropertySplitter") public PropertySplitter propertySplitter() { return new PropertySplitter(); } + + } + + @Configuration + public static class LogTaskConfigConfiguration { + + @Bean + public CacheDigestTask cacheDigestTask() { + return new CacheDigestTask(); + } + } @Configuration @@ -177,23 +207,25 @@ public MetaServerConnectionFactory metaServerConnectionFactory() { } @Bean(name = "serverHandlers") - public Collection serverHandlers(DataServerConfig dataServerBootstrapConfig) { + public Collection serverHandlers(DataServerConfig dataServerConfig) { Collection list = new ArrayList<>(); list.add(getDataHandler()); list.add(clientOffHandler()); list.add(getDataVersionsHandler()); - list.add(publishDataProcessor(dataServerBootstrapConfig)); + list.add(publishDataProcessor()); list.add(sessionServerRegisterHandler()); list.add(unPublishDataHandler()); list.add(dataServerConnectionHandler()); + list.add(renewDatumHandler()); + list.add(datumSnapshotHandler()); return list; } @Bean(name = "serverSyncHandlers") - public Collection serverSyncHandlers(DataServerConfig dataServerBootstrapConfig) { + public Collection serverSyncHandlers(DataServerConfig dataServerConfig) { Collection list = new ArrayList<>(); list.add(getDataHandler()); - list.add(publishDataProcessor(dataServerBootstrapConfig)); + list.add(publishDataProcessor()); list.add(unPublishDataHandler()); list.add(notifyFetchDatumHandler()); list.add(notifyOnlineHandler()); @@ -215,6 +247,7 @@ public Collection metaClientHandlers() { Collection list = new ArrayList<>(); list.add(serverChangeHandler()); list.add(statusConfirmHandler()); + list.add(notifyProvideDataChangeHandler()); return list; } @@ -244,8 +277,18 @@ public AbstractServerHandler clientOffHandler() { } @Bean - public AbstractServerHandler publishDataProcessor(DataServerConfig dataServerBootstrapConfig) { - return new PublishDataHandler(dataServerBootstrapConfig); + public AbstractServerHandler datumSnapshotHandler() { + return new DatumSnapshotHandler(); + } + + @Bean + public RenewDatumHandler renewDatumHandler() { + return new RenewDatumHandler(); + } + + @Bean + public AbstractServerHandler publishDataProcessor() { + return new PublishDataHandler(); } @Bean @@ -292,6 +335,11 @@ public AbstractClientHandler serverChangeHandler() { public AbstractClientHandler statusConfirmHandler() { return new StatusConfirmHandler(); } + + @Bean + public NotifyProvideDataChangeHandler notifyProvideDataChangeHandler() { + return new NotifyProvideDataChangeHandler(); + } } @Configuration @@ -316,6 +364,11 @@ public BackUpNotifier backUpNotifier() { return new BackUpNotifier(); } + @Bean + public SnapshotBackUpNotifier snapshotBackUpNotifier() { + return new SnapshotBackUpNotifier(); + } + @Bean(name = "dataChangeNotifiers") public List dataChangeNotifiers(DataServerConfig dataServerBootstrapConfig) { List list = new ArrayList<>(); @@ -378,6 +431,11 @@ public LocalDataServerCleanHandler localDataServerCleanHandler() { return new LocalDataServerCleanHandler(); } + @Bean + public DatumLeaseManager datumLeaseManager() { + return new DatumLeaseManager(); + } + @Bean public GetSyncDataHandler getSyncDataHandler() { return new GetSyncDataHandler(); @@ -413,8 +471,8 @@ public ConnectionRefreshMetaTask connectionRefreshMetaTask() { } @Bean - public ReNewNodeTask reNewNodeTask() { - return new ReNewNodeTask(); + public RenewNodeTask renewNodeTask() { + return new RenewNodeTask(); } @Bean(name = "tasks") @@ -422,7 +480,7 @@ public List tasks() { List list = new ArrayList<>(); list.add(connectionRefreshTask()); list.add(connectionRefreshMetaTask()); - list.add(reNewNodeTask()); + list.add(renewNodeTask()); return list; } @@ -462,9 +520,17 @@ public static class AfterWorkingProcessConfiguration { @Autowired AbstractClientHandler notifyDataSyncHandler; + @Autowired + RenewDatumHandler renewDatumHandler; + + @Autowired + DatumLeaseManager datumLeaseManager; + @Bean(name = "afterWorkProcessors") public List afterWorkingProcessors() { List list = new ArrayList<>(); + list.add(renewDatumHandler); + list.add(datumLeaseManager); list.add(disconnectEventHandler); list.add((NotifyDataSyncHandler) notifyDataSyncHandler); return list; @@ -476,4 +542,40 @@ public AfterWorkingProcessHandler afterWorkingProcessHandler() { } } + + @Configuration + public static class ExecutorConfiguration { + + @Autowired + DataServerConfig dataServerConfig; + + @Bean(name = "publishProcessorExecutor") + public ThreadPoolExecutor publishProcessorExecutor() { + return new ThreadPoolExecutorDataServer("PublishProcessorExecutor", + dataServerConfig.getPublishExecutorMinPoolSize(), + dataServerConfig.getPublishExecutorMaxPoolSize(), 300, TimeUnit.SECONDS, + new ArrayBlockingQueue<>(dataServerConfig.getPublishExecutorQueueSize()), + new NamedThreadFactory("DataServer-PublishProcessor-executor", true)); + } + + @Bean(name = "renewDatumProcessorExecutor") + public ThreadPoolExecutor renewDatumProcessorExecutor() { + return new ThreadPoolExecutorDataServer("RenewDatumProcessorExecutor", + dataServerConfig.getRenewDatumExecutorMinPoolSize(), + dataServerConfig.getRenewDatumExecutorMaxPoolSize(), 300, TimeUnit.SECONDS, + new ArrayBlockingQueue<>(dataServerConfig.getRenewDatumExecutorQueueSize()), + new NamedThreadFactory("DataServer-RenewDatumProcessor-executor", true)); + } + + @Bean(name = "getDataProcessorExecutor") + public ThreadPoolExecutor getDataProcessorExecutor() { + return new ThreadPoolExecutorDataServer("GetDataProcessorExecutor", + dataServerConfig.getGetDataExecutorMinPoolSize(), + dataServerConfig.getGetDataExecutorMaxPoolSize(), + dataServerConfig.getGetDataExecutorKeepAliveTime(), TimeUnit.SECONDS, + new ArrayBlockingQueue<>(dataServerConfig.getGetDataExecutorQueueSize()), + new NamedThreadFactory("DataServer-GetDataProcessor-executor", true)); + } + + } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBootstrap.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBootstrap.java index e42293b84..8cc934baf 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBootstrap.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerBootstrap.java @@ -16,6 +16,25 @@ */ package com.alipay.sofa.registry.server.data.bootstrap; +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import javax.annotation.Resource; +import javax.ws.rs.Path; +import javax.ws.rs.ext.Provider; + +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.metaserver.ProvideData; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; @@ -31,21 +50,7 @@ import com.alipay.sofa.registry.server.data.event.StartTaskTypeEnum; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; -import org.glassfish.jersey.server.ResourceConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.ApplicationContext; - -import javax.annotation.Resource; -import javax.ws.rs.Path; -import javax.ws.rs.ext.Provider; -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; /** * @@ -59,7 +64,7 @@ public class DataServerBootstrap { .getLogger(DataServerBootstrap.class); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private IMetaServerService metaServerService; @@ -82,12 +87,18 @@ public class DataServerBootstrap { @Autowired private EventCenter eventCenter; + @Autowired + private CacheDigestTask cacheDigestTask; + @Resource(name = "serverHandlers") private Collection serverHandlers; @Resource(name = "serverSyncHandlers") private Collection serverSyncHandlers; + @Autowired + private DatumLeaseManager datumLeaseManager; + private Server server; private Server dataSyncServer; @@ -107,7 +118,9 @@ public class DataServerBootstrap { */ public void start() { try { - LOGGER.info("[DataServerBootstrap] begin start server"); + LOGGER.info("begin start server"); + + LOGGER.info("the configuration items are as follows: " + dataServerConfig.toString()); openDataServer(); @@ -117,13 +130,15 @@ public void start() { startRaftClient(); + fetchProviderData(); + startScheduler(); Runtime.getRuntime().addShutdownHook(new Thread(this::doStop)); - LOGGER.info("[DataServerBootstrap] start server success"); + LOGGER.info("start server success"); } catch (Exception e) { - throw new RuntimeException("[DataServerBootstrap] start server error", e); + throw new RuntimeException("start server error", e); } } @@ -131,15 +146,13 @@ private void openDataServer() { try { if (serverForSessionStarted.compareAndSet(false, true)) { server = boltExchange.open(new URL(NetUtil.getLocalAddress().getHostAddress(), - dataServerBootstrapConfig.getPort()), serverHandlers + dataServerConfig.getPort()), serverHandlers .toArray(new ChannelHandler[serverHandlers.size()])); - LOGGER.info("Data server for session started! port:{}", - dataServerBootstrapConfig.getPort()); + LOGGER.info("Data server for session started! port:{}", dataServerConfig.getPort()); } } catch (Exception e) { serverForSessionStarted.set(false); - LOGGER - .error("Data server start error! port:{}", dataServerBootstrapConfig.getPort(), e); + LOGGER.error("Data server start error! port:{}", dataServerConfig.getPort(), e); throw new RuntimeException("Data server start error!", e); } } @@ -148,15 +161,15 @@ private void openDataSyncServer() { try { if (serverForDataSyncStarted.compareAndSet(false, true)) { dataSyncServer = boltExchange.open(new URL(NetUtil.getLocalAddress() - .getHostAddress(), dataServerBootstrapConfig.getSyncDataPort()), - serverSyncHandlers.toArray(new ChannelHandler[serverSyncHandlers.size()])); + .getHostAddress(), dataServerConfig.getSyncDataPort()), serverSyncHandlers + .toArray(new ChannelHandler[serverSyncHandlers.size()])); LOGGER.info("Data server for sync started! port:{}", - dataServerBootstrapConfig.getSyncDataPort()); + dataServerConfig.getSyncDataPort()); } } catch (Exception e) { serverForDataSyncStarted.set(false); LOGGER.error("Data sync server start error! port:{}", - dataServerBootstrapConfig.getSyncDataPort(), e); + dataServerConfig.getSyncDataPort(), e); throw new RuntimeException("Data sync server start error!", e); } } @@ -166,15 +179,15 @@ private void openHttpServer() { if (httpServerStarted.compareAndSet(false, true)) { bindResourceConfig(); httpServer = jerseyExchange.open( - new URL(NetUtil.getLocalAddress().getHostAddress(), dataServerBootstrapConfig + new URL(NetUtil.getLocalAddress().getHostAddress(), dataServerConfig .getHttpServerPort()), new ResourceConfig[] { jerseyResourceConfig }); LOGGER.info("Open http server port {} success!", - dataServerBootstrapConfig.getHttpServerPort()); + dataServerConfig.getHttpServerPort()); } } catch (Exception e) { httpServerStarted.set(false); - LOGGER.error("Open http server port {} error!", - dataServerBootstrapConfig.getHttpServerPort(), e); + LOGGER + .error("Open http server port {} error!", dataServerConfig.getHttpServerPort(), e); throw new RuntimeException("Open http server error!", e); } } @@ -182,21 +195,35 @@ private void openHttpServer() { private void startRaftClient() { metaServerService.startRaftClient(); eventCenter.post(new MetaServerChangeEvent(metaServerService.getMetaServerMap())); - LOGGER.info("[DataServerBootstrap] raft client started!Leader is {}", - metaServerService.getLeader()); + LOGGER.info("raft client started!Leader is {}", metaServerService.getLeader()); + } + + private void fetchProviderData() { + ProvideData provideData = metaServerService + .fetchData(ValueConstants.ENABLE_DATA_DATUM_EXPIRE); + if (provideData == null || provideData.getProvideData() == null + || provideData.getProvideData().getObject() == null) { + LOGGER + .info("Fetch enableDataDatumExpire but no data existed, current config not change!"); + return; + } + boolean enableDataDatumExpire = Boolean.parseBoolean((String) provideData.getProvideData() + .getObject()); + LOGGER.info("Fetch enableDataDatumExpire {} success!", enableDataDatumExpire); + datumLeaseManager.setRenewEnable(enableDataDatumExpire); } private void startScheduler() { try { if (schedulerStarted.compareAndSet(false, true)) { syncDataScheduler.startScheduler(); - // start all startTask except renew task + // start all startTask except correction task eventCenter.post(new StartTaskEvent( - Arrays.stream(StartTaskTypeEnum.values()).filter(type->type != StartTaskTypeEnum.RENEW).collect( - Collectors.toSet()))); + Arrays.stream(StartTaskTypeEnum.values()).filter(type -> type != StartTaskTypeEnum.RENEW) + .collect(Collectors.toSet()))); //start dump log - new CacheDigestTask().start(); + cacheDigestTask.start(); } } catch (Exception e) { schedulerStarted.set(false); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerConfig.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerConfig.java index aa0d2f3aa..6b47d4717 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerConfig.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/bootstrap/DataServerConfig.java @@ -16,15 +16,18 @@ */ package com.alipay.sofa.registry.server.data.bootstrap; -import com.alipay.sofa.registry.net.NetUtil; -import org.springframework.boot.context.properties.ConfigurationProperties; - import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import com.alipay.sofa.registry.net.NetUtil; + /** * * @@ -34,10 +37,11 @@ @ConfigurationProperties(prefix = DataServerConfig.PRE_FIX) public class DataServerConfig { - public static final String PRE_FIX = "data.server"; + public static final String PRE_FIX = "data.server"; - public static final String IP = NetUtil.getLocalAddress() - .getHostAddress(); + public static final String IP = NetUtil + .getLocalAddress() + .getHostAddress(); private int port; @@ -51,9 +55,9 @@ public class DataServerConfig { private int queueSize; - private int notifyIntervalMs = 500; + private int notifyIntervalMs; - private int clientOffDelayMs = 1000; + private int clientOffDelayMs; private int notifyTempDataIntervalMs; @@ -61,41 +65,59 @@ public class DataServerConfig { private CommonConfig commonConfig; - private Set metaIps = null; + private Set metaIps = null; + + private int storeNodes = 3; + + private int numberOfReplicas = 1000; + + private long localDataServerCleanDelay = 1000 * 60 * 30; + + private int getDataExecutorMinPoolSize = 80; + + private int getDataExecutorMaxPoolSize = 400; + + private int getDataExecutorQueueSize = 10000; + + private long getDataExecutorKeepAliveTime = 60; - private int storeNodes = 3; + private int notifyDataSyncExecutorMinPoolSize = 80; - private int numberOfReplicas = 1000; + private int notifyDataSyncExecutorMaxPoolSize = 400; - private long localDataServerCleanDelay = 1000 * 60 * 30; + private int notifyDataSyncExecutorQueueSize = 700; - private int getDataExecutorMinPoolSize = 80; + private long notifyDataSyncExecutorKeepAliveTime = 60; - private int getDataExecutorMaxPoolSize = 400; + private long notifySessionRetryFirstDelay = 1000; - private int getDataExecutorQueueSize = 10000; + private long notifySessionRetryIncrementDelay = 1000; - private long getDataExecutorKeepAliveTime = 60; + private int notifySessionRetryTimes = 10; - private int notifyDataSyncExecutorMinPoolSize = 80; + private int publishExecutorMinPoolSize = 80; - private int notifyDataSyncExecutorMaxPoolSize = 400; + private int publishExecutorMaxPoolSize = 400; - private int notifyDataSyncExecutorQueueSize = 700; + private int publishExecutorQueueSize = 10000; - private long notifyDataSyncExecutorKeepAliveTime = 60; + private int renewDatumExecutorMinPoolSize = 50; - private long notifySessionRetryFirstDelay = 1000; + private int renewDatumExecutorMaxPoolSize = 400; - private long notifySessionRetryIncrementDelay = 1000; + private int renewDatumExecutorQueueSize = 100000; - private int notifySessionRetryTimes = 10; + private int datumTimeToLiveSec = 900; - private int publishExecutorMinPoolSize = 80; + private int datumLeaseManagerExecutorThreadSize = 1; - private int publishExecutorMaxPoolSize = 400; + private int datumLeaseManagerExecutorQueueSize = 1000000; - private int publishExecutorQueueSize = 10000; + private int sessionServerNotifierRetryExecutorThreadSize = 10; + + private int sessionServerNotifierRetryExecutorQueueSize = 1000000; + + private int renewEnableDelaySec = 30; /** * constructor @@ -105,10 +127,82 @@ public DataServerConfig(CommonConfig commonConfig) { this.commonConfig = commonConfig; } + /** + * Getter method for property renewEnableDelaySec. + * + * @return property value of renewEnableDelaySec + */ + public int getRenewEnableDelaySec() { + return renewEnableDelaySec; + } + + /** + * Setter method for property renewEnableDelaySec . + * + * @param renewEnableDelaySec value to be assigned to property renewEnableDelaySec + */ + public void setRenewEnableDelaySec(int renewEnableDelaySec) { + this.renewEnableDelaySec = renewEnableDelaySec; + } + public String getLocalDataCenter() { return commonConfig.getLocalDataCenter(); } + /** + * Getter method for property renewDatumExecutorMinPoolSize. + * + * @return property value of renewDatumExecutorMinPoolSize + */ + public int getRenewDatumExecutorMinPoolSize() { + return renewDatumExecutorMinPoolSize; + } + + /** + * Setter method for property renewDatumExecutorMinPoolSize . + * + * @param renewDatumExecutorMinPoolSize value to be assigned to property renewDatumExecutorMinPoolSize + */ + public void setRenewDatumExecutorMinPoolSize(int renewDatumExecutorMinPoolSize) { + this.renewDatumExecutorMinPoolSize = renewDatumExecutorMinPoolSize; + } + + /** + * Getter method for property renewDatumExecutorMaxPoolSize. + * + * @return property value of renewDatumExecutorMaxPoolSize + */ + public int getRenewDatumExecutorMaxPoolSize() { + return renewDatumExecutorMaxPoolSize; + } + + /** + * Setter method for property renewDatumExecutorMaxPoolSize . + * + * @param renewDatumExecutorMaxPoolSize value to be assigned to property renewDatumExecutorMaxPoolSize + */ + public void setRenewDatumExecutorMaxPoolSize(int renewDatumExecutorMaxPoolSize) { + this.renewDatumExecutorMaxPoolSize = renewDatumExecutorMaxPoolSize; + } + + /** + * Getter method for property renewDatumExecutorQueueSize. + * + * @return property value of renewDatumExecutorQueueSize + */ + public int getRenewDatumExecutorQueueSize() { + return renewDatumExecutorQueueSize; + } + + /** + * Setter method for property renewDatumExecutorQueueSize . + * + * @param renewDatumExecutorQueueSize value to be assigned to property renewDatumExecutorQueueSize + */ + public void setRenewDatumExecutorQueueSize(int renewDatumExecutorQueueSize) { + this.renewDatumExecutorQueueSize = renewDatumExecutorQueueSize; + } + /** * Getter method for property port. * @@ -619,4 +713,99 @@ public int getNotifySessionRetryTimes() { public void setNotifySessionRetryTimes(int notifySessionRetryTimes) { this.notifySessionRetryTimes = notifySessionRetryTimes; } + + /** + * Getter method for property datumTimeToLiveSec. + * + * @return property value of datumTimeToLiveSec + */ + public int getDatumTimeToLiveSec() { + return datumTimeToLiveSec; + } + + /** + * Setter method for property datumTimeToLiveSec . + * + * @param datumTimeToLiveSec value to be assigned to property datumTimeToLiveSec + */ + public void setDatumTimeToLiveSec(int datumTimeToLiveSec) { + this.datumTimeToLiveSec = datumTimeToLiveSec; + } + + /** + * Getter method for property datumLeaseManagerExecutorQueueSize. + * + * @return property value of datumLeaseManagerExecutorQueueSize + */ + public int getDatumLeaseManagerExecutorQueueSize() { + return datumLeaseManagerExecutorQueueSize; + } + + /** + * Setter method for property datumLeaseManagerExecutorQueueSize . + * + * @param datumLeaseManagerExecutorQueueSize value to be assigned to property datumLeaseManagerExecutorQueueSize + */ + public void setDatumLeaseManagerExecutorQueueSize(int datumLeaseManagerExecutorQueueSize) { + this.datumLeaseManagerExecutorQueueSize = datumLeaseManagerExecutorQueueSize; + } + + /** + * Getter method for property datumLeaseManagerExecutorThreadSize. + * + * @return property value of datumLeaseManagerExecutorThreadSize + */ + public int getDatumLeaseManagerExecutorThreadSize() { + return datumLeaseManagerExecutorThreadSize; + } + + /** + * Setter method for property datumLeaseManagerExecutorThreadSize . + * + * @param datumLeaseManagerExecutorThreadSize value to be assigned to property datumLeaseManagerExecutorThreadSize + */ + public void setDatumLeaseManagerExecutorThreadSize(int datumLeaseManagerExecutorThreadSize) { + this.datumLeaseManagerExecutorThreadSize = datumLeaseManagerExecutorThreadSize; + } + + /** + * Getter method for property sessionServerNotifierRetryExecutorThreadSize. + * + * @return property value of sessionServerNotifierRetryExecutorThreadSize + */ + public int getSessionServerNotifierRetryExecutorThreadSize() { + return sessionServerNotifierRetryExecutorThreadSize; + } + + /** + * Setter method for property sessionServerNotifierRetryExecutorThreadSize . + * + * @param sessionServerNotifierRetryExecutorThreadSize value to be assigned to property sessionServerNotifierRetryExecutorThreadSize + */ + public void setSessionServerNotifierRetryExecutorThreadSize(int sessionServerNotifierRetryExecutorThreadSize) { + this.sessionServerNotifierRetryExecutorThreadSize = sessionServerNotifierRetryExecutorThreadSize; + } + + /** + * Getter method for property sessionServerNotifierRetryExecutorQueueSize. + * + * @return property value of sessionServerNotifierRetryExecutorQueueSize + */ + public int getSessionServerNotifierRetryExecutorQueueSize() { + return sessionServerNotifierRetryExecutorQueueSize; + } + + /** + * Setter method for property sessionServerNotifierRetryExecutorQueueSize . + * + * @param sessionServerNotifierRetryExecutorQueueSize value to be assigned to property sessionServerNotifierRetryExecutorQueueSize + */ + public void setSessionServerNotifierRetryExecutorQueueSize(int sessionServerNotifierRetryExecutorQueueSize) { + this.sessionServerNotifierRetryExecutorQueueSize = sessionServerNotifierRetryExecutorQueueSize; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/CacheDigestTask.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/CacheDigestTask.java index 5b09ddb31..feec34a6f 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/CacheDigestTask.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/CacheDigestTask.java @@ -16,19 +16,21 @@ */ package com.alipay.sofa.registry.server.data.cache; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; + import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.util.NamedThreadFactory; -import org.springframework.util.CollectionUtils; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; /** * @@ -39,20 +41,23 @@ public class CacheDigestTask { private static final Logger LOGGER = LoggerFactory.getLogger(CacheDigestTask.class); + @Autowired + private DatumCache datumCache; + /** * */ public void start() { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("CacheDigestTask")); + ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("CacheDigestTask")); executor.scheduleAtFixedRate(() -> { try { - Map> allMap = DatumCache.getAll(); + Map> allMap = datumCache.getAll(); if (!allMap.isEmpty()) { for (Entry> dataCenterEntry : allMap.entrySet()) { String dataCenter = dataCenterEntry.getKey(); Map datumMap = dataCenterEntry.getValue(); - LOGGER.info("[CacheDigestTask] size of datum in {} is {}", - dataCenter, datumMap.size()); + LOGGER.info("[CacheDigestTask] size of datum in {} is {}", dataCenter, datumMap.size()); for (Entry dataInfoEntry : datumMap.entrySet()) { String dataInfoId = dataInfoEntry.getKey(); Datum data = dataInfoEntry.getValue(); @@ -63,14 +68,12 @@ public void start() { pubStr.append(logPublisher(publisher)).append(";"); } } - LOGGER.info( - "[Datum] dataInfoId={}, version={}, dataCenter={}, publishers=[{}]", - dataInfoId, data.getVersion(), dataCenter, pubStr.toString()); + LOGGER.info("[Datum] dataInfoId={}, version={}, dataCenter={}, publishers=[{}]", dataInfoId, + data.getVersion(), dataCenter, pubStr.toString()); } int pubCount = datumMap.values().stream().map(Datum::getPubMap) .filter(map -> map != null && !map.isEmpty()).mapToInt(Map::size).sum(); - LOGGER.info("[CacheDigestTask] size of publisher in {} is {}", - dataCenter, pubCount); + LOGGER.info("[CacheDigestTask] size of publisher in {} is {}", dataCenter, pubCount); } } else { LOGGER.info("[CacheDigestTask] datum cache is empty"); @@ -86,9 +89,9 @@ private String logPublisher(Publisher publisher) { if (publisher != null) { URL url = publisher.getSourceAddress(); String urlStr = url != null ? url.getAddressString() : "null"; - return String.format("dataInfoId=%s, version=%s, host=%s, registerId=%s", - publisher.getDataInfoId(), publisher.getVersion(), urlStr, - publisher.getRegisterId()); + return String.format("registerId=%s, registerTimestamp=%s, host=%s, version=%s", + publisher.getRegisterId(), publisher.getRegisterTimestamp(), urlStr, + publisher.getVersion()); } return ""; } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DataServerCache.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DataServerCache.java index 5cc050ba3..df481af15 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DataServerCache.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DataServerCache.java @@ -21,6 +21,7 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.event.DataServerChangeEvent.FromType; import com.alipay.sofa.registry.server.data.event.handler.AfterWorkingProcessHandler; import com.alipay.sofa.registry.server.data.node.DataNodeStatus; import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; @@ -78,7 +79,7 @@ public class DataServerCache { * @param newItem * @return changedMap(datacenter, serverIp) */ - public Map> compareAndSet(DataServerChangeItem newItem) { + public Map> compareAndSet(DataServerChangeItem newItem, FromType fromType) { synchronized (DataServerCache.class) { // versionMap: datacenter -> version Map newVersionMap = newItem.getVersionMap(); @@ -109,8 +110,8 @@ public Map> compareAndSet(DataServerChangeItem newItem) { if (isTheSame.get()) { LOGGER .info( - "current process map has a same version as change map,this change will be ignored!process version={},get version={}", - currentNewVersionMap, newVersionMap); + "current process map has a same version as change map,this change will be ignored!process version={},get version={},from={}", + currentNewVersionMap, newVersionMap, fromType); return new HashMap<>(); } } @@ -138,7 +139,8 @@ public Map> compareAndSet(DataServerChangeItem newItem) { init(newVersionMap.get(dataServerConfig.getLocalDataCenter())); } if (!changedMap.isEmpty()) { - LOGGER.info("old server map = {}", dataServerChangeItem.getServerMap()); + LOGGER.info("old server map = {},from={}", dataServerChangeItem.getServerMap(), + fromType); LOGGER.info("new server map = {}", newServerMap); LOGGER.info("new server version map = {}", newVersionMap); LOGGER.info("status map = {}", nodeStatusMap); @@ -254,8 +256,9 @@ private void updateDataServerStatus() { LOGGER .info( - "nodeStatusMap not contains all push list,nodeStatusMap {},push {},diff {}", - nodeStatusMap, itemIps, Sets.difference(ips, itemIps)); + "nodeStatusMap not contains all push list,nodeStatusMap {},push {},diff1{},diff2{}", + nodeStatusMap, itemIps, Sets.difference(ips, itemIps), + Sets.difference(itemIps, ips)); return; } } else { @@ -270,6 +273,11 @@ private void updateDataServerStatus() { dataNodeStatus.setStatus(LocalServerStatusEnum.WORKING); + //after working update current dataCenter list to old DataServerChangeItem + updateItem( + newDataServerChangeItem.getServerMap().get(dataServerConfig.getLocalDataCenter()), + newVersion, dataServerConfig.getLocalDataCenter()); + //after working status,must clean this map,because calculate backupTriad need add not working node,see LocalDataServerChangeEventHandler getToBeSyncMap resetStatusMapToWorking(); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DatumCache.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DatumCache.java index 6b17f7702..2b076924c 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DatumCache.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/DatumCache.java @@ -16,11 +16,6 @@ */ package com.alipay.sofa.registry.server.data.cache; -import com.alipay.sofa.registry.common.model.dataserver.Datum; -import com.alipay.sofa.registry.common.model.store.Publisher; -import com.alipay.sofa.registry.server.data.change.DataChangeTypeEnum; -import org.springframework.util.StringUtils; - import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -28,29 +23,44 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.change.DataChangeTypeEnum; +import com.alipay.sofa.registry.server.data.node.DataServerNode; +import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerNodeFactory; + /** * cache of datum, providing query function to the upper module * * @author qian.lqlq - * @version $Id: DatumCache.java, v 0.1 2017-12-06 20:50 qian.lqlq Exp $ + * @version $Id: this.java, v 0.1 2017-12-06 20:50 qian.lqlq Exp $ */ public class DatumCache { - public static final long ERROR_DATUM_VERSION = -2L; + public static final long ERROR_DATUM_VERSION = -2L; /** * row: dataCenter * column: dataInfoId * value: datum */ - private static final Map> DATUM_MAP = new ConcurrentHashMap<>(); + private final Map> DATUM_MAP = new ConcurrentHashMap<>(); /** + * all datum index + * * row: ip:port * column: registerId * value: publisher */ - private static final Map> CLIENT_PUB_MAP = new ConcurrentHashMap<>(); + private final Map> ALL_CONNECT_ID_INDEX = new ConcurrentHashMap<>(); + + @Autowired + private DataServerConfig dataServerConfig; /** * get datum by specific dataCenter and dataInfoId @@ -59,7 +69,7 @@ public class DatumCache { * @param dataInfoId * @return */ - public static Datum get(String dataCenter, String dataInfoId) { + public Datum get(String dataCenter, String dataInfoId) { if (DATUM_MAP.containsKey(dataCenter)) { Map map = DATUM_MAP.get(dataCenter); if (map.containsKey(dataInfoId)) { @@ -75,7 +85,7 @@ public static Datum get(String dataCenter, String dataInfoId) { * @param dataInfoId * @return */ - public static Map get(String dataInfoId) { + public Map get(String dataInfoId) { Map datumMap = new HashMap<>(); DATUM_MAP.forEach((dataCenter, datums) -> { if (datums.containsKey(dataInfoId)) { @@ -93,12 +103,12 @@ public static Map get(String dataInfoId) { * @param dataInfoId * @return */ - public static Map getDatumGroupByDataCenter(String dataCenter, String dataInfoId) { + public Map getDatumGroupByDataCenter(String dataCenter, String dataInfoId) { Map map = new HashMap<>(); if (StringUtils.isEmpty(dataCenter)) { - map = DatumCache.get(dataInfoId); + map = this.get(dataInfoId); } else { - Datum datum = DatumCache.get(dataCenter, dataInfoId); + Datum datum = this.get(dataCenter, dataInfoId); if (datum != null) { map.put(dataCenter, datum); } @@ -111,18 +121,38 @@ public static Map getDatumGroupByDataCenter(String dataCenter, St * * @return */ - public static Map> getAll() { + public Map> getAll() { return DATUM_MAP; } /** * * - * @param host + * @param connectId * @return */ - public static Map getByHost(String host) { - return CLIENT_PUB_MAP.getOrDefault(host, null); + public Map getByConnectId(String connectId) { + return ALL_CONNECT_ID_INDEX.getOrDefault(connectId, null); + } + + /** + * get own publishers by connectId + */ + public Map getOwnByConnectId(String connectId) { + Map ownPubMap = new HashMap<>(); + Map allPubMap = ALL_CONNECT_ID_INDEX.getOrDefault(connectId, null); + if (allPubMap != null) { + for (Map.Entry entry : allPubMap.entrySet()) { + String registerId = entry.getKey(); + Publisher publisher = entry.getValue(); + DataServerNode dataServerNode = DataServerNodeFactory.computeDataServerNode( + dataServerConfig.getLocalDataCenter(), publisher.getDataInfoId()); + if (DataServerConfig.IP.equals(dataServerNode.getIp())) { + ownPubMap.put(registerId, publisher); + } + } + } + return ownPubMap; } /** @@ -132,18 +162,11 @@ public static Map getByHost(String host) { * @param datum * @return the last version before datum changed, if datum is not exist, return null */ - public static MergeResult putDatum(DataChangeTypeEnum changeType, Datum datum) { + public MergeResult putDatum(DataChangeTypeEnum changeType, Datum datum) { MergeResult mergeResult; String dataCenter = datum.getDataCenter(); String dataInfoId = datum.getDataInfoId(); - Map map = DATUM_MAP.get(dataCenter); - if (map == null) { - map = new ConcurrentHashMap<>(); - Map ret = DATUM_MAP.putIfAbsent(dataCenter, map); - if (ret != null) { - map = ret; - } - } + Map map = getDatumMapByDataCenter(dataCenter); //first put UnPublisher datum(dataId group instanceId is null),can not add to cache if (datum.getDataId() == null && map.get(dataInfoId) == null) { @@ -159,14 +182,7 @@ public static MergeResult putDatum(DataChangeTypeEnum changeType, Datum datum) { Entry entry = iterator.next(); Publisher publisher = entry.getValue(); if (!(publisher instanceof UnPublisher)) { - String registerId = publisher.getRegisterId(); - Map clientRegisterMap = new ConcurrentHashMap<>(); - clientRegisterMap.put(registerId, publisher); - Map retMap = CLIENT_PUB_MAP.putIfAbsent(publisher - .getSourceAddress().getAddressString(), clientRegisterMap); - if (retMap != null) { - retMap.putAll(clientRegisterMap); - } + addToIndex(publisher); } else { //first put to cache,UnPublisher data must remove,not so got error pub data exist iterator.remove(); @@ -184,13 +200,25 @@ public static MergeResult putDatum(DataChangeTypeEnum changeType, Datum datum) { return mergeResult; } + private Map getDatumMapByDataCenter(String dataCenter) { + Map map = DATUM_MAP.get(dataCenter); + if (map == null) { + map = new ConcurrentHashMap<>(); + Map ret = DATUM_MAP.putIfAbsent(dataCenter, map); + if (ret != null) { + map = ret; + } + } + return map; + } + /** * remove datum ant contains all pub data,and clean all the client map reference * @param dataCenter * @param dataInfoId * @return */ - public static boolean cleanDatum(String dataCenter, String dataInfoId) { + public boolean cleanDatum(String dataCenter, String dataInfoId) { Map datumMap = DATUM_MAP.get(dataCenter); if (datumMap != null) { @@ -204,8 +232,7 @@ public static boolean cleanDatum(String dataCenter, String dataInfoId) { //remove from cache if (cachePub != null) { cachePubMap.remove(registerId); - CLIENT_PUB_MAP.get(cachePub.getSourceAddress().getAddressString()).remove( - registerId); + removeFromIndex(cachePub); } } return true; @@ -220,7 +247,7 @@ public static boolean cleanDatum(String dataCenter, String dataInfoId) { * @param datum * @return */ - private static MergeResult mergeDatum(Datum datum) { + private MergeResult mergeDatum(Datum datum) { boolean isChanged = false; Datum cacheDatum = DATUM_MAP.get(datum.getDataCenter()).get(datum.getDataInfoId()); Map cachePubMap = cacheDatum.getPubMap(); @@ -229,37 +256,8 @@ private static MergeResult mergeDatum(Datum datum) { String registerId = pubEntry.getKey(); Publisher pub = pubEntry.getValue(); Publisher cachePub = cachePubMap.get(registerId); - if (pub instanceof UnPublisher) { - //remove from cache - if (cachePub != null - && pub.getRegisterTimestamp() > cachePub.getRegisterTimestamp()) { - cachePubMap.remove(registerId); - CLIENT_PUB_MAP.get(cachePub.getSourceAddress().getAddressString()).remove( - registerId); - isChanged = true; - } - } else { - String pubAddr = pub.getSourceAddress().getAddressString(); - long version = pub.getVersion(); - long cacheVersion = cachePub == null ? 0L : cachePub.getVersion(); - String cachePubAddr = cachePub == null ? "" : cachePub.getSourceAddress() - .getAddressString(); - if (cacheVersion <= version) { - cachePubMap.put(registerId, pub); - if (cacheVersion < version || !pubAddr.equals(cachePubAddr)) { - // if version of both pub and cachePub are not equal, or sourceAddress of both are not equal, update - // eg: sessionserver crash, client reconnect to other sessionserver, sourceAddress changed, version not changed - // eg: client restart, sourceAddress and version are both changed - if (CLIENT_PUB_MAP.containsKey(cachePubAddr)) { - CLIENT_PUB_MAP.get(cachePubAddr).remove(registerId); - } - if (!CLIENT_PUB_MAP.containsKey(pubAddr)) { - CLIENT_PUB_MAP.putIfAbsent(pubAddr, new ConcurrentHashMap<>()); - } - CLIENT_PUB_MAP.get(pubAddr).put(registerId, pub); - isChanged = true; - } - } + if (mergePublisher(pub, cachePubMap, cachePub)) { + isChanged = true; } } Long lastVersion = cacheDatum.getVersion(); @@ -269,12 +267,83 @@ private static MergeResult mergeDatum(Datum datum) { return new MergeResult(lastVersion, isChanged); } + /** + * cover datum by snapshot + */ + public Datum putSnapshot(String dataInfoId, Map toBeDeletedPubMap, + Map snapshotPubMap) { + // get cache datum + Map datumMap = getDatumMapByDataCenter(dataServerConfig.getLocalDataCenter()); + Datum cacheDatum = datumMap.get(dataInfoId); + if (cacheDatum == null) { + cacheDatum = new Datum(dataInfoId, dataServerConfig.getLocalDataCenter()); + Publisher publisher = snapshotPubMap.values().iterator().next(); + cacheDatum.setInstanceId(publisher.getInstanceId()); + cacheDatum.setDataId(publisher.getDataId()); + cacheDatum.setGroup(publisher.getGroup()); + Datum datum = datumMap.putIfAbsent(dataInfoId, cacheDatum); + if (datum != null) { + cacheDatum = datum; + } + } + //remove toBeDeletedPubMap from cacheDatum + for (Entry toBeDeletedPubEntry : toBeDeletedPubMap.entrySet()) { + String registerId = toBeDeletedPubEntry.getKey(); + Publisher toBeDeletedPub = toBeDeletedPubEntry.getValue(); + if (cacheDatum != null) { + cacheDatum.getPubMap().remove(registerId); + removeFromIndex(toBeDeletedPub); + } + } + // add snapshotPubMap to cacheDatum + for (Entry pubEntry : snapshotPubMap.entrySet()) { + String registerId = pubEntry.getKey(); + Publisher snapshotPub = pubEntry.getValue(); + Publisher cachePub = cacheDatum.getPubMap().put(registerId, snapshotPub); + if (cachePub != null) { + removeFromIndex(cachePub); + } + addToIndex(snapshotPub); + } + + cacheDatum.updateVersion(); + + return cacheDatum; + } + + private boolean mergePublisher(Publisher pub, Map cachePubMap, + Publisher cachePub) { + boolean isChanged = false; + String registerId = pub.getRegisterId(); + if (pub instanceof UnPublisher) { + //remove from cache + if (cachePub != null && pub.getRegisterTimestamp() > cachePub.getRegisterTimestamp()) { + cachePubMap.remove(registerId); + removeFromIndex(cachePub); + isChanged = true; + } + } else { + long version = pub.getVersion(); + long cacheVersion = cachePub == null ? 0L : cachePub.getVersion(); + if (cacheVersion <= version) { + cachePubMap.put(registerId, pub); + // connectId and cacheConnectId may not be equal, so indexes need to be deleted and added, rather than overwritten directly. + // why connectId and cacheConnectId may not be equal? + // eg: sessionserver crash, client(RegistryClient but not ConfregClient) reconnect to other sessionserver, sourceAddress changed, version not changed + removeFromIndex(cachePub); + addToIndex(pub); + isChanged = true; + } + } + return isChanged; + } + /** * * @param datum * @return */ - private static Long coverDatum(Datum datum) { + private Long coverDatum(Datum datum) { String dataCenter = datum.getDataCenter(); String dataInfoId = datum.getDataInfoId(); Datum cacheDatum = DATUM_MAP.get(dataCenter).get(dataInfoId); @@ -285,25 +354,57 @@ private static Long coverDatum(Datum datum) { for (Entry pubEntry : pubMap.entrySet()) { String registerId = pubEntry.getKey(); Publisher pub = pubEntry.getValue(); - String pubAddr = pub.getSourceAddress().getAddressString(); - if (!CLIENT_PUB_MAP.containsKey(pubAddr)) { - CLIENT_PUB_MAP.putIfAbsent(pubAddr, new ConcurrentHashMap<>()); - } - CLIENT_PUB_MAP.get(pubAddr).put(registerId, pub); + addToIndex(pub); Publisher cachePub = cachePubMap.get(registerId); - if (cachePub != null - && pubAddr.equals(cachePub.getSourceAddress().getAddressString())) { + if (cachePub != null && getConnectId(pub).equals(getConnectId(cachePub))) { cachePubMap.remove(registerId); } } if (!cachePubMap.isEmpty()) { for (Publisher cachePub : cachePubMap.values()) { - CLIENT_PUB_MAP.get(cachePub.getSourceAddress().getAddressString()).remove( - cachePub.getRegisterId()); + removeFromIndex(cachePub); } } } return cacheDatum.getVersion(); } + private void removeFromIndex(Publisher publisher) { + if (publisher == null) { + return; + } + String connectId = getConnectId(publisher); + + // remove from ALL_CONNECT_ID_INDEX + Map publisherMap = ALL_CONNECT_ID_INDEX.get(connectId); + if (publisherMap != null) { + publisherMap.remove(publisher.getRegisterId()); + } + } + + private void addToIndex(Publisher publisher) { + if (publisher == null) { + return; + } + String connectId = getConnectId(publisher); + + // add to ALL_CONNECT_ID_INDEX + Map publisherMap = ALL_CONNECT_ID_INDEX + .computeIfAbsent(connectId, s -> new ConcurrentHashMap<>()); + publisherMap.put(publisher.getRegisterId(), publisher); + + } + + private String getConnectId(Publisher cachePub) { + return cachePub.getSourceAddress().getAddressString(); + } + + /** + * Getter method for property OWN_CONNECT_ID_INDEX. + * + * @return property value of OWN_CONNECT_ID_INDEX + */ + public Set getAllConnectIds() { + return ALL_CONNECT_ID_INDEX.keySet(); + } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/UnPublisher.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/UnPublisher.java index 5db5d80b9..1f3488dc8 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/UnPublisher.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/cache/UnPublisher.java @@ -45,6 +45,6 @@ public UnPublisher(String dataInfoId, String registerId, long registerTimeStamp) @Override public DataType getDataType() { - return DataType.UNPUBLISHER; + return DataType.UN_PUBLISHER; } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/ChangeData.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/ChangeData.java index 166f8fa48..f3e541877 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/ChangeData.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/ChangeData.java @@ -16,11 +16,11 @@ */ package com.alipay.sofa.registry.server.data.change; -import com.alipay.sofa.registry.common.model.dataserver.Datum; - import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; +import com.alipay.sofa.registry.common.model.dataserver.Datum; + /** * changed data * diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataChangeHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataChangeHandler.java index 6f9e0104f..665095b0d 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataChangeHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataChangeHandler.java @@ -27,9 +27,9 @@ import com.alipay.sofa.registry.server.data.change.event.DataChangeEventQueue; import com.alipay.sofa.registry.server.data.change.notify.IDataChangeNotifier; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.List; import java.util.Map; @@ -41,7 +41,7 @@ * @author qian.lqlq * @version $Id: DataChangeHandler.java, v 0.1 2017-12-07 18:44 qian.lqlq Exp $ */ -public class DataChangeHandler implements InitializingBean { +public class DataChangeHandler { private static final Logger LOGGER = LoggerFactory .getLogger(DataChangeHandler.class); @@ -49,31 +49,24 @@ public class DataChangeHandler implements InitializingBean { private static final Logger LOGGER_START = LoggerFactory.getLogger("DATA-START-LOGS"); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private DataChangeEventCenter dataChangeEventCenter; + @Autowired + private DatumCache datumCache; + @Resource private List dataChangeNotifiers; - @Override - public void afterPropertiesSet() { - //init DataChangeEventCenter - dataChangeEventCenter.init(dataServerBootstrapConfig); - start(); - } - - /** - * - */ + @PostConstruct public void start() { DataChangeEventQueue[] queues = dataChangeEventCenter.getQueues(); int queueCount = queues.length; - Executor executor = ExecutorFactory.newFixedThreadPool(queueCount, - DataChangeHandler.class.getSimpleName()); - Executor notifyExecutor = ExecutorFactory.newFixedThreadPool( - dataServerBootstrapConfig.getQueueCount() * 5, this.getClass().getSimpleName()); + Executor executor = ExecutorFactory.newFixedThreadPool(queueCount, DataChangeHandler.class.getSimpleName()); + Executor notifyExecutor = ExecutorFactory + .newFixedThreadPool(dataServerConfig.getQueueCount() * 5, this.getClass().getSimpleName()); for (int idx = 0; idx < queueCount; idx++) { final DataChangeEventQueue dataChangeEventQueue = queues[idx]; final String name = dataChangeEventQueue.getName(); @@ -112,66 +105,85 @@ public ChangeNotifier(ChangeData changeData, String name) { @Override public void run() { - Datum datum = changeData.getDatum(); - String dataCenter = datum.getDataCenter(); - String dataInfoId = datum.getDataInfoId(); - long version = datum.getVersion(); - DataSourceTypeEnum sourceType = changeData.getSourceType(); - DataChangeTypeEnum changeType = changeData.getChangeType(); - try { - if (sourceType == DataSourceTypeEnum.CLEAN) { - if (DatumCache.cleanDatum(dataCenter, dataInfoId)) { - LOGGER - .info( - "[DataChangeHandler][{}] clean datum, dataCenter={}, dataInfoId={}, version={},sourceType={}, changeType={}", - name, dataCenter, dataInfoId, version, sourceType, changeType); - } + if (changeData instanceof SnapshotData) { + SnapshotData snapshotData = (SnapshotData) changeData; + String dataInfoId = snapshotData.getDataInfoId(); + Map toBeDeletedPubMap = snapshotData.getToBeDeletedPubMap(); + Map snapshotPubMap = snapshotData.getSnapshotPubMap(); + Datum oldDatum = datumCache.get(dataServerConfig.getLocalDataCenter(), dataInfoId); + long lastVersion = oldDatum != null ? oldDatum.getVersion() : 0l; + Datum datum = datumCache.putSnapshot(dataInfoId, toBeDeletedPubMap, snapshotPubMap); + long version = datum != null ? datum.getVersion() : 0l; + LOGGER + .info( + "[DataChangeHandler][{}] snapshot handle,dataInfoId={}, version={}, lastVersion={}", + name, dataInfoId, version, lastVersion); + notify(datum, changeData.getSourceType(), null); + + } else { + Datum datum = changeData.getDatum(); + + String dataCenter = datum.getDataCenter(); + String dataInfoId = datum.getDataInfoId(); + DataSourceTypeEnum sourceType = changeData.getSourceType(); + DataChangeTypeEnum changeType = changeData.getChangeType(); + + if (changeType == DataChangeTypeEnum.MERGE + && sourceType != DataSourceTypeEnum.BACKUP + && sourceType != DataSourceTypeEnum.SYNC) { + //update version for pub or unPub merge to cache + //if the version product before merge to cache,it may be cause small version override big one + datum.updateVersion(); + } - } else { - Long lastVersion = null; + long version = datum.getVersion(); - if (sourceType == DataSourceTypeEnum.PUB_TEMP) { + try { + if (sourceType == DataSourceTypeEnum.CLEAN) { + if (datumCache.cleanDatum(dataCenter, dataInfoId)) { + LOGGER + .info( + "[DataChangeHandler][{}] clean datum, dataCenter={}, dataInfoId={}, version={},sourceType={}, changeType={}", + name, dataCenter, dataInfoId, version, sourceType, changeType); + } + + } else if (sourceType == DataSourceTypeEnum.PUB_TEMP) { notifyTempPub(datum, sourceType, changeType); - return; - } - MergeResult mergeResult = DatumCache.putDatum(changeType, datum); - lastVersion = mergeResult.getLastVersion(); + } else { + MergeResult mergeResult = datumCache.putDatum(changeType, datum); + Long lastVersion = mergeResult.getLastVersion(); + + if (lastVersion != null + && lastVersion.longValue() == datumCache.ERROR_DATUM_VERSION) { + LOGGER + .error( + "[DataChangeHandler][{}] first put unPub datum into cache error, dataCenter={}, dataInfoId={}, version={}, sourceType={},isContainsUnPub={}", + name, dataCenter, dataInfoId, version, sourceType, + datum.isContainsUnPub()); + return; + } - if (lastVersion != null - && lastVersion.longValue() == DatumCache.ERROR_DATUM_VERSION) { LOGGER - .error( - "[DataChangeHandler][{}] first put unPub datum into cache error, dataCenter={}, dataInfoId={}, version={}, sourceType={},isContainsUnPub={}", - name, dataCenter, dataInfoId, version, sourceType, + .info( + "[DataChangeHandler][{}] datum handle,datum={},dataCenter={}, dataInfoId={}, version={}, lastVersion={}, sourceType={}, changeType={},changeFlag={},isContainsUnPub={}", + name, datum.hashCode(), dataCenter, dataInfoId, version, + lastVersion, sourceType, changeType, mergeResult.isChangeFlag(), datum.isContainsUnPub()); - return; - } - - boolean changeFlag = mergeResult.isChangeFlag(); - - LOGGER - .info( - "[DataChangeHandler][{}] datum handle,datum={},dataCenter={}, dataInfoId={}, version={}, lastVersion={}, sourceType={}, changeType={},changeFlag={},isContainsUnPub={}", - name, datum.hashCode(), dataCenter, dataInfoId, version, lastVersion, - sourceType, changeType, changeFlag, datum.isContainsUnPub()); - //lastVersion null means first add datum - if (lastVersion == null || version != lastVersion) { - if (changeFlag) { - for (IDataChangeNotifier notifier : dataChangeNotifiers) { - if (notifier.getSuitableSource().contains(sourceType)) { - notifier.notify(datum, lastVersion); - } + //lastVersion null means first add datum + if (lastVersion == null || version != lastVersion) { + if (mergeResult.isChangeFlag()) { + notify(datum, sourceType, lastVersion); } } } + } catch (Exception e) { + LOGGER + .error( + "[DataChangeHandler][{}] put datum into cache error, dataCenter={}, dataInfoId={}, version={}, sourceType={},isContainsUnPub={}", + name, dataCenter, dataInfoId, version, sourceType, + datum.isContainsUnPub(), e); } - } catch (Exception e) { - LOGGER - .error( - "[DataChangeHandler][{}] put datum into cache error, dataCenter={}, dataInfoId={}, version={}, sourceType={},isContainsUnPub={}", - name, dataCenter, dataInfoId, version, sourceType, datum.isContainsUnPub(), - e); } } @@ -183,7 +195,7 @@ private void notifyTempPub(Datum datum, DataSourceTypeEnum sourceType, String dataInfoId = datum.getDataInfoId(); long version = datum.getVersion(); - Datum existDatum = DatumCache.get(dataCenter, dataInfoId); + Datum existDatum = datumCache.get(dataCenter, dataInfoId); if (existDatum != null) { Map cachePubMap = existDatum.getPubMap(); if (cachePubMap != null && !cachePubMap.isEmpty()) { @@ -196,11 +208,16 @@ private void notifyTempPub(Datum datum, DataSourceTypeEnum sourceType, "[DataChangeHandler][{}] datum handle temp pub,datum={},dataCenter={}, dataInfoId={}, version={}, sourceType={}, changeType={}", name, datum.hashCode(), dataCenter, dataInfoId, version, sourceType, changeType); + notify(datum, sourceType, null); + } + + private void notify(Datum datum, DataSourceTypeEnum sourceType, Long lastVersion) { for (IDataChangeNotifier notifier : dataChangeNotifiers) { if (notifier.getSuitableSource().contains(sourceType)) { - notifier.notify(datum, null); + notifier.notify(datum, lastVersion); } } } } + } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataSourceTypeEnum.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataSourceTypeEnum.java index c41a14f51..b2787fbb9 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataSourceTypeEnum.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/DataSourceTypeEnum.java @@ -46,5 +46,10 @@ public enum DataSourceTypeEnum { /** * local dataInfo check,not belong this node schedule remove */ - CLEAN + CLEAN, + + /** + * Snapshot data, after renew finds data inconsistent + */ + SNAPSHOT, } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/SnapshotData.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/SnapshotData.java new file mode 100644 index 000000000..495019d65 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/SnapshotData.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.change; + +import java.util.Map; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +import com.alipay.sofa.registry.common.model.store.Publisher; + +/** + * changed data + * + * @author kezhu.wukz + * @version $Id: ChangeData.java, v 0.1 2019-07-12 16:23 kezhu.wukz Exp $ + */ +public class SnapshotData extends ChangeData { + + private String dataInfoId; + + private Map toBeDeletedPubMap; + + private Map snapshotPubMap; + + public SnapshotData(String dataInfoId, Map toBeDeletedPubMap, + Map snapshotPubMap) { + super(null, 0, DataSourceTypeEnum.SNAPSHOT, null); + this.dataInfoId = dataInfoId; + this.toBeDeletedPubMap = toBeDeletedPubMap; + this.snapshotPubMap = snapshotPubMap; + } + + /** + * Getter method for property dataInfoId. + * + * @return property value of dataInfoId + */ + public String getDataInfoId() { + return dataInfoId; + } + + /** + * Getter method for property toBeDeletedPubMap. + * + * @return property value of toBeDeletedPubMap + */ + public Map getToBeDeletedPubMap() { + return toBeDeletedPubMap; + } + + /** + * Getter method for property snapshotPubMap. + * + * @return property value of snapshotPubMap + */ + public Map getSnapshotPubMap() { + return snapshotPubMap; + } + + @Override + public long getDelay(TimeUnit unit) { + return 0; + } + + @Override + public int compareTo(Delayed o) { + return -1; + } +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/ClientChangeEvent.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/ClientChangeEvent.java index c063f50d4..b2eb9f036 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/ClientChangeEvent.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/ClientChangeEvent.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.server.data.change.event; +import com.alipay.sofa.registry.util.DatumVersionUtil; + /** * * @author qian.lqlq @@ -41,7 +43,7 @@ public ClientChangeEvent(String host, String dataCenter, long occurredTimestamp) this.host = host; this.dataCenter = dataCenter; this.occurredTimestamp = occurredTimestamp; - this.version = System.currentTimeMillis(); + this.version = DatumVersionUtil.nextId(); } @Override diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventCenter.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventCenter.java index 58c5496e2..01b5e220d 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventCenter.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventCenter.java @@ -16,16 +16,21 @@ */ package com.alipay.sofa.registry.server.data.change.event; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.PublishType; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.data.cache.UnPublisher; import com.alipay.sofa.registry.server.data.change.DataChangeTypeEnum; import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; -import java.util.concurrent.atomic.AtomicBoolean; - /** * * @author qian.lqlq @@ -44,16 +49,20 @@ public class DataChangeEventCenter { */ private DataChangeEventQueue[] dataChangeEventQueues; - /** - * - * @param config - */ - public void init(DataServerConfig config) { + @Autowired + private DataServerConfig dataServerConfig; + + @Autowired + private DatumCache datumCache; + + @PostConstruct + public void init() { if (isInited.compareAndSet(false, true)) { - queueCount = config.getQueueCount(); + queueCount = dataServerConfig.getQueueCount(); dataChangeEventQueues = new DataChangeEventQueue[queueCount]; for (int idx = 0; idx < queueCount; idx++) { - dataChangeEventQueues[idx] = new DataChangeEventQueue(idx, config); + dataChangeEventQueues[idx] = new DataChangeEventQueue(idx, dataServerConfig, this, + datumCache); dataChangeEventQueues[idx].start(); } } @@ -101,6 +110,16 @@ public void onChange(ClientChangeEvent event) { } } + /** + * + * @param event + */ + public void onChange(DatumSnapshotEvent event) { + for (DataChangeEventQueue dataChangeEventQueue : dataChangeEventQueues) { + dataChangeEventQueue.onChange(event); + } + } + /** * * @param changeType @@ -118,7 +137,7 @@ public void sync(DataChangeTypeEnum changeType, DataSourceTypeEnum sourceType, D * @param key * @return */ - private int hash(String key) { + public int hash(String key) { if (queueCount > 1) { return Math.abs(key.hashCode() % queueCount); } else { diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventQueue.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventQueue.java index 99cd31bd3..f3b1f78cc 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventQueue.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeEventQueue.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.data.change.event; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.locks.ReentrantLock; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.log.Logger; @@ -26,19 +36,12 @@ import com.alipay.sofa.registry.server.data.change.ChangeData; import com.alipay.sofa.registry.server.data.change.DataChangeTypeEnum; import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; +import com.alipay.sofa.registry.server.data.change.SnapshotData; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; import com.alipay.sofa.registry.server.data.node.DataServerNode; import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerNodeFactory; import com.google.common.collect.Interners; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.locks.ReentrantLock; - /** * a queue of DataChangeEvent * @@ -47,11 +50,16 @@ */ public class DataChangeEventQueue { - private static final Logger LOGGER = LoggerFactory - .getLogger(DataChangeEventQueue.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(DataChangeEventQueue.class); - private static final Logger LOGGER_START = LoggerFactory - .getLogger("DATA-START-LOGS"); + private static final Logger LOGGER_START = LoggerFactory + .getLogger("DATA-START-LOGS"); + + private static final Logger RENEW_LOGGER = LoggerFactory + .getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[DataChangeEventQueue]"); /** * @@ -66,29 +74,36 @@ public class DataChangeEventQueue { /** * */ - private final Map> CHANGE_DATA_MAP = new ConcurrentHashMap<>(); + private final Map> CHANGE_DATA_MAP_FOR_MERGE = new ConcurrentHashMap<>(); /** * */ - private final DelayQueue CHANGE_QUEUE = new DelayQueue(); + private final DelayQueue CHANGE_QUEUE = new DelayQueue(); private final int notifyIntervalMs; private final int notifyTempDataIntervalMs; - private final ReentrantLock lock = new ReentrantLock(); + private final ReentrantLock lock = new ReentrantLock(); + + private final int queueIdx; private DataServerConfig dataServerConfig; + private DataChangeEventCenter dataChangeEventCenter; + + private DatumCache datumCache; + /** * constructor - * @param idx + * @param queueIdx * @param dataServerConfig */ - public DataChangeEventQueue(int idx, DataServerConfig dataServerConfig) { - - this.name = String.format("%s_%s", DataChangeEventQueue.class.getSimpleName(), idx); + public DataChangeEventQueue(int queueIdx, DataServerConfig dataServerConfig, + DataChangeEventCenter dataChangeEventCenter, DatumCache datumCache) { + this.queueIdx = queueIdx; + this.name = String.format("%s_%s", DataChangeEventQueue.class.getSimpleName(), queueIdx); this.dataServerConfig = dataServerConfig; int queueSize = dataServerConfig.getQueueSize(); if (queueSize <= 0) { @@ -98,6 +113,8 @@ public DataChangeEventQueue(int idx, DataServerConfig dataServerConfig) { } this.notifyIntervalMs = dataServerConfig.getNotifyIntervalMs(); this.notifyTempDataIntervalMs = dataServerConfig.getNotifyTempDataIntervalMs(); + this.dataChangeEventCenter = dataChangeEventCenter; + this.datumCache = datumCache; } /** @@ -126,16 +143,20 @@ public ChangeData take() throws InterruptedException { ChangeData changeData = CHANGE_QUEUE.take(); lock.lock(); try { - Datum datum = changeData.getDatum(); - if (changeData.getSourceType() != DataSourceTypeEnum.PUB_TEMP) { - CHANGE_DATA_MAP.get(datum.getDataCenter()).remove(datum.getDataInfoId()); - } + removeMapForMerge(changeData); return changeData; } finally { lock.unlock(); } } + private void removeMapForMerge(ChangeData changeData) { + Datum datum = changeData.getDatum(); + if (changeData.getSourceType() != DataSourceTypeEnum.PUB_TEMP && datum != null) { + CHANGE_DATA_MAP_FOR_MERGE.get(datum.getDataCenter()).remove(datum.getDataInfoId()); + } + } + /** * * @param dataCenter @@ -146,10 +167,10 @@ public ChangeData take() throws InterruptedException { */ private ChangeData getChangeData(String dataCenter, String dataInfoId, DataSourceTypeEnum sourceType, DataChangeTypeEnum changeType) { - Map map = CHANGE_DATA_MAP.get(dataCenter); + Map map = CHANGE_DATA_MAP_FOR_MERGE.get(dataCenter); if (map == null) { Map newMap = new ConcurrentHashMap<>(); - map = CHANGE_DATA_MAP.putIfAbsent(dataCenter, newMap); + map = CHANGE_DATA_MAP_FOR_MERGE.putIfAbsent(dataCenter, newMap); if (map == null) { map = newMap; } @@ -172,8 +193,8 @@ private ChangeData getChangeData(String dataCenter, String dataInfoId, * */ public void start() { - Executor executor = ExecutorFactory.newSingleThreadExecutor( - String.format("%s_%s", DataChangeEventQueue.class.getSimpleName(), getName())); + Executor executor = ExecutorFactory + .newSingleThreadExecutor(String.format("%s_%s", DataChangeEventQueue.class.getSimpleName(), getName())); executor.execute(() -> { while (true) { try { @@ -182,16 +203,17 @@ public void start() { if (scope == DataChangeScopeEnum.DATUM) { DataChangeEvent dataChangeEvent = (DataChangeEvent) event; //Temporary push data will be notify as soon as,and not merge to normal pub data; - if (dataChangeEvent.getSourceType() == DataSourceTypeEnum.PUB_TEMP){ - addTempChangeData(dataChangeEvent.getDatum(),dataChangeEvent.getChangeType(), + if (dataChangeEvent.getSourceType() == DataSourceTypeEnum.PUB_TEMP) { + addTempChangeData(dataChangeEvent.getDatum(), dataChangeEvent.getChangeType(), dataChangeEvent.getSourceType()); - } - else { - handleDatum(dataChangeEvent.getChangeType(), - dataChangeEvent.getSourceType(), dataChangeEvent.getDatum()); + } else { + handleDatum(dataChangeEvent.getChangeType(), dataChangeEvent.getSourceType(), + dataChangeEvent.getDatum()); } } else if (scope == DataChangeScopeEnum.CLIENT) { - handleHost((ClientChangeEvent) event); + handleClientOff((ClientChangeEvent) event); + } else if (scope == DataChangeScopeEnum.SNAPSHOT) { + handleSnapshot((DatumSnapshotEvent) event); } } catch (Throwable e) { LOGGER.error("[{}] handle change event failed", getName(), e); @@ -201,15 +223,21 @@ public void start() { LOGGER_START.info("[{}] start DataChangeEventQueue success", getName()); } - private void handleHost(ClientChangeEvent event) { - String clientHost = event.getHost(); - synchronized (Interners.newWeakInterner().intern(clientHost)) { - Map pubMap = DatumCache.getByHost(clientHost); + private void handleClientOff(ClientChangeEvent event) { + String connectId = event.getHost(); + synchronized (Interners.newWeakInterner().intern(connectId)) { + Map pubMap = datumCache.getByConnectId(connectId); if (pubMap != null && !pubMap.isEmpty()) { - LOGGER.info("[{}] client off begin, host={}, occurTimestamp={},all pub size={}", - getName(), clientHost, event.getOccurredTimestamp(), pubMap.size()); + LOGGER.info( + "[{}] client off begin, connectId={}, occurTimestamp={}, all pubSize={}", + getName(), connectId, event.getOccurredTimestamp(), pubMap.size()); int count = 0; for (Publisher publisher : pubMap.values()) { + // Only care dataInfoIds which belong to this queue + if (!belongTo(publisher.getDataInfoId())) { + continue; + } + DataServerNode dataServerNode = DataServerNodeFactory.computeDataServerNode( dataServerConfig.getLocalDataCenter(), publisher.getDataInfoId()); //current dataCenter backup data need not unPub,it will be unPub by backup sync event @@ -224,11 +252,11 @@ private void handleHost(ClientChangeEvent event) { } LOGGER .info( - "[{}] client off handle, host={}, occurTimestamp={},version={},handle pub size={}", - getName(), clientHost, event.getOccurredTimestamp(), event.getVersion(), + "[{}] client off handle, connectId={}, occurTimestamp={}, version={}, handle pubSize={}", + getName(), connectId, event.getOccurredTimestamp(), event.getVersion(), count); } else { - LOGGER.info("[{}] no datum to handle, host={}", getName(), clientHost); + LOGGER.info("[{}] no datum to handle, connectId={}", getName(), connectId); } } } @@ -259,7 +287,7 @@ private void handleDatum(DataChangeTypeEnum changeType, DataSourceTypeEnum sourc // and version of cachePub is greater than version of pub, should be ignored if (!(pub instanceof UnPublisher) && !(cachePub instanceof UnPublisher) && pub.getSourceAddress().equals(cachePub.getSourceAddress()) - && cachePub.getVersion() >= pub.getVersion()) { + && cachePub.getVersion() > pub.getVersion()) { continue; } } @@ -272,11 +300,76 @@ private void handleDatum(DataChangeTypeEnum changeType, DataSourceTypeEnum sourc } } + private void handleSnapshot(DatumSnapshotEvent event) { + String connectId = event.getConnectId(); + Map cachePubMap = event.getCachePubMap(); + Map snapshotPubMap = event.getPubMap(); + + // build SnapshotData + Map dataInfoId2SnapshotData = new HashMap<>(); + synchronized (Interners.newWeakInterner().intern(connectId)) { + for (Map.Entry entry : snapshotPubMap.entrySet()) { + String registerId = entry.getKey(); + Publisher publisher = entry.getValue(); + String dataInfoId = publisher.getDataInfoId(); + + // Only care dataInfoIds which belong to this queue + if (!belongTo(dataInfoId)) { + continue; + } + + SnapshotData snapshotData = getOrCreateSnapshotData(dataInfoId2SnapshotData, + dataInfoId); + snapshotData.getSnapshotPubMap().put(registerId, publisher); + } + for (Map.Entry entry : cachePubMap.entrySet()) { + String registerId = entry.getKey(); + Publisher publisher = entry.getValue(); + String dataInfoId = publisher.getDataInfoId(); + + // Only care dataInfoIds which belong to this queue + if (!belongTo(dataInfoId)) { + continue; + } + + SnapshotData snapshotData = getOrCreateSnapshotData(dataInfoId2SnapshotData, + dataInfoId); + snapshotData.getToBeDeletedPubMap().put(registerId, publisher); + } + } + + // put all SnapshotDatas to queue + for (SnapshotData snapshotData : dataInfoId2SnapshotData.values()) { + RENEW_LOGGER + .info( + "SnapshotData: connectId={}, dataInfoId={}, cachePubSize={}, snapshotPubSize={}", + connectId, snapshotData.getDataInfoId(), snapshotData.getToBeDeletedPubMap() + .size(), snapshotData.getSnapshotPubMap().size()); + CHANGE_QUEUE.put(snapshotData); + } + } + + private SnapshotData getOrCreateSnapshotData(Map dataInfoId2SnapshotData, + String dataInfoId) { + SnapshotData snapshotData = dataInfoId2SnapshotData.get(dataInfoId); + if (snapshotData == null) { + snapshotData = new SnapshotData(dataInfoId, new HashMap<>(), new HashMap<>()); + dataInfoId2SnapshotData.put(dataInfoId, snapshotData); + } + return snapshotData; + } + private void addTempChangeData(Datum targetDatum, DataChangeTypeEnum changeType, DataSourceTypeEnum sourceType) { - ChangeData tempChangeData = new ChangeData(targetDatum, this.notifyTempDataIntervalMs, sourceType, changeType); CHANGE_QUEUE.put(tempChangeData); } + + /** + * Determine whether dataInfoId belongs to the current queue + */ + private boolean belongTo(String dataInfoId) { + return this.queueIdx == this.dataChangeEventCenter.hash(dataInfoId); + } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeScopeEnum.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeScopeEnum.java index bfba719e5..94bbdb0d3 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeScopeEnum.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DataChangeScopeEnum.java @@ -22,5 +22,5 @@ * @version $Id: DataChangeScopeEnum.java, v 0.1 2018-05-10 16:51 qian.lqlq Exp $ */ public enum DataChangeScopeEnum { - CLIENT, DATUM + CLIENT, DATUM, SNAPSHOT } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DatumSnapshotEvent.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DatumSnapshotEvent.java new file mode 100644 index 000000000..af08c25c6 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/event/DatumSnapshotEvent.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.change.event; + +import java.util.Map; + +import com.alipay.sofa.registry.common.model.store.Publisher; + +/** + * + * @author kezhu.wukz + * @version $Id: DatumSnapshotEvent.java, v 0.1 2019-05-30 18:22 kezhu.wukz Exp $ + */ +public class DatumSnapshotEvent implements IDataChangeEvent { + + /** connId, format is ip:port */ + private String connectId; + + private Map pubMap; + + private Map cachePubMap; + + public DatumSnapshotEvent(String connectId, Map cachePubMap, + Map pubMap) { + this.connectId = connectId; + this.cachePubMap = cachePubMap; + this.pubMap = pubMap; + } + + /** + * Getter method for property connectId. + * + * @return property value of connectId + */ + public String getConnectId() { + return connectId; + } + + /** + * Getter method for property pubMap. + * + * @return property value of pubMap + */ + public Map getPubMap() { + return pubMap; + } + + /** + * Getter method for property cachePubMap. + * + * @return property value of cachePubMap + */ + public Map getCachePubMap() { + return cachePubMap; + } + + @Override + public DataChangeScopeEnum getScope() { + return DataChangeScopeEnum.SNAPSHOT; + } + +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SessionServerNotifier.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SessionServerNotifier.java index 727156d35..451f89804 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SessionServerNotifier.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SessionServerNotifier.java @@ -16,6 +16,15 @@ */ package com.alipay.sofa.registry.server.data.change.notify; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.remoting.Connection; import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -33,12 +42,6 @@ import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; /** * Notify session DataChangeRequest,if fail get result callback retry @@ -54,7 +57,7 @@ public class SessionServerNotifier implements IDataChangeNotifier { private AsyncHashedWheelTimer asyncHashedWheelTimer; @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private Exchange boltExchange; @@ -62,13 +65,19 @@ public class SessionServerNotifier implements IDataChangeNotifier { @Autowired private SessionServerConnectionFactory sessionServerConnectionFactory; - public SessionServerNotifier() { + @Autowired + private DatumCache datumCache; + + @PostConstruct + public void init() { ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); threadFactoryBuilder.setDaemon(true); asyncHashedWheelTimer = new AsyncHashedWheelTimer(threadFactoryBuilder.setNameFormat( "Registry-SessionServerNotifier-WheelTimer").build(), 100, TimeUnit.MILLISECONDS, 1024, - threadFactoryBuilder.setNameFormat("Registry-SessionServerNotifier-WheelExecutor-%d") - .build(), new TaskFailedCallback() { + dataServerConfig.getSessionServerNotifierRetryExecutorThreadSize(), + dataServerConfig.getSessionServerNotifierRetryExecutorQueueSize(), threadFactoryBuilder + .setNameFormat("Registry-SessionServerNotifier-WheelExecutor-%d").build(), + new TaskFailedCallback() { @Override public void executionRejected(Throwable e) { LOGGER.error("executionRejected: " + e.getMessage(), e); @@ -86,6 +95,7 @@ public Set getSuitableSource() { Set set = new HashSet<>(); set.add(DataSourceTypeEnum.PUB); set.add(DataSourceTypeEnum.SYNC); + set.add(DataSourceTypeEnum.SNAPSHOT); return set; } @@ -109,17 +119,17 @@ private void doNotify(NotifyCallback notifyCallback) { LOGGER .info(String .format( - "connection from sessionserver(%s) is not fine, so ignore notify, retryTimes=%s,request=%s", + "connection from sessionServer(%s) is not fine, so ignore notify, retryTimes=%s,request=%s", connection.getRemoteAddress(), notifyCallback.retryTimes, request)); } return; } - Server sessionServer = boltExchange.getServer(dataServerBootstrapConfig.getPort()); + Server sessionServer = boltExchange.getServer(dataServerConfig.getPort()); sessionServer.sendCallback(sessionServer.getChannel(connection.getRemoteAddress()), - request, notifyCallback, dataServerBootstrapConfig.getRpcTimeout()); + request, notifyCallback, dataServerConfig.getRpcTimeout()); } catch (Exception e) { LOGGER.error(String.format( - "invokeWithCallback failed: sessionserver(%s),retryTimes=%s, request=%s", + "invokeWithCallback failed: sessionServer(%s),retryTimes=%s, request=%s", connection.getRemoteAddress(), notifyCallback.retryTimes, request), e); onFailed(notifyCallback); } @@ -133,14 +143,14 @@ private void onFailed(NotifyCallback notifyCallback) { Connection connection = notifyCallback.connection; notifyCallback.retryTimes++; - if (notifyCallback.retryTimes <= dataServerBootstrapConfig.getNotifySessionRetryTimes()) { + if (notifyCallback.retryTimes <= dataServerConfig.getNotifySessionRetryTimes()) { this.asyncHashedWheelTimer.newTimeout(timeout -> { if (LOGGER.isInfoEnabled()) { - LOGGER.info(String.format("retrying notify sessionserver(%s), retryTimes=%s, request=%s", + LOGGER.info(String.format("retrying notify sessionServer(%s), retryTimes=%s, request=%s", connection.getRemoteAddress(), notifyCallback.retryTimes, request)); } //check version, if it's fall behind, stop retry - long currentVersion = DatumCache.get(request.getDataCenter(), request.getDataInfoId()).getVersion(); + long currentVersion = datumCache.get(request.getDataCenter(), request.getDataInfoId()).getVersion(); if (request.getVersion() == currentVersion) { doNotify(notifyCallback); } else { @@ -159,9 +169,9 @@ private void onFailed(NotifyCallback notifyCallback) { } private long getDelayTimeForRetry(int retryTimes) { - long initialSleepTime = TimeUnit.MILLISECONDS.toMillis(dataServerBootstrapConfig + long initialSleepTime = TimeUnit.MILLISECONDS.toMillis(dataServerConfig .getNotifySessionRetryFirstDelay()); - long increment = TimeUnit.MILLISECONDS.toMillis(dataServerBootstrapConfig + long increment = TimeUnit.MILLISECONDS.toMillis(dataServerConfig .getNotifySessionRetryIncrementDelay()); long result = initialSleepTime + (increment * (retryTimes - 1)); return result >= 0L ? result : 0L; @@ -185,7 +195,7 @@ public void onCallback(Channel channel, Object message) { LOGGER .error(String .format( - "response not success when notify sessionserver(%s), retryTimes=%s, request=%s, response=%s", + "response not success when notify sessionServer(%s), retryTimes=%s, request=%s, response=%s", connection.getRemoteAddress(), retryTimes, request, result)); onFailed(this); } @@ -194,7 +204,7 @@ public void onCallback(Channel channel, Object message) { @Override public void onException(Channel channel, Throwable e) { LOGGER.error(String.format( - "exception when notify sessionserver(%s), retryTimes=%s, request=%s", + "exception when notify sessionServer(%s), retryTimes=%s, request=%s", connection.getRemoteAddress(), retryTimes, request), e); onFailed(this); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SnapshotBackUpNotifier.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SnapshotBackUpNotifier.java new file mode 100644 index 000000000..aab640fb2 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/SnapshotBackUpNotifier.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.change.notify; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; +import com.alipay.sofa.registry.server.data.datasync.SnapshotOperator; +import com.alipay.sofa.registry.server.data.datasync.SyncDataService; + +/** + * + * @author kezhu.wukz + * @version $Id: SnapshotBackUpNotifier.java, v 0.1 2019-07-12 18:40 kezhu.wukz Exp $ + */ +public class SnapshotBackUpNotifier implements IDataChangeNotifier { + + @Autowired + private SyncDataService syncDataService; + + @Override + public Set getSuitableSource() { + Set set = new HashSet<>(); + set.add(DataSourceTypeEnum.SNAPSHOT); + return set; + } + + @Override + public void notify(Datum datum, Long lastVersion) { + syncDataService.appendOperator(new SnapshotOperator(datum.getVersion(), lastVersion, datum, + DataSourceTypeEnum.BACKUP)); + } +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/TempPublisherNotifier.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/TempPublisherNotifier.java index b37fa7541..f4f5f5e9a 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/TempPublisherNotifier.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/change/notify/TempPublisherNotifier.java @@ -16,6 +16,13 @@ */ package com.alipay.sofa.registry.server.data.change.notify; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executor; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.remoting.Connection; import com.alipay.remoting.InvokeCallback; import com.alipay.sofa.registry.common.model.CommonResponse; @@ -31,12 +38,6 @@ import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; import com.alipay.sofa.registry.server.data.remoting.sessionserver.SessionServerConnectionFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executor; /** * @@ -54,7 +55,7 @@ public class TempPublisherNotifier implements IDataChangeNotifier { .getSimpleName()); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private Exchange boltExchange; @@ -83,7 +84,7 @@ private void doNotify(NotifyPushDataCallback notifyPushdataCallback) { Connection connection = notifyPushdataCallback.getConnection(); DataPushRequest request = notifyPushdataCallback.getRequest(); try { - Server sessionServer = boltExchange.getServer(dataServerBootstrapConfig.getPort()); + Server sessionServer = boltExchange.getServer(dataServerConfig.getPort()); sessionServer.sendCallback(sessionServer.getChannel(connection.getRemoteAddress()), request, new CallbackHandler() { @@ -96,7 +97,7 @@ public void onCallback(Channel channel, Object message) { public void onException(Channel channel, Throwable exception) { notifyPushdataCallback.onException(exception); } - }, dataServerBootstrapConfig.getRpcTimeout()); + }, dataServerConfig.getRpcTimeout()); } catch (Exception e) { LOGGER.error("[TempPublisherNotifier] notify sessionserver {} failed, {}", connection.getRemoteIP(), request, e); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/SnapshotOperator.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/SnapshotOperator.java new file mode 100644 index 000000000..dd7aaf163 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/SnapshotOperator.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.datasync; + +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; + +/** + * + * @author kezhu.wukz + * @version $Id: SnapshotOperator.java, v 0.1 2019-07-12 20:33 kezhu.wukz Exp $ + */ +public class SnapshotOperator extends Operator { + + public SnapshotOperator(Long version, Long sourceVersion, Datum datum, + DataSourceTypeEnum sourceType) { + super(version, sourceVersion, datum, sourceType); + } +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/AbstractAcceptorStore.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/AbstractAcceptorStore.java index 70e644c0e..b07713814 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/AbstractAcceptorStore.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/AbstractAcceptorStore.java @@ -16,6 +16,13 @@ */ package com.alipay.sofa.registry.server.data.datasync.sync; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.remoting.Connection; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.NotifyDataSyncRequest; @@ -26,18 +33,14 @@ import com.alipay.sofa.registry.remoting.Server; import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.data.datasync.AcceptorStore; import com.alipay.sofa.registry.server.data.datasync.Operator; +import com.alipay.sofa.registry.server.data.datasync.SnapshotOperator; import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerConnectionFactory; import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; import com.alipay.sofa.registry.server.data.util.DelayItem; import com.alipay.sofa.registry.server.data.util.TimeUtil; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.DelayQueue; /** * @@ -61,11 +64,14 @@ public abstract class AbstractAcceptorStore implements AcceptorStore { private Exchange boltExchange; @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private DataServerConnectionFactory dataServerConnectionFactory; + @Autowired + private DatumCache datumCache; + private Map> acceptors = new ConcurrentHashMap<>(); private Map> notifyAcceptorsCache = new ConcurrentHashMap<>(); @@ -105,13 +111,21 @@ public void addOperator(Operator operator) { Acceptor existAcceptor = acceptorMap.get(dataInfoId); if (existAcceptor == null) { - Acceptor newAcceptor = new Acceptor(DEFAULT_MAX_BUFFER_SIZE, dataInfoId, dataCenter); + Acceptor newAcceptor = new Acceptor(DEFAULT_MAX_BUFFER_SIZE, dataInfoId, + dataCenter, datumCache); existAcceptor = acceptorMap.putIfAbsent(dataInfoId, newAcceptor); if (existAcceptor == null) { existAcceptor = newAcceptor; } } - existAcceptor.appendOperator(operator); + + if (operator instanceof SnapshotOperator) { + //snapshot: clear the queue, Make other data retrieve the latest memory data + existAcceptor.clearBefore(); + } else { + existAcceptor.appendOperator(operator); + } + //put cache putCache(existAcceptor); } catch (Exception e) { @@ -192,7 +206,7 @@ private void notifyChange(Acceptor acceptor) { continue; } - Server syncServer = boltExchange.getServer(dataServerBootstrapConfig.getSyncDataPort()); + Server syncServer = boltExchange.getServer(dataServerConfig.getSyncDataPort()); for (int tryCount = 0; tryCount < NOTIFY_RETRY; tryCount++) { try { @@ -234,6 +248,8 @@ public void changeDataCheck() { removeCache(acceptor); // compare and remove } catch (InterruptedException e) { break; + } catch (Throwable e) { + LOGGER.error(e.getMessage(), e); } } @@ -270,11 +286,11 @@ public SyncData getSyncData(SyncDataRequest syncDataRequest) { } /** - * Getter method for property dataServerBootstrapConfig. + * Getter method for property dataServerConfig. * - * @return property value of dataServerBootstrapConfig + * @return property value of dataServerConfig */ public DataServerConfig getDataServerConfig() { - return dataServerBootstrapConfig; + return dataServerConfig; } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/Acceptor.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/Acceptor.java index 5650ea263..b758cf6fa 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/Acceptor.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/datasync/sync/Acceptor.java @@ -16,13 +16,6 @@ */ package com.alipay.sofa.registry.server.data.datasync.sync; -import com.alipay.sofa.registry.common.model.dataserver.Datum; -import com.alipay.sofa.registry.common.model.dataserver.SyncData; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; -import com.alipay.sofa.registry.server.data.cache.DatumCache; -import com.alipay.sofa.registry.server.data.datasync.Operator; - import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; @@ -36,6 +29,14 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.common.model.dataserver.SyncData; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.server.data.datasync.Operator; +import com.alipay.sofa.registry.util.DatumVersionUtil; + /** * * @author shangyu.wh @@ -57,16 +58,19 @@ public class Acceptor { private final Lock read = readWriteLock.readLock(); private final Lock write = readWriteLock.writeLock(); + private final DatumCache datumCache; + /** * constructor * @param maxBufferSize * @param dataInfoId * @param dataCenter */ - public Acceptor(int maxBufferSize, String dataInfoId, String dataCenter) { + public Acceptor(int maxBufferSize, String dataInfoId, String dataCenter, DatumCache datumCache) { this.maxBufferSize = maxBufferSize; this.dataInfoId = dataInfoId; this.dataCenter = dataCenter; + this.datumCache = datumCache; } /** @@ -146,7 +150,7 @@ public SyncData process(Long currentVersion) { //first get all data if (operators.isEmpty()) { wholeDataTag = true; - retList.add(DatumCache.get(dataCenter, dataInfoId)); + retList.add(datumCache.get(dataCenter, dataInfoId)); LOGGER.info("Get all data!dataInfoID:{} dataCenter:{}.All data size{}:", dataInfoId, dataCenter, retList.size()); } else { @@ -162,7 +166,7 @@ public SyncData process(Long currentVersion) { "Append log queue is empty,Maybe all logs record expired or no operator append!So must get all data!dataInfoID:{} dataCenter:{}.queue size{}:", dataInfoId, dataCenter, logOperatorsOrder.size()); wholeDataTag = true; - retList.add(DatumCache.get(dataCenter, dataInfoId)); + retList.add(datumCache.get(dataCenter, dataInfoId)); syncData = new SyncData(dataInfoId, dataCenter, wholeDataTag, retList); } @@ -250,7 +254,8 @@ private boolean isFull() { private boolean isExpired(int durationSECS, long peekVersion) { durationSECS = (durationSECS > 0) ? durationSECS * 1000 : DEFAULT_DURATION_SECS * 1000; - boolean ret = System.currentTimeMillis() > peekVersion + durationSECS; + boolean ret = System.currentTimeMillis() > DatumVersionUtil.getRealTimestamp(peekVersion) + + durationSECS; if (LOGGER.isDebugEnabled()) { LOGGER.debug("now:" + System.currentTimeMillis() + " peek:" + peekVersion + " du:" + durationSECS + " result:" + ret); @@ -258,7 +263,7 @@ private boolean isExpired(int durationSECS, long peekVersion) { return ret; } - private void clearBefore() { + public void clearBefore() { write.lock(); try { diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/DataServerChangeEvent.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/DataServerChangeEvent.java index a41dfd113..447c3af8c 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/DataServerChangeEvent.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/DataServerChangeEvent.java @@ -29,14 +29,24 @@ */ public class DataServerChangeEvent { + /** + * node type enum + */ + public enum FromType { + CONNECT_TASK, META_NOTIFY, REGISTER_META + } + private DataServerChangeItem dataServerChangeItem; + private FromType fromType; + /** * constructor * @param dataServerChangeItem */ - public DataServerChangeEvent(DataServerChangeItem dataServerChangeItem) { + public DataServerChangeEvent(DataServerChangeItem dataServerChangeItem, FromType fromType) { this.dataServerChangeItem = dataServerChangeItem; + this.fromType = fromType; } /** @@ -45,7 +55,7 @@ public DataServerChangeEvent(DataServerChangeItem dataServerChangeItem) { * @param versionMap */ public DataServerChangeEvent(Map> serverMap, - Map versionMap) { + Map versionMap, FromType fromType) { if (serverMap == null) { serverMap = new HashMap<>(); } @@ -53,6 +63,8 @@ public DataServerChangeEvent(Map> serverMap, versionMap = new HashMap<>(); } this.dataServerChangeItem = new DataServerChangeItem(serverMap, versionMap); + + this.fromType = fromType; } /** @@ -63,4 +75,13 @@ public DataServerChangeEvent(Map> serverMap, public DataServerChangeItem getDataServerChangeItem() { return dataServerChangeItem; } + + /** + * Getter method for property fromType. + * + * @return property value of fromType + */ + public FromType getFromType() { + return fromType; + } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/StartTaskTypeEnum.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/StartTaskTypeEnum.java index a015a1f4d..49217c99f 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/StartTaskTypeEnum.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/StartTaskTypeEnum.java @@ -34,7 +34,7 @@ public enum StartTaskTypeEnum { CONNECT_DATA, /** - * ReNewNodeTask + * RenewNodeTask */ RENEW, diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/DataServerChangeEventHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/DataServerChangeEventHandler.java index b2b1ec0a5..d9a0a3d49 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/DataServerChangeEventHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/DataServerChangeEventHandler.java @@ -55,7 +55,7 @@ public class DataServerChangeEventHandler extends AbstractEventHandler localDataServers = dataServerCache.getDataServers( - dataServerBootstrapConfig.getLocalDataCenter()).keySet(); + dataServerConfig.getLocalDataCenter()).keySet(); //get changed dataservers Map> changedMap = dataServerCache - .compareAndSet(dataServerChangeItem); + .compareAndSet(dataServerChangeItem,event.getFromType()); if(!changedMap.isEmpty()) { for (Entry> changeEntry : changedMap.entrySet()) { String dataCenter = changeEntry.getKey(); @@ -102,34 +102,34 @@ public void doHandle(DataServerChangeEvent event) { Set ipSet = DataServerNodeFactory.getIps(dataCenter); for (String ip : ipSet) { if (!ips.contains(ip)) { - DataServerNodeFactory.remove(dataCenter, ip, dataServerBootstrapConfig); + DataServerNodeFactory.remove(dataCenter, ip, dataServerConfig); LOGGER.info( - "[DataServerChangeEventHandler] remove connection, datacenter:{}, ip:{}", - dataCenter, ip); + "[DataServerChangeEventHandler] remove connection, datacenter:{}, ip:{},from:{}", + dataCenter, ip,event.getFromType()); } } Long newVersion = dataServerCache.getDataCenterNewVersion(dataCenter); Map newDataNodes = dataServerCache.getNewDataServerMap(dataCenter); //if the datacenter is self, post LocalDataServerChangeEvent - if (dataServerBootstrapConfig.getLocalDataCenter().equals(dataCenter)) { + if (dataServerConfig.getLocalDataCenter().equals(dataCenter)) { Set newjoined = new HashSet<>(ips); newjoined.removeAll(localDataServers); //avoid input map reference operation DataServerNodeFactory MAP Map map = new ConcurrentHashMap<>(newDataNodes); - LOGGER.info("Node list change fire LocalDataServerChangeEvent,current node list={},version={}", - map.keySet(), newVersion); + LOGGER.info("Node list change fire LocalDataServerChangeEvent,current node list={},version={},from:{}", + map.keySet(), newVersion,event.getFromType()); eventCenter.post(new LocalDataServerChangeEvent(map, newjoined, dataServerChangeItem.getVersionMap() - .get(dataServerBootstrapConfig.getLocalDataCenter()), + .get(dataServerConfig.getLocalDataCenter()), newVersion)); } else { dataServerCache.updateItem(newDataNodes, newVersion, dataCenter); } } else { //if the datacenter which has no dataservers is not self, remove it - if (!dataServerBootstrapConfig.getLocalDataCenter().equals(dataCenter)) { + if (!dataServerConfig.getLocalDataCenter().equals(dataCenter)) { removeDataCenter(dataCenter); } Long newVersion = dataServerCache.getDataCenterNewVersion(dataCenter); @@ -148,8 +148,8 @@ public void doHandle(DataServerChangeEvent event) { if (!StringUtils.equals(ip, DataServerConfig.IP)) { Connection connection = dataServerNode.getConnection(); if (connection != null && !connection.isFine()) { - LOGGER.warn("[DataServerChangeEventHandler] dataServer connections is not fine,try to reconnect it,old connection={},dataCenter={}", - connection.getRemoteAddress(), dataCenter); + LOGGER.warn("[DataServerChangeEventHandler] dataServer connections is not fine,try to reconnect it,old connection={},dataCenter={},from:{}", + connection.getRemoteAddress(), dataCenter,event.getFromType()); connectDataServer(dataCenter, ip); } } @@ -170,8 +170,8 @@ private void connectDataServer(String dataCenter, String ip) { Connection conn = null; for (int tryCount = 0; tryCount < TRY_COUNT; tryCount++) { try { - conn = ((BoltChannel) dataNodeExchanger.connect(new URL(ip, - dataServerBootstrapConfig.getSyncDataPort()))).getConnection(); + conn = ((BoltChannel) dataNodeExchanger.connect(new URL(ip, dataServerConfig + .getSyncDataPort()))).getConnection(); break; } catch (Exception e) { LOGGER.error("[DataServerChangeEventHandler] connect dataServer {} in {} error", @@ -189,11 +189,8 @@ private void connectDataServer(String dataCenter, String ip) { "[DataServerChangeEventHandler] connect dataserver %s in %s failed five times,dataServer will not work,please check connect!", ip, dataCenter)); } - LOGGER.info("[DataServerChangeEventHandler] connect dataserver {} in {} success", ip, - dataCenter); //maybe get dataNode from metaServer,current has not start! register dataNode info to factory,wait for connect task next execute - DataServerNodeFactory.register(new DataServerNode(ip, dataCenter, conn), - dataServerBootstrapConfig); + DataServerNodeFactory.register(new DataServerNode(ip, dataCenter, conn), dataServerConfig); } /** diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/LocalDataServerChangeEventHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/LocalDataServerChangeEventHandler.java index 9a79171e6..d303d192e 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/LocalDataServerChangeEventHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/LocalDataServerChangeEventHandler.java @@ -16,6 +16,7 @@ */ package com.alipay.sofa.registry.server.data.event.handler; +import com.alipay.remoting.Connection; import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.NotifyFetchDatumRequest; @@ -25,18 +26,20 @@ import com.alipay.sofa.registry.consistency.hash.ConsistentHash; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.bolt.BoltChannel; import com.alipay.sofa.registry.remoting.exchange.message.Request; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; import com.alipay.sofa.registry.server.data.cache.BackupTriad; import com.alipay.sofa.registry.server.data.cache.DataServerCache; import com.alipay.sofa.registry.server.data.cache.DatumCache; -import com.alipay.sofa.registry.server.data.correction.LocalDataServerCleanHandler; import com.alipay.sofa.registry.server.data.event.LocalDataServerChangeEvent; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; import com.alipay.sofa.registry.server.data.node.DataNodeStatus; import com.alipay.sofa.registry.server.data.node.DataServerNode; import com.alipay.sofa.registry.server.data.remoting.DataNodeExchanger; import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerNodeFactory; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; +import com.alipay.sofa.registry.server.data.renew.LocalDataServerCleanHandler; import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; import com.alipay.sofa.registry.server.data.util.TimeUtil; import com.google.common.collect.Lists; @@ -46,7 +49,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; @@ -66,7 +68,7 @@ public class LocalDataServerChangeEventHandler extends .getLogger(LocalDataServerChangeEventHandler.class); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private LocalDataServerCleanHandler localDataServerCleanHandler; @@ -80,10 +82,18 @@ public class LocalDataServerChangeEventHandler extends @Autowired private DataNodeStatus dataNodeStatus; + @Autowired + private DatumCache datumCache; + + @Autowired + private DatumLeaseManager datumLeaseManager; + private BlockingQueue events = new LinkedBlockingDeque<>(); private AtomicBoolean isChanged = new AtomicBoolean(false); + private static final int TRY_COUNT = 5; + @Override public Class interest() { return LocalDataServerChangeEvent.class; @@ -92,7 +102,11 @@ public Class interest() { @Override public void doHandle(LocalDataServerChangeEvent localDataServerChangeEvent) { isChanged.set(true); + + // Better change to Listener pattern localDataServerCleanHandler.reset(); + datumLeaseManager.reset(); + events.offer(localDataServerChangeEvent); } @@ -119,11 +133,11 @@ public void run() { try { LocalDataServerChangeEvent event = events.take(); //if the new joined servers contains self, set status as INITIAL - Set newJoined = event.getNewJoined(); - if (newJoined.contains(DataServerConfig.IP) - && dataNodeStatus.getStatus() != LocalServerStatusEnum.INITIAL) { - dataNodeStatus.setStatus(LocalServerStatusEnum.INITIAL); - } + //Set newJoined = event.getNewJoined(); + //if (newJoined.contains(DataServerConfig.IP) + // && dataNodeStatus.getStatus() != LocalServerStatusEnum.INITIAL) { + // dataNodeStatus.setStatus(LocalServerStatusEnum.INITIAL); + //} //if size of events is greater than 0, not handle and continue, only handle the last one in the queue if (events.size() > 0) { continue; @@ -143,7 +157,7 @@ public void run() { dataServerCache.updateItem(event.getLocalDataServerMap(), event.getLocalDataCenterversion(), - dataServerBootstrapConfig.getLocalDataCenter()); + dataServerConfig.getLocalDataCenter()); } } catch (Throwable t) { LOGGER.error("sync local data error", t); @@ -162,7 +176,7 @@ private void notifyToFetch(LocalDataServerChangeEvent event, long changeVersion) Map dataServerMapIn = event.getLocalDataServerMap(); List dataServerNodeList = Lists.newArrayList(dataServerMapIn.values()); ConsistentHash consistentHash = new ConsistentHash<>( - dataServerBootstrapConfig.getNumberOfReplicas(), dataServerNodeList); + dataServerConfig.getNumberOfReplicas(), dataServerNodeList); Map dataServerMap = new ConcurrentHashMap<>(dataServerMapIn); Map>> toBeSyncMap = getToBeSyncMap(consistentHash); @@ -182,7 +196,7 @@ private void notifyToFetch(LocalDataServerChangeEvent event, long changeVersion) for (Entry dataTriadEntry : dataTriadMap .entrySet()) { String dataInfoId = dataTriadEntry.getKey(); - Datum datum = DatumCache.get(dataCenter, dataInfoId); + Datum datum = datumCache.get(dataCenter, dataInfoId); if (datum != null) { versionMap.put(dataInfoId, datum.getVersion()); } @@ -212,7 +226,7 @@ private void notifyToFetch(LocalDataServerChangeEvent event, long changeVersion) if (!isChanged.get()) { //update server list dataServerCache.updateItem(dataServerMapIn, event.getLocalDataCenterversion(), - dataServerBootstrapConfig.getLocalDataCenter()); + dataServerConfig.getLocalDataCenter()); } } } @@ -229,14 +243,14 @@ private void notifyToFetch(LocalDataServerChangeEvent event, long changeVersion) Map> triadCache = new HashMap<>(); ConsistentHash consistentHashOld = dataServerCache - .calculateOldConsistentHash(dataServerBootstrapConfig.getLocalDataCenter()); + .calculateOldConsistentHash(dataServerConfig.getLocalDataCenter()); if (consistentHash == null) { LOGGER.error("Calculate Old ConsistentHash error!"); throw new RuntimeException("Calculate Old ConsistentHash error!"); } //compute new triad for every datum in cache - Map> allMap = DatumCache.getAll(); + Map> allMap = datumCache.getAll(); for (Entry> dataCenterEntry : allMap.entrySet()) { String dataCenter = dataCenterEntry.getKey(); Map datumMap = dataCenterEntry.getValue(); @@ -251,12 +265,12 @@ private void notifyToFetch(LocalDataServerChangeEvent event, long changeVersion) backupNodes = triadCache.get(dataInfoId); } else { backupNodes = consistentHash.getNUniqueNodesFor(dataInfoId, - dataServerBootstrapConfig.getStoreNodes()); + dataServerConfig.getStoreNodes()); triadCache.put(dataInfoId, backupNodes); } BackupTriad backupTriad = new BackupTriad(dataInfoId, consistentHashOld.getNUniqueNodesFor(dataInfoId, - dataServerBootstrapConfig.getStoreNodes())); + dataServerConfig.getStoreNodes())); if (backupTriad != null) { List newJoinedNodes = backupTriad.getNewJoined(backupNodes, dataServerCache.getNotWorking()); @@ -296,7 +310,7 @@ private boolean doNotify(String targetIp, Map> notifyV long version) { while (!isChanged.get()) { DataServerNode targetNode = DataServerNodeFactory.getDataServerNode( - dataServerBootstrapConfig.getLocalDataCenter(), targetIp); + dataServerConfig.getLocalDataCenter(), targetIp); if (targetNode == null || targetNode.getConnection() == null) { LOGGER.info( "notify version change to sync has not connect,targetNode={}, map={}", @@ -343,31 +357,37 @@ public URL getRequestUrl() { */ private void notifyOnline(long changeVersion) { Map dataServerNodeMap = DataServerNodeFactory - .getDataServerNodes(dataServerBootstrapConfig.getLocalDataCenter()); + .getDataServerNodes(dataServerConfig.getLocalDataCenter()); for (Entry serverEntry : dataServerNodeMap.entrySet()) { while (true) { String ip = serverEntry.getKey(); - DataServerNode dataServerNode = serverEntry.getValue(); + DataServerNode dataServerNode = DataServerNodeFactory.getDataServerNode( + dataServerConfig.getLocalDataCenter(), ip); + if (dataServerNode == null) { + LOGGER + .warn( + "notify Online dataserver {} has not existed in DataServerNodeFactory!version={}", + ip, changeVersion); break; } try { - if (dataServerNode.getConnection() == null - || !dataServerNode.getConnection().isFine()) { - LOGGER - .warn( - "notify Online dataserver connect {} not existed or not fine!version={}", - ip, changeVersion); - Map dataServerNodeMapCurrent = DataServerNodeFactory - .getDataServerNodes(dataServerBootstrapConfig.getLocalDataCenter()); - DataServerNode dataServerNodeCurrent = dataServerNodeMapCurrent.get(ip); - if (dataServerNodeCurrent == null) { + final Connection connection = dataServerNode.getConnection(); + if (connection == null || !connection.isFine()) { + if (connection == null) { LOGGER .warn( - "notify Online dataserver {} has not existed in DataServerNodeFactory!version={}", + "notify Online dataserver connect not existed,ip={},version={}", ip, changeVersion); - break; + } else { + LOGGER + .warn( + "notify Online dataserver connect not fine!remote={},local={},version={}", + connection.getRemoteAddress(), + connection.getLocalAddress(), changeVersion); } + //connect now and registry connect + connectDataServer(dataServerConfig.getLocalDataCenter(), ip); //maybe get dataNode from metaServer,current has not connected!wait for connect task execute TimeUtil.randomDelay(1000); continue; @@ -383,8 +403,8 @@ public Object getRequestBody() { @Override public URL getRequestUrl() { - return new URL(dataServerNode.getConnection().getRemoteIP(), - dataServerNode.getConnection().getRemotePort()); + return new URL(connection.getRemoteIP(), connection + .getRemotePort()); } }).getResult(); if (response.isSuccess()) { @@ -403,5 +423,44 @@ public URL getRequestUrl() { } } + /** + * connect specific dataserver + * + * @param dataCenter + * @param ip + */ + private void connectDataServer(String dataCenter, String ip) { + Connection conn = null; + for (int tryCount = 0; tryCount < TRY_COUNT; tryCount++) { + try { + conn = ((BoltChannel) dataNodeExchanger.connect(new URL(ip, dataServerConfig + .getSyncDataPort()))).getConnection(); + break; + } catch (Exception e) { + LOGGER.error( + "[LocalDataServerChangeEventHandler] connect dataServer {} in {} error", + ip, dataCenter, e); + TimeUtil.randomDelay(3000); + } + } + if (conn == null || !conn.isFine()) { + LOGGER + .error( + "[LocalDataServerChangeEventHandler] connect dataserver {} in {} failed five times", + ip, dataCenter); + throw new RuntimeException( + String + .format( + "[LocalDataServerChangeEventHandler] connect dataserver %s in %s failed five times,dataServer will not work,please check connect!", + ip, dataCenter)); + } + LOGGER + .info( + "[LocalDataServerChangeEventHandler] connect dataserver in {} success,remote={},local={}", + dataCenter, conn.getRemoteAddress(), conn.getLocalAddress()); + //maybe get dataNode from metaServer,current has not start! register dataNode info to factory,wait for connect task next execute + DataServerNodeFactory.register(new DataServerNode(ip, dataCenter, conn), + dataServerConfig); + } } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/MetaServerChangeEventHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/MetaServerChangeEventHandler.java index 9b035c98b..1498d8947 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/MetaServerChangeEventHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/event/handler/MetaServerChangeEventHandler.java @@ -56,7 +56,7 @@ public class MetaServerChangeEventHandler extends AbstractEventHandler dataClientHandlers; @@ -60,11 +62,11 @@ public Response request(Request request) { if (null != request.getCallBackHandler()) { client.sendCallback(channel, request.getRequestBody(), request.getCallBackHandler(), - dataServerBootstrapConfig.getRpcTimeout()); + dataServerConfig.getRpcTimeout()); return () -> Response.ResultStatus.SUCCESSFUL; } else { final Object result = client.sendSync(channel, request.getRequestBody(), - dataServerBootstrapConfig.getRpcTimeout()); + dataServerConfig.getRpcTimeout()); return () -> result; } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/MetaNodeExchanger.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/MetaNodeExchanger.java index 607beec97..c79b8dabf 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/MetaNodeExchanger.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/MetaNodeExchanger.java @@ -16,6 +16,12 @@ */ package com.alipay.sofa.registry.server.data.remoting; +import java.util.Collection; + +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; @@ -29,10 +35,6 @@ import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractClientHandler; import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.annotation.Resource; -import java.util.Collection; /** * @author xuanbei @@ -49,7 +51,7 @@ public class MetaNodeExchanger implements NodeExchanger { private IMetaServerService metaServerService; @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Resource(name = "metaClientHandlers") private Collection metaClientHandlers; @@ -63,12 +65,12 @@ public Response request(Request request) { try { final Object result = client.sendSync(channel, request.getRequestBody(), - dataServerBootstrapConfig.getRpcTimeout()); + dataServerConfig.getRpcTimeout()); return () -> result; } catch (Exception e) { //retry URL url = new URL(metaServerService.refreshLeader().getIp(), - dataServerBootstrapConfig.getMetaServerPort()); + dataServerConfig.getMetaServerPort()); channel = client.getChannel(url); if (channel == null) { channel = client.connect(url); @@ -76,7 +78,7 @@ public Response request(Request request) { LOGGER.warn("MetaNode Exchanger request send error!It will be retry once!Request url:{}", url); final Object result = client.sendSync(channel, request.getRequestBody(), - dataServerBootstrapConfig.getRpcTimeout()); + dataServerConfig.getRpcTimeout()); return () -> result; } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/DataServerNodeFactory.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/DataServerNodeFactory.java index 53a484bea..f13e88355 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/DataServerNodeFactory.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/DataServerNodeFactory.java @@ -59,14 +59,18 @@ public class DataServerNodeFactory { * * @param dataServerNode */ - public static void register(DataServerNode dataServerNode, - DataServerConfig dataServerBootstrapConfig) { + public static void register(DataServerNode dataServerNode, DataServerConfig dataServerConfig) { String dataCenter = dataServerNode.getDataCenter(); - if (!MAP.containsKey(dataCenter)) { - MAP.put(dataCenter, new ConcurrentHashMap<>()); + Map dataMap = MAP.get(dataCenter); + if (dataMap == null) { + Map newMap = new ConcurrentHashMap<>(); + dataMap = MAP.putIfAbsent(dataCenter, newMap); + if (dataMap == null) { + dataMap = newMap; + } } - MAP.get(dataCenter).put(dataServerNode.getIp(), dataServerNode); - refreshConsistent(dataCenter, dataServerBootstrapConfig); + dataMap.put(dataServerNode.getIp(), dataServerNode); + refreshConsistent(dataCenter, dataServerConfig); } /** @@ -74,31 +78,29 @@ public static void register(DataServerNode dataServerNode, * * @param dataCenter */ - public static void refreshConsistent(String dataCenter, - DataServerConfig dataServerBootstrapConfig) { + public static void refreshConsistent(String dataCenter, DataServerConfig dataServerConfig) { List dataServerNodes = Lists.newArrayList(MAP.get(dataCenter).values()); - if (dataServerBootstrapConfig.getLocalDataCenter().equals(dataCenter)) { + if (dataServerConfig.getLocalDataCenter().equals(dataCenter)) { if (!MAP.get(dataCenter).keySet().contains(DataServerConfig.IP)) { - dataServerNodes.add(new DataServerNode(DataServerConfig.IP, - dataServerBootstrapConfig.getLocalDataCenter(), null)); + dataServerNodes.add(new DataServerNode(DataServerConfig.IP, dataServerConfig + .getLocalDataCenter(), null)); } } CONSISTENT_HASH_MAP.put(dataCenter, - new ConsistentHash<>(dataServerBootstrapConfig.getNumberOfReplicas(), dataServerNodes)); + new ConsistentHash<>(dataServerConfig.getNumberOfReplicas(), dataServerNodes)); } /** * for single node consistentHash - * @param dataServerBootstrapConfig + * @param dataServerConfig */ - public static void initConsistent(DataServerConfig dataServerBootstrapConfig) { + public static void initConsistent(DataServerConfig dataServerConfig) { if (init.compareAndSet(false, true)) { List dataServerNodes = Lists.newArrayList(); - dataServerNodes.add(new DataServerNode(DataServerConfig.IP, dataServerBootstrapConfig + dataServerNodes.add(new DataServerNode(DataServerConfig.IP, dataServerConfig .getLocalDataCenter(), null)); - CONSISTENT_HASH_MAP.put(dataServerBootstrapConfig.getLocalDataCenter(), - new ConsistentHash<>(dataServerBootstrapConfig.getNumberOfReplicas(), - dataServerNodes)); + CONSISTENT_HASH_MAP.put(dataServerConfig.getLocalDataCenter(), new ConsistentHash<>( + dataServerConfig.getNumberOfReplicas(), dataServerNodes)); } } @@ -155,8 +157,7 @@ public static Set getIps(String dataCenter) { * @param dataCenter * @param ip */ - public static void remove(String dataCenter, String ip, - DataServerConfig dataServerBootstrapConfig) { + public static void remove(String dataCenter, String ip, DataServerConfig dataServerConfig) { if (MAP.containsKey(dataCenter)) { Map map = MAP.get(dataCenter); if (map != null) { @@ -168,7 +169,7 @@ public static void remove(String dataCenter, String ip, map.remove(ip); } } - refreshConsistent(dataCenter, dataServerBootstrapConfig); + refreshConsistent(dataCenter, dataServerConfig); } /** diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/FetchDataHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/FetchDataHandler.java index 76c9c0b33..0ebcab135 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/FetchDataHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/FetchDataHandler.java @@ -16,6 +16,10 @@ */ package com.alipay.sofa.registry.server.data.remoting.dataserver.handler; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.GenericResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -25,8 +29,6 @@ import com.alipay.sofa.registry.server.data.remoting.handler.AbstractClientHandler; import com.alipay.sofa.registry.util.ParaCheckUtil; -import java.util.Map; - /** * processor to get specific data * @@ -35,6 +37,9 @@ */ public class FetchDataHandler extends AbstractClientHandler { + @Autowired + private DatumCache datumCache; + @Override public void checkParam(GetDataRequest request) throws RuntimeException { ParaCheckUtil.checkNotBlank(request.getDataInfoId(), "GetDataRequest.dataInfoId"); @@ -42,7 +47,7 @@ public void checkParam(GetDataRequest request) throws RuntimeException { @Override public Object doHandle(Channel channel, GetDataRequest request) { - return new GenericResponse>().fillSucceed(DatumCache + return new GenericResponse>().fillSucceed(datumCache .getDatumGroupByDataCenter(request.getDataCenter(), request.getDataInfoId())); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyDataSyncHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyDataSyncHandler.java index af94482d1..afdf1f191 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyDataSyncHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyDataSyncHandler.java @@ -60,7 +60,7 @@ public class NotifyDataSyncHandler extends AbstractClientHandler noWorkQueue = new LinkedBlockingQueue<>(); @Override @@ -98,23 +101,21 @@ public Object doHandle(Channel channel, NotifyDataSyncRequest request) { return CommonResponse.buildSuccessResponse(); } - private void executorRequest(Connection connection,NotifyDataSyncRequest request){ + private void executorRequest(Connection connection, NotifyDataSyncRequest request) { executor.execute(() -> { String dataInfoId = request.getDataInfoId(); String dataCenter = request.getDataCenter(); - Datum datum = DatumCache.get(dataCenter, dataInfoId); + Datum datum = datumCache.get(dataCenter, dataInfoId); Long version = (datum == null) ? null : datum.getVersion(); Long requestVersion = request.getVersion(); if (version == null || requestVersion == 0L || version < requestVersion) { - LOGGER.info( - "[NotifyDataSyncProcessor] begin get sync data, currentVersion={},request={}", version, + LOGGER.info("[NotifyDataSyncProcessor] begin get sync data, currentVersion={},request={}", version, request); - getSyncDataHandler - .syncData(new SyncDataCallback(getSyncDataHandler, connection, new SyncDataRequest(dataInfoId, - dataCenter, version, request.getDataSourceType()), dataChangeEventCenter)); + getSyncDataHandler.syncData(new SyncDataCallback(getSyncDataHandler, connection, + new SyncDataRequest(dataInfoId, dataCenter, version, request.getDataSourceType()), + dataChangeEventCenter)); } else { - LOGGER.info( - "[NotifyDataSyncHandler] not need to sync data, version={}", version); + LOGGER.info("[NotifyDataSyncHandler] not need to sync data, currentVersion={},request={}", version,request); } }); } @@ -152,11 +153,10 @@ public Class interest() { public Executor getExecutor() { if (notifyExecutor == null) { notifyExecutor = new ThreadPoolExecutorDataServer("NotifyDataSyncProcessorExecutor", - dataServerBootstrapConfig.getNotifyDataSyncExecutorMinPoolSize(), - dataServerBootstrapConfig.getNotifyDataSyncExecutorMaxPoolSize(), - dataServerBootstrapConfig.getNotifyDataSyncExecutorKeepAliveTime(), - TimeUnit.SECONDS, new ArrayBlockingQueue<>( - dataServerBootstrapConfig.getNotifyDataSyncExecutorQueueSize()), + dataServerConfig.getNotifyDataSyncExecutorMinPoolSize(), + dataServerConfig.getNotifyDataSyncExecutorMaxPoolSize(), + dataServerConfig.getNotifyDataSyncExecutorKeepAliveTime(), TimeUnit.SECONDS, + new ArrayBlockingQueue<>(dataServerConfig.getNotifyDataSyncExecutorQueueSize()), new NamedThreadFactory("DataServer-NotifyDataSyncProcessor-executor", true)); } return notifyExecutor; diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyFetchDatumHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyFetchDatumHandler.java index cb11bf076..828452533 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyFetchDatumHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/handler/NotifyFetchDatumHandler.java @@ -23,6 +23,7 @@ import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.GetDataRequest; import com.alipay.sofa.registry.common.model.dataserver.NotifyFetchDatumRequest; +import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.Channel; @@ -37,6 +38,7 @@ import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerConnectionFactory; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; +import com.alipay.sofa.registry.server.data.renew.LocalDataServerCleanHandler; import com.alipay.sofa.registry.server.data.util.TimeUtil; import com.alipay.sofa.registry.util.ParaCheckUtil; import org.springframework.beans.factory.annotation.Autowired; @@ -63,14 +65,17 @@ public class NotifyFetchDatumHandler extends AbstractServerHandler> versionMap = request.getDataVersionMap(); long version = request.getChangeVersion(); String ip = request.getIp(); if (version >= dataServerCache.getCurVersion()) { if (versionMap.isEmpty()) { - LOGGER - .info( - "[NotifyFetchDatumHandler] get changeVersion map is empty,change version is {},current version is {},ip is {}", - version, dataServerCache.getCurVersion(), ip); + LOGGER.info( + "[NotifyFetchDatumHandler] get changeVersion map is empty,change version is {},current version is {},ip is {}", + version, dataServerCache.getCurVersion(), ip); dataServerCache.synced(version, ip); } else { ExecutorFactory.getCommonExecutor().execute(() -> { @@ -97,7 +105,7 @@ public Object doHandle(Channel channel, NotifyFetchDatumRequest request) { Map map = dataCenterEntry.getValue(); for (Entry dataInfoEntry : map.entrySet()) { String dataInfoId = dataInfoEntry.getKey(); - Datum datum = DatumCache.get(dataCenter, dataInfoId); + Datum datum = datumCache.get(dataCenter, dataInfoId); if (datum != null) { long inVersion = dataInfoEntry.getValue(); long currentVersion = datum.getVersion(); @@ -121,8 +129,7 @@ public Object doHandle(Channel channel, NotifyFetchDatumRequest request) { }); } } else { - LOGGER.info( - "[NotifyFetchDatumHandler] ignore notify because changeVersion {} is less than {},ip is {}", + LOGGER.info("[NotifyFetchDatumHandler] ignore notify because changeVersion {} is less than {},ip is {}", version, dataServerCache.getCurVersion(), ip); } return CommonResponse.buildSuccessResponse(); @@ -136,23 +143,22 @@ public Object doHandle(Channel channel, NotifyFetchDatumRequest request) { * @param dataInfoId */ private void fetchDatum(String targetIp, String dataCenter, String dataInfoId) { - while ((dataServerCache.getDataServers(dataServerConfig.getLocalDataCenter()).keySet()) - .contains(targetIp)) { + while (dataServerConnectionFactory.getConnection(targetIp) != null) { Connection connection = dataServerConnectionFactory.getConnection(targetIp); if (connection == null || !connection.isFine()) { throw new RuntimeException(String.format("connection of %s is not available", targetIp)); } try { - Server syncServer = boltExchange.getServer(dataServerBootstrapConfig - .getSyncDataPort()); + Server syncServer = boltExchange.getServer(dataServerConfig.getSyncDataPort()); GenericResponse> response = (GenericResponse>) syncServer .sendSync(syncServer.getChannel(connection.getRemoteAddress()), new GetDataRequest(dataInfoId, dataCenter), - dataServerBootstrapConfig.getRpcTimeout()); + dataServerConfig.getRpcTimeout()); if (response.isSuccess()) { Datum datum = response.getData().get(dataCenter); if (datum != null) { + processDatum(datum); dataChangeEventCenter.sync(DataChangeTypeEnum.COVER, DataSourceTypeEnum.BACKUP, datum); LOGGER @@ -171,6 +177,16 @@ private void fetchDatum(String targetIp, String dataCenter, String dataInfoId) { } } + private void processDatum(Datum datum) { + if (datum != null) { + Map publisherMap = datum.getPubMap(); + + if (publisherMap != null && !publisherMap.isEmpty()) { + publisherMap.forEach((registerId, publisher) -> Publisher.processPublisher(publisher)); + } + } + } + @Override public CommonResponse buildFailedResponse(String msg) { return CommonResponse.buildFailedResponse(msg); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ConnectionRefreshTask.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ConnectionRefreshTask.java index 041bb2bc4..9e1b96586 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ConnectionRefreshTask.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ConnectionRefreshTask.java @@ -18,6 +18,7 @@ import com.alipay.sofa.registry.server.data.cache.DataServerChangeItem; import com.alipay.sofa.registry.server.data.event.DataServerChangeEvent; +import com.alipay.sofa.registry.server.data.event.DataServerChangeEvent.FromType; import com.alipay.sofa.registry.server.data.event.EventCenter; import com.alipay.sofa.registry.server.data.event.StartTaskTypeEnum; import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; @@ -42,7 +43,8 @@ public class ConnectionRefreshTask extends AbstractTask { public void handle() { DataServerChangeItem dataServerChangeItem = metaServerService.getDateServers(); if (dataServerChangeItem != null) { - eventCenter.post(new DataServerChangeEvent(dataServerChangeItem)); + eventCenter + .post(new DataServerChangeEvent(dataServerChangeItem, FromType.CONNECT_TASK)); } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ReNewNodeTask.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/RenewNodeTask.java similarity index 91% rename from server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ReNewNodeTask.java rename to server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/RenewNodeTask.java index 8275cbfef..965fc9f40 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/ReNewNodeTask.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/dataserver/task/RenewNodeTask.java @@ -25,16 +25,16 @@ /** * * @author shangyu.wh - * @version $Id: ReNewNodeTask.java, v 0.1 2018-04-02 20:56 shangyu.wh Exp $ + * @version $Id: RenewNodeTask.java, v 0.1 2018-04-02 20:56 shangyu.wh Exp $ */ -public class ReNewNodeTask extends AbstractTask { +public class RenewNodeTask extends AbstractTask { @Autowired private IMetaServerService metaServerService; @Override public void handle() { - metaServerService.reNewNodeTask(); + metaServerService.renewNodeTask(); } @Override diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/handler/AbstractClientHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/handler/AbstractClientHandler.java index 8f48d5166..13563f506 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/handler/AbstractClientHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/handler/AbstractClientHandler.java @@ -29,7 +29,10 @@ */ public abstract class AbstractClientHandler implements ChannelHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClientHandler.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(AbstractClientHandler.class); + + private static final Logger LOGGER_EXCHANGE = LoggerFactory.getLogger("DATA-EXCHANGE"); @Override public void connected(Channel channel) { @@ -64,7 +67,7 @@ public void received(Channel channel, T message) { @Override public Object reply(Channel channel, T request) { try { - logRequest(request); + logRequest(channel, request); checkParam(request); return doHandle(channel, request); } catch (Exception e) { @@ -102,8 +105,13 @@ public Object reply(Channel channel, T request) { * * @param request */ - protected void logRequest(T request) { - log(request.toString()); + protected void logRequest(Channel channel, T request) { + if (channel != null) { + log(new StringBuilder("Remote:").append(channel.getRemoteAddress()).append(" Request:") + .append(request).toString()); + } else { + log(request.toString()); + } } /** @@ -112,7 +120,7 @@ protected void logRequest(T request) { * @param log */ protected void log(String log) { - LOGGER.info(new StringBuilder("[").append(getClassName()).append("] ").append(log) + LOGGER_EXCHANGE.info(new StringBuilder("[").append(getClassName()).append("] ").append(log) .toString()); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/DefaultMetaServiceImpl.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/DefaultMetaServiceImpl.java index ac94deb3e..5a5ebf4c1 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/DefaultMetaServiceImpl.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/DefaultMetaServiceImpl.java @@ -21,16 +21,19 @@ import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.metaserver.DataNode; +import com.alipay.sofa.registry.common.model.metaserver.FetchProvideDataRequest; import com.alipay.sofa.registry.common.model.metaserver.GetNodesRequest; import com.alipay.sofa.registry.common.model.metaserver.MetaNode; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; -import com.alipay.sofa.registry.common.model.metaserver.ReNewNodesRequest; +import com.alipay.sofa.registry.common.model.metaserver.ProvideData; +import com.alipay.sofa.registry.common.model.metaserver.RenewNodesRequest; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.jraft.bootstrap.RaftClient; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.bolt.BoltChannel; import com.alipay.sofa.registry.remoting.exchange.message.Request; +import com.alipay.sofa.registry.remoting.exchange.message.Response; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; import com.alipay.sofa.registry.server.data.cache.DataServerChangeItem; import com.alipay.sofa.registry.server.data.node.DataServerNode; @@ -60,7 +63,7 @@ public class DefaultMetaServiceImpl implements IMetaServerService { .getLogger(DefaultMetaServiceImpl.class); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private MetaNodeExchanger metaNodeExchanger; @@ -75,25 +78,24 @@ public class DefaultMetaServiceImpl implements IMetaServerService { @Override public Map> getMetaServerMap() { HashMap> map = new HashMap<>(); - Set set = dataServerBootstrapConfig.getMetaServerIpAddresses(); + Set set = dataServerConfig.getMetaServerIpAddresses(); Map connectionMap = metaServerConnectionFactory - .getConnections(dataServerBootstrapConfig.getLocalDataCenter()); + .getConnections(dataServerConfig.getLocalDataCenter()); Connection connection = null; try { if (connectionMap.isEmpty()) { List list = new ArrayList(set); Collections.shuffle(list); connection = ((BoltChannel) metaNodeExchanger.connect(new URL(list.iterator() - .next(), dataServerBootstrapConfig.getMetaServerPort()))).getConnection(); + .next(), dataServerConfig.getMetaServerPort()))).getConnection(); } else { List connections = new ArrayList<>(connectionMap.values()); Collections.shuffle(connections); connection = connections.iterator().next(); if (!connection.isFine()) { connection = ((BoltChannel) metaNodeExchanger.connect(new URL(connection - .getRemoteIP(), dataServerBootstrapConfig.getMetaServerPort()))) - .getConnection(); + .getRemoteIP(), dataServerConfig.getMetaServerPort()))).getConnection(); } } @@ -115,11 +117,10 @@ public URL getRequestUrl() { Map> metaNodesMap = result.getNodes(); if (metaNodesMap != null && !metaNodesMap.isEmpty()) { - Map metaNodeMap = metaNodesMap.get(dataServerBootstrapConfig + Map metaNodeMap = metaNodesMap.get(dataServerConfig .getLocalDataCenter()); if (metaNodeMap != null && !metaNodeMap.isEmpty()) { - map.put(dataServerBootstrapConfig.getLocalDataCenter(), - metaNodeMap.keySet()); + map.put(dataServerConfig.getLocalDataCenter(), metaNodeMap.keySet()); } else { LOGGER .error( @@ -150,13 +151,13 @@ public DataServerNode getDataServer(String dataCenter, String dataInfoId) { @Override public List getDataServers(String dataCenter, String dataInfoId) { return DataServerNodeFactory.computeDataServerNodes(dataCenter, dataInfoId, - dataServerBootstrapConfig.getStoreNodes()); + dataServerConfig.getStoreNodes()); } @Override public DataServerChangeItem getDateServers() { Map connectionMap = metaServerConnectionFactory - .getConnections(dataServerBootstrapConfig.getLocalDataCenter()); + .getConnections(dataServerConfig.getLocalDataCenter()); String leader = getLeader().getIp(); if (connectionMap.containsKey(leader)) { Connection connection = connectionMap.get(leader); @@ -203,14 +204,14 @@ public URL getRequestUrl() { @Override public List getOtherDataCenters() { Set all = new HashSet<>(DataServerNodeFactory.getAllDataCenters()); - all.remove(dataServerBootstrapConfig.getLocalDataCenter()); + all.remove(dataServerConfig.getLocalDataCenter()); return new ArrayList<>(all); } @Override - public void reNewNodeTask() { + public void renewNodeTask() { Map connectionMap = metaServerConnectionFactory - .getConnections(dataServerBootstrapConfig.getLocalDataCenter()); + .getConnections(dataServerConfig.getLocalDataCenter()); for (Entry connectEntry : connectionMap.entrySet()) { String ip = connectEntry.getKey(); //just send to leader @@ -218,13 +219,13 @@ public void reNewNodeTask() { Connection connection = connectEntry.getValue(); if (connection.isFine()) { try { - ReNewNodesRequest reNewNodesRequest = new ReNewNodesRequest<>( + RenewNodesRequest renewNodesRequest = new RenewNodesRequest<>( new DataNode(new URL(DataServerConfig.IP), - dataServerBootstrapConfig.getLocalDataCenter())); + dataServerConfig.getLocalDataCenter())); metaNodeExchanger.request(new Request() { @Override public Object getRequestBody() { - return reNewNodesRequest; + return renewNodesRequest; } @Override @@ -233,12 +234,12 @@ public URL getRequestUrl() { } }).getResult(); } catch (Exception e) { - LOGGER.error("[ReNewNodeTask] reNew data node to metaServer error : {}", + LOGGER.error("[RenewNodeTask] renew data node to metaServer error : {}", ip, e); String newip = refreshLeader().getIp(); LOGGER .warn( - "[ReNewNodeTask] reNew data node to metaServer error,leader refresh: {}", + "[RenewNodeTask] renew data node to metaServer error,leader refresh: {}", newip); } } else { @@ -252,6 +253,53 @@ public URL getRequestUrl() { } } + @Override + public ProvideData fetchData(String dataInfoId) { + + Map connectionMap = metaServerConnectionFactory + .getConnections(dataServerConfig.getLocalDataCenter()); + String leader = getLeader().getIp(); + if (connectionMap.containsKey(leader)) { + Connection connection = connectionMap.get(leader); + if (connection.isFine()) { + try { + Request request = new Request() { + + @Override + public FetchProvideDataRequest getRequestBody() { + + return new FetchProvideDataRequest(dataInfoId); + } + + @Override + public URL getRequestUrl() { + return new URL(connection.getRemoteIP(), connection.getRemotePort()); + } + }; + + Response response = metaNodeExchanger.request(request); + + Object result = response.getResult(); + if (result instanceof ProvideData) { + return (ProvideData) result; + } else { + LOGGER.error("fetch null provider data!"); + throw new RuntimeException("MetaNodeService fetch null provider data!"); + } + } catch (Exception e) { + LOGGER.error("fetch provider data error! " + e.getMessage(), e); + throw new RuntimeException("fetch provider data error! " + e.getMessage(), e); + } + } + } + String newip = refreshLeader().getIp(); + LOGGER.warn( + "[ConnectionRefreshTask] refresh connections metaServer not fine,refresh leader : {}", + newip); + return null; + + } + @Override public void startRaftClient() { try { @@ -268,7 +316,7 @@ public void startRaftClient() { private String getServerConfig() { String ret = ""; - Set ips = dataServerBootstrapConfig.getMetaServerIpAddresses(); + Set ips = dataServerConfig.getMetaServerIpAddresses(); if (ips != null && !ips.isEmpty()) { ret = ips.stream().map(ip -> ip + ":" + ValueConstants.RAFT_SERVER_PORT) .collect(Collectors.joining(",")); @@ -280,8 +328,7 @@ private String getServerConfig() { } private String getGroup() { - return ValueConstants.RAFT_SERVER_GROUP + "_" - + dataServerBootstrapConfig.getLocalDataCenter(); + return ValueConstants.RAFT_SERVER_GROUP + "_" + dataServerConfig.getLocalDataCenter(); } @Override diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/IMetaServerService.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/IMetaServerService.java index e98f8e453..d1cf4192f 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/IMetaServerService.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/IMetaServerService.java @@ -17,6 +17,7 @@ package com.alipay.sofa.registry.server.data.remoting.metaserver; import com.alipay.sofa.jraft.entity.PeerId; +import com.alipay.sofa.registry.common.model.metaserver.ProvideData; import com.alipay.sofa.registry.server.data.cache.DataServerChangeItem; import com.alipay.sofa.registry.server.data.node.DataServerNode; @@ -73,7 +74,7 @@ public interface IMetaServerService { /** * scheduler update data server expireTime */ - void reNewNodeTask(); + void renewNodeTask(); /** * start raft client for get leader send request @@ -91,4 +92,11 @@ public interface IMetaServerService { * @return */ PeerId refreshLeader(); + + /** + * get provider data + * @param dataInfoId + * @return + */ + ProvideData fetchData(String dataInfoId); } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/NotifyProvideDataChangeHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/NotifyProvideDataChangeHandler.java new file mode 100644 index 000000000..756a025cb --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/NotifyProvideDataChangeHandler.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.remoting.metaserver.handler; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.common.model.Node.NodeType; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.metaserver.DataOperator; +import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; +import com.alipay.sofa.registry.common.model.metaserver.ProvideData; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.Channel; +import com.alipay.sofa.registry.server.data.remoting.handler.AbstractClientHandler; +import com.alipay.sofa.registry.server.data.remoting.metaserver.IMetaServerService; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; + +/** + * + * @author shangyu.wh + * @version $Id: DataChangeRequestHandler.java, v 0.1 2017-12-12 15:09 shangyu.wh Exp $ + */ +public class NotifyProvideDataChangeHandler extends AbstractClientHandler { + + private static final Logger LOGGER = LoggerFactory + .getLogger(NotifyProvideDataChangeHandler.class); + + @Autowired + private IMetaServerService metaServerService; + + @Autowired + private DatumLeaseManager datumLeaseManager; + + @Override + public HandlerType getType() { + return HandlerType.PROCESSER; + } + + @Override + protected NodeType getConnectNodeType() { + return NodeType.DATA; + } + + @Override + public void checkParam(Object request) throws RuntimeException { + + } + + @Override + public Object doHandle(Channel channel, Object request) { + + NotifyProvideDataChange notifyProvideDataChange = (NotifyProvideDataChange) request; + + fireDataChangeFetchTask(notifyProvideDataChange); + return null; + } + + private void fireDataChangeFetchTask(NotifyProvideDataChange notifyProvideDataChange) { + + String dataInfoId = notifyProvideDataChange.getDataInfoId(); + if (notifyProvideDataChange.getDataOperator() != DataOperator.REMOVE) { + + if (ValueConstants.ENABLE_DATA_DATUM_EXPIRE.equals(dataInfoId)) { + ProvideData provideData = metaServerService.fetchData(dataInfoId); + if (provideData == null || provideData.getProvideData() == null + || provideData.getProvideData().getObject() == null) { + LOGGER + .info("Fetch enableDataDatumExpire but no data existed, current config not change!"); + return; + } + boolean enableDataDatumExpire = Boolean.parseBoolean((String) provideData + .getProvideData().getObject()); + LOGGER.info("Fetch enableDataDatumExpire {} success!", enableDataDatumExpire); + datumLeaseManager.setRenewEnable(enableDataDatumExpire); + } + } + } + + @Override + public Class interest() { + return NotifyProvideDataChange.class; + } + + @Override + public CommonResponse buildFailedResponse(String msg) { + return CommonResponse.buildFailedResponse(msg); + } + +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/ServerChangeHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/ServerChangeHandler.java index 0174f5776..0ace90cc8 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/ServerChangeHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/metaserver/handler/ServerChangeHandler.java @@ -24,6 +24,7 @@ import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; import com.alipay.sofa.registry.server.data.event.DataServerChangeEvent; +import com.alipay.sofa.registry.server.data.event.DataServerChangeEvent.FromType; import com.alipay.sofa.registry.server.data.event.EventCenter; import com.alipay.sofa.registry.server.data.event.MetaServerChangeEvent; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; @@ -57,7 +58,7 @@ public Object doHandle(Channel channel, NodeChangeResult request) { ExecutorFactory.getCommonExecutor().execute(() -> { if (request.getNodeType() == NodeType.DATA) { eventCenter.post(new DataServerChangeEvent(request.getNodes(), - request.getDataCenterListVersions())); + request.getDataCenterListVersions(), FromType.META_NOTIFY)); } else if (request.getNodeType() == NodeType.META) { Map> metaNodesMap = request.getNodes(); if (metaNodesMap != null && !metaNodesMap.isEmpty()) { diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/SessionServerConnectionFactory.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/SessionServerConnectionFactory.java index e8072e5ca..0ee31edf1 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/SessionServerConnectionFactory.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/SessionServerConnectionFactory.java @@ -16,14 +16,6 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver; -import com.alipay.remoting.Connection; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; -import com.alipay.sofa.registry.net.NetUtil; -import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.DisconnectEventHandler; -import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.SessionServerDisconnectEvent; -import org.springframework.beans.factory.annotation.Autowired; - import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -32,6 +24,15 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.remoting.Connection; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.net.NetUtil; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.DisconnectEventHandler; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.SessionServerDisconnectEvent; + /** * the factory to hold sesseionserver connections * @@ -39,29 +40,29 @@ * @version $Id: SessionServerConnectionFactory.java, v 0.1 2017-12-06 15:48 qian.lqlq Exp $ */ public class SessionServerConnectionFactory { - private static final Logger LOGGER = LoggerFactory - .getLogger(SessionServerConnectionFactory.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(SessionServerConnectionFactory.class); - private static final int DELAY = 30 * 1000; + private static final int DELAY = 30 * 1000; /** * collection of connections * key : processId * value : connection */ - private final Map MAP = new ConcurrentHashMap<>(); + private final Map MAP = new ConcurrentHashMap<>(); /** * key : sessionserver host * value: sesseionserver processId */ - private final Map PROCESSID_MAP = new ConcurrentHashMap<>(); + private final Map PROCESS_ID_MAP = new ConcurrentHashMap<>(); /** * key : sessionserver processId * value: ip:port of clients */ - private final Map> PROCESSID_CLIENT_MAP = new ConcurrentHashMap<>(); + private final Map> PROCESS_ID_CONNECT_ID_MAP = new ConcurrentHashMap<>(); @Autowired private DisconnectEventHandler disconnectEventHandler; @@ -70,41 +71,41 @@ public class SessionServerConnectionFactory { * register connection * * @param processId - * @param clientHosts + * @param connectIds * @param connection */ - public void register(String processId, Set clientHosts, Connection connection) { + public void register(String processId, Set connectIds, Connection connection) { String serverHost = NetUtil.toAddressString(connection.getRemoteAddress()); if (LOGGER.isInfoEnabled()) { LOGGER.info("session({}, processId={}) registered", serverHost, processId); } MAP.put(processId, new Pair(serverHost, connection)); - Set ret = PROCESSID_CLIENT_MAP.getOrDefault(processId, null); + Set ret = PROCESS_ID_CONNECT_ID_MAP.getOrDefault(processId, null); if (ret == null) { - PROCESSID_CLIENT_MAP.putIfAbsent(processId, new HashSet<>()); + PROCESS_ID_CONNECT_ID_MAP.putIfAbsent(processId, new HashSet<>()); } - PROCESSID_CLIENT_MAP.get(processId).addAll(clientHosts); - PROCESSID_MAP.put(serverHost, processId); + PROCESS_ID_CONNECT_ID_MAP.get(processId).addAll(connectIds); + PROCESS_ID_MAP.put(serverHost, processId); } /** * * @param processId - * @param clientAddress + * @param connectId */ - public void registerClient(String processId, String clientAddress) { - Set ret = PROCESSID_CLIENT_MAP.getOrDefault(processId, null); + public void registerConnectId(String processId, String connectId) { + Set ret = PROCESS_ID_CONNECT_ID_MAP.getOrDefault(processId, null); if (ret == null) { - PROCESSID_CLIENT_MAP.putIfAbsent(processId, new HashSet<>()); + PROCESS_ID_CONNECT_ID_MAP.putIfAbsent(processId, new HashSet<>()); } - PROCESSID_CLIENT_MAP.get(processId).add(clientAddress); + PROCESS_ID_CONNECT_ID_MAP.get(processId).add(connectId); } /** * remove connection by specific host */ public void removeProcess(String sessionServerHost) { - String processId = PROCESSID_MAP.remove(sessionServerHost); + String processId = PROCESS_ID_MAP.remove(sessionServerHost); if (LOGGER.isInfoEnabled()) { LOGGER.info("session({}, processId={}) unregistered", sessionServerHost, processId); } @@ -118,8 +119,8 @@ public void removeProcess(String sessionServerHost) { * * @param processId */ - public Set removeClients(String processId) { - return PROCESSID_CLIENT_MAP.remove(processId); + public Set removeConnectIds(String processId) { + return PROCESS_ID_CONNECT_ID_MAP.remove(processId); } /** diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/ClientDisconnectEvent.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/ClientDisconnectEvent.java index 3659db591..c3f233133 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/ClientDisconnectEvent.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/ClientDisconnectEvent.java @@ -23,16 +23,16 @@ */ public class ClientDisconnectEvent extends DisconnectEvent { - private String host; + private String connectId; /** * constructor - * @param host + * @param connectId * @param registerTimestamp * @param timeoutMs */ - public ClientDisconnectEvent(String host, long registerTimestamp, int timeoutMs) { - this.host = host; + public ClientDisconnectEvent(String connectId, long registerTimestamp, int timeoutMs) { + this.connectId = connectId; setRegisterTimestamp(registerTimestamp); setGmtOccur(System.currentTimeMillis()); setTimeoutMs(timeoutMs); @@ -40,12 +40,12 @@ public ClientDisconnectEvent(String host, long registerTimestamp, int timeoutMs) } /** - * Getter method for property host. + * Getter method for property connectId. * - * @return property value of host + * @return property value of connectId */ - public String getHost() { - return host; + public String getConnectId() { + return connectId; } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/DisconnectEventHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/DisconnectEventHandler.java index fa870f910..d386f21f0 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/DisconnectEventHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/disconnect/DisconnectEventHandler.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; @@ -26,15 +36,6 @@ import com.alipay.sofa.registry.server.data.node.DataNodeStatus; import com.alipay.sofa.registry.server.data.remoting.sessionserver.SessionServerConnectionFactory; import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; /** * @author qian.lqlq @@ -82,7 +83,8 @@ public void receive(DisconnectEvent event) { sessionServerDisconnectEvent.getProcessId()); } else if (event.getType() == DisconnectTypeEnum.CLIENT) { ClientDisconnectEvent clientDisconnectEvent = (ClientDisconnectEvent) event; - LOGGER.info("receive client off event: clientHost={}", clientDisconnectEvent.getHost()); + LOGGER.info("receive client off event: connectId={}", + clientDisconnectEvent.getConnectId()); } if (dataNodeStatus.getStatus() != LocalServerStatusEnum.WORKING) { @@ -95,7 +97,11 @@ public void receive(DisconnectEvent event) { public void afterWorkingProcess() { try { - //sleep for sync all done + /* + * After the snapshot data is synchronized during startup, it is queued and then placed asynchronously into + * DatumCache. When the notification becomes WORKING, there may be data in the queue that is not executed + * to DatumCache. So it need to sleep for a while. + */ TimeUnit.MILLISECONDS.sleep(BLOCK_FOR_ALL_SYNC); while (!noWorkQueue.isEmpty()) { @@ -123,22 +129,22 @@ public void afterPropertiesSet() { try { DisconnectEvent disconnectEvent = EVENT_QUEUE.take(); if (disconnectEvent.getType() == DisconnectTypeEnum.SESSION_SERVER) { - SessionServerDisconnectEvent event = (SessionServerDisconnectEvent) disconnectEvent; - String processId = event.getProcessId(); + SessionServerDisconnectEvent event = (SessionServerDisconnectEvent) disconnectEvent; + String processId = event.getProcessId(); //check processId confirm remove,and not be registered again when delay time String sessionServerHost = event.getSessionServerHost(); if (sessionServerConnectionFactory .removeProcessIfMatch(processId, sessionServerHost)) { - Set clientHosts = sessionServerConnectionFactory - .removeClients(processId); + Set connectIds = sessionServerConnectionFactory + .removeConnectIds(processId); - LOGGER.info("session off is triggered: sessionServerHost={}, clientHost={}, processId={}", + LOGGER.info("session off is triggered: sessionServerHost={}, connectId={}, processId={}", sessionServerHost, - clientHosts, processId); + connectIds, processId); - if (clientHosts != null && !clientHosts.isEmpty()) { - for (String host : clientHosts) { - unPub(host, event.getRegisterTimestamp()); + if (connectIds != null && !connectIds.isEmpty()) { + for (String connectId : connectIds) { + unPub(connectId, event.getRegisterTimestamp()); } } } else { @@ -147,7 +153,7 @@ public void afterPropertiesSet() { } } else { ClientDisconnectEvent event = (ClientDisconnectEvent) disconnectEvent; - unPub(event.getHost(), event.getRegisterTimestamp()); + unPub(event.getConnectId(), event.getRegisterTimestamp()); } } catch (Throwable e) { LOGGER.error("handle client disconnect event failed", e); @@ -159,11 +165,11 @@ public void afterPropertiesSet() { /** * - * @param host + * @param connectId * @param registerTimestamp */ - private void unPub(String host, long registerTimestamp) { - dataChangeEventCenter.onChange(new ClientChangeEvent(host, dataServerConfig + private void unPub(String connectId, long registerTimestamp) { + dataChangeEventCenter.onChange(new ClientChangeEvent(connectId, dataServerConfig .getLocalDataCenter(), registerTimestamp)); } } \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardService.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardService.java index 43931d46c..b896521fc 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardService.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardService.java @@ -28,10 +28,9 @@ public interface ForwardService { /** * Need forward boolean. * - * @param dataInfoId the data info id * @return the boolean */ - boolean needForward(String dataInfoId); + boolean needForward(); /** * Forward request object. diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardServiceImpl.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardServiceImpl.java index 7228bc03d..b8985153a 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardServiceImpl.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/forward/ForwardServiceImpl.java @@ -16,6 +16,10 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.forward; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.remoting.exception.RemotingException; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; @@ -28,9 +32,6 @@ import com.alipay.sofa.registry.server.data.remoting.DataNodeExchanger; import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerNodeFactory; import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.List; /** * The type Forward service. @@ -43,7 +44,7 @@ public class ForwardServiceImpl implements ForwardService { private static final Logger LOGGER = LoggerFactory.getLogger(ForwardServiceImpl.class); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private DataNodeStatus dataNodeStatus; @@ -52,10 +53,10 @@ public class ForwardServiceImpl implements ForwardService { private DataNodeExchanger dataNodeExchanger; /** - * @see ForwardService#needForward(String) + * @see ForwardService#needForward() */ @Override - public boolean needForward(String dataInfoId) { + public boolean needForward() { return dataNodeStatus.getStatus() != LocalServerStatusEnum.WORKING; } @@ -66,9 +67,9 @@ public boolean needForward(String dataInfoId) { public Object forwardRequest(String dataInfoId, Object request) throws RemotingException { try { // 1. get store nodes - List dataServerNodes = DataServerNodeFactory.computeDataServerNodes( - dataServerBootstrapConfig.getLocalDataCenter(), dataInfoId, - dataServerBootstrapConfig.getStoreNodes()); + List dataServerNodes = DataServerNodeFactory + .computeDataServerNodes(dataServerConfig.getLocalDataCenter(), dataInfoId, + dataServerConfig.getStoreNodes()); // 2. find next node if (null == dataServerNodes || dataServerNodes.size() <= 0) { diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/ClientOffHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/ClientOffHandler.java index 61724135b..5df47ec9d 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/ClientOffHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/ClientOffHandler.java @@ -16,6 +16,10 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.dataserver.ClientOffRequest; @@ -24,10 +28,8 @@ import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.ClientDisconnectEvent; import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.DisconnectEventHandler; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; import com.alipay.sofa.registry.util.ParaCheckUtil; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.List; /** * processor to remove data of specific clients immediately @@ -38,11 +40,14 @@ public class ClientOffHandler extends AbstractServerHandler { @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private DisconnectEventHandler disconnectEventHandler; + @Autowired + private DatumLeaseManager datumLeaseManager; + @Override public void checkParam(ClientOffRequest request) throws RuntimeException { ParaCheckUtil.checkNotEmpty(request.getHosts(), "ClientOffRequest.hosts"); @@ -52,8 +57,11 @@ public void checkParam(ClientOffRequest request) throws RuntimeException { public Object doHandle(Channel channel, ClientOffRequest request) { List hosts = request.getHosts(); for (String host : hosts) { + // stop task of this connectId + datumLeaseManager.remove(host); + disconnectEventHandler.receive(new ClientDisconnectEvent(host, request.getGmtOccur(), - dataServerBootstrapConfig.getClientOffDelayMs())); + dataServerConfig.getClientOffDelayMs())); } return CommonResponse.buildSuccessResponse(); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/DatumSnapshotHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/DatumSnapshotHandler.java new file mode 100644 index 000000000..3c43fc486 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/DatumSnapshotHandler.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.remoting.sessionserver.handler; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.PublisherDigestUtil; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.Channel; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.server.data.change.event.DataChangeEventCenter; +import com.alipay.sofa.registry.server.data.change.event.DatumSnapshotEvent; +import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; +import com.alipay.sofa.registry.util.ParaCheckUtil; + +/** + * handling snapshot request + * + * @author kezhu.wukz + * @version $Id: ClientOffProcessor.java, v 0.1 2019-05-30 15:48 kezhu.wukz Exp $ + */ +public class DatumSnapshotHandler extends AbstractServerHandler { + + private static final Logger RENEW_LOGGER = LoggerFactory.getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[DatumSnapshotHandler]"); + + /** Limited List Printing */ + private static final int LIMITED_LIST_SIZE_FOR_PRINT = 10; + + @Autowired + private DataChangeEventCenter dataChangeEventCenter; + + @Autowired + private DatumLeaseManager datumLeaseManager; + + @Autowired + private DatumCache datumCache; + + @Autowired + private ThreadPoolExecutor renewDatumProcessorExecutor; + + @Override + public Executor getExecutor() { + return renewDatumProcessorExecutor; + } + + @Override + public void checkParam(DatumSnapshotRequest request) throws RuntimeException { + ParaCheckUtil.checkNotBlank(request.getConnectId(), "DatumSnapshotRequest.connectId"); + ParaCheckUtil.checkNotEmpty(request.getPublishers(), "DatumSnapshotRequest.publishers"); + } + + @Override + public Object doHandle(Channel channel, DatumSnapshotRequest request) { + RENEW_LOGGER.info("Received datumSnapshotRequest: {}", request); + + Map pubMap = request.getPublishers().stream() + .collect(Collectors.toMap(p -> p.getRegisterId(), p -> p)); + + // diff the cache and snapshot + boolean isDiff = true; + Map cachePubMap = datumCache.getOwnByConnectId(request.getConnectId()); + if (cachePubMap == null) { + RENEW_LOGGER + .info(">>>>>>> connectId={}, cachePubMap.size=0, pubMap.size={}, isDiff={}, the diff is: pubMap={}", + request.getConnectId(), pubMap.size(), isDiff, limitedToString(pubMap.values())); + } else { + List diffPub1 = subtract(pubMap, cachePubMap); + List diffPub2 = subtract(cachePubMap, pubMap); + if (diffPub1.size() == 0 && diffPub2.size() == 0) { + isDiff = false; + } + RENEW_LOGGER + .info(">>>>>>> connectId={}, cachePubMap.size={}, pubMap.size={}, isDiff={}, the diff is: pubMap-cachePubMap=(size:{}){}, cachePubMap-pubMap=(size:{}){}", + request.getConnectId(), cachePubMap.size(), pubMap.size(), isDiff, diffPub1.size(), + limitedToString(diffPub1), diffPub2.size(), limitedToString(diffPub2)); + } + + if (isDiff) { + // build DatumSnapshotEvent and send to eventCenter + dataChangeEventCenter.onChange(new DatumSnapshotEvent(request.getConnectId(), cachePubMap, pubMap)); + } + + // record the renew timestamp + datumLeaseManager.renew(request.getConnectId()); + + return CommonResponse.buildSuccessResponse(); + } + + /** + * Limited List Printing + */ + private String limitedToString(Collection publishers) { + Iterator it = publishers.iterator(); + if (!it.hasNext()) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + int i = 1; + for (;;) { + Publisher e = it.next(); + sb.append("Publisher{dataInfoId='").append(e.getDataInfoId()).append('\''); + sb.append(", cell='").append(e.getCell()).append('\''); + sb.append(", registerId='").append(e.getRegisterId()).append('\''); + sb.append(", version=").append(e.getVersion()); + sb.append(", sourceAddress=").append(e.getSourceAddress()); + sb.append(", registerTimestamp=").append(e.getRegisterTimestamp()); + sb.append(", clientRegisterTimestamp=").append(e.getClientRegisterTimestamp()); + sb.append('}'); + if (!it.hasNext() || i++ >= LIMITED_LIST_SIZE_FOR_PRINT) + return sb.append(']').toString(); + sb.append(',').append(' '); + } + } + + private List subtract(Map pubMap1, Map pubMap2) { + List list = new ArrayList(); + for (Map.Entry entry : pubMap1.entrySet()) { + String registerId = entry.getKey(); + Publisher publisher1 = entry.getValue(); + Publisher publisher2 = pubMap2.get(registerId); + if (publisher2 == null + || PublisherDigestUtil.getDigestValue(publisher1) != PublisherDigestUtil + .getDigestValue(publisher2)) { + list.add(publisher1); + } + } + return list; + } + + @Override + public CommonResponse buildFailedResponse(String msg) { + return CommonResponse.buildFailedResponse(msg); + } + + @Override + public HandlerType getType() { + return HandlerType.PROCESSER; + } + + @Override + public Class interest() { + return DatumSnapshotRequest.class; + } + + @Override + protected Node.NodeType getConnectNodeType() { + return Node.NodeType.DATA; + } +} diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataHandler.java index 76682983e..f2c9a9c7f 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataHandler.java @@ -16,6 +16,12 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.GenericResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -23,20 +29,10 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.Channel; -import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.forward.ForwardService; -import com.alipay.sofa.registry.server.data.util.ThreadPoolExecutorDataServer; -import com.alipay.sofa.registry.util.NamedThreadFactory; import com.alipay.sofa.registry.util.ParaCheckUtil; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; /** * processor to get specific data @@ -48,14 +44,21 @@ public class GetDataHandler extends AbstractServerHandler { /** LOGGER */ private static final Logger LOGGER = LoggerFactory.getLogger(GetDataHandler.class); + @Autowired private ForwardService forwardService; @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DatumCache datumCache; + @Autowired private ThreadPoolExecutor getDataProcessorExecutor; + @Override + public Executor getExecutor() { + return getDataProcessorExecutor; + } + @Override public void checkParam(GetDataRequest request) throws RuntimeException { ParaCheckUtil.checkNotBlank(request.getDataInfoId(), "GetDataRequest.dataInfoId"); @@ -64,7 +67,7 @@ public void checkParam(GetDataRequest request) throws RuntimeException { @Override public Object doHandle(Channel channel, GetDataRequest request) { String dataInfoId = request.getDataInfoId(); - if (forwardService.needForward(dataInfoId)) { + if (forwardService.needForward()) { try { LOGGER.warn("[forward] Get data request forward, request: {}", request); return forwardService.forwardRequest(dataInfoId, request); @@ -77,7 +80,7 @@ public Object doHandle(Channel channel, GetDataRequest request) { } } - return new GenericResponse>().fillSucceed(DatumCache + return new GenericResponse>().fillSucceed(datumCache .getDatumGroupByDataCenter(request.getDataCenter(), dataInfoId)); } @@ -101,16 +104,4 @@ protected Node.NodeType getConnectNodeType() { return Node.NodeType.DATA; } - @Override - public Executor getExecutor() { - if (getDataProcessorExecutor == null) { - getDataProcessorExecutor = new ThreadPoolExecutorDataServer("GetDataProcessorExecutor", - dataServerBootstrapConfig.getGetDataExecutorMinPoolSize(), - dataServerBootstrapConfig.getGetDataExecutorMaxPoolSize(), - dataServerBootstrapConfig.getGetDataExecutorKeepAliveTime(), TimeUnit.SECONDS, - new ArrayBlockingQueue<>(dataServerBootstrapConfig.getGetDataExecutorQueueSize()), - new NamedThreadFactory("DataServer-GetDataProcessor-executor", true)); - } - return getDataProcessorExecutor; - } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataVersionsHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataVersionsHandler.java index e2fa8e4e4..268425b14 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataVersionsHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/GetDataVersionsHandler.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.GenericResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -25,12 +35,6 @@ import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.util.ParaCheckUtil; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - /** * processor to get versions of specific dataInfoIds * @@ -38,6 +42,18 @@ * @version $Id: GetDataVersionsProcessor.java, v 0.1 2017-12-06 19:56 qian.lqlq Exp $ */ public class GetDataVersionsHandler extends AbstractServerHandler { + + @Autowired + private DatumCache datumCache; + + @Autowired + private ThreadPoolExecutor getDataProcessorExecutor; + + @Override + public Executor getExecutor() { + return getDataProcessorExecutor; + } + @Override protected void logRequest(Channel channel, GetDataVersionRequest request) { } @@ -52,7 +68,7 @@ public Object doHandle(Channel channel, GetDataVersionRequest request) { Map> map = new HashMap<>(); List dataInfoIds = request.getDataInfoIds(); for (String dataInfoId : dataInfoIds) { - Map datumMap = DatumCache.get(dataInfoId); + Map datumMap = datumCache.get(dataInfoId); Set> entrySet = datumMap.entrySet(); for (Entry entry : entrySet) { String dataCenter = entry.getKey(); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/PublishDataHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/PublishDataHandler.java index 94caad81e..ffbbaab46 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/PublishDataHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/PublishDataHandler.java @@ -16,6 +16,11 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.PublishType; @@ -29,15 +34,8 @@ import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.SessionServerConnectionFactory; import com.alipay.sofa.registry.server.data.remoting.sessionserver.forward.ForwardService; -import com.alipay.sofa.registry.server.data.util.ThreadPoolExecutorDataServer; -import com.alipay.sofa.registry.util.NamedThreadFactory; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; import com.alipay.sofa.registry.util.ParaCheckUtil; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; /** * processor to publish data @@ -63,17 +61,11 @@ public class PublishDataHandler extends AbstractServerHandler(dataServerConfig.getPublishExecutorQueueSize()), - new NamedThreadFactory("DataServer-PublishProcessorExecutor-executor", true)); - } + @Autowired + private ThreadPoolExecutor publishProcessorExecutor; @Override public void checkParam(PublishDataRequest request) throws RuntimeException { @@ -94,7 +86,7 @@ public void checkParam(PublishDataRequest request) throws RuntimeException { @Override public Object doHandle(Channel channel, PublishDataRequest request) { Publisher publisher = Publisher.processPublisher(request.getPublisher()); - if (forwardService.needForward(publisher.getDataInfoId())) { + if (forwardService.needForward()) { LOGGER.warn("[forward] Publish request refused, request: {}", request); CommonResponse response = new CommonResponse(); response.setSuccess(false); @@ -103,9 +95,13 @@ public Object doHandle(Channel channel, PublishDataRequest request) { } dataChangeEventCenter.onChange(publisher, dataServerConfig.getLocalDataCenter()); + if (publisher.getPublishType() != PublishType.TEMPORARY) { - sessionServerConnectionFactory.registerClient(request.getSessionServerProcessId(), - publisher.getSourceAddress().getAddressString()); + String connectId = publisher.getSourceAddress().getAddressString(); + sessionServerConnectionFactory.registerConnectId(request.getSessionServerProcessId(), + connectId); + // record the renew timestamp + datumLeaseManager.renew(connectId); } return CommonResponse.buildSuccessResponse(); @@ -133,6 +129,6 @@ protected Node.NodeType getConnectNodeType() { @Override public Executor getExecutor() { - return publishExecutor; + return publishProcessorExecutor; } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/RenewDatumHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/RenewDatumHandler.java new file mode 100644 index 000000000..3004b3bdd --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/RenewDatumHandler.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.remoting.sessionserver.handler; + +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.common.model.GenericResponse; +import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.PublisherDigestUtil; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.Channel; +import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.server.data.event.AfterWorkingProcess; +import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; +import com.alipay.sofa.registry.util.ParaCheckUtil; + +/** + * handling snapshot request + * + * @author kezhu.wukz + * @version $Id: RenewDatumHandler.java, v 0.1 2019-05-30 15:48 kezhu.wukz Exp $ + */ +public class RenewDatumHandler extends AbstractServerHandler implements + AfterWorkingProcess { + + /** LOGGER */ + private static final Logger LOGGER = LoggerFactory.getLogger(RenewDatumHandler.class); + + private static final Logger RENEW_LOGGER = LoggerFactory.getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[RenewDatumHandler]"); + + private final AtomicBoolean renewEnabled = new AtomicBoolean(false); + + @Autowired + private DatumLeaseManager datumLeaseManager; + + @Autowired + private DatumCache datumCache; + + @Autowired + private ThreadPoolExecutor renewDatumProcessorExecutor; + + @Autowired + private DataServerConfig dataServerConfig; + + @Override + public Executor getExecutor() { + return renewDatumProcessorExecutor; + } + + @Override + protected void logRequest(Channel channel, RenewDatumRequest request) { + } + + @Override + public void checkParam(RenewDatumRequest request) throws RuntimeException { + ParaCheckUtil.checkNotBlank(request.getConnectId(), "RenewDatumRequest.connectId"); + ParaCheckUtil.checkNotBlank(request.getDigestSum(), "RenewDatumRequest.digestSum"); + } + + @Override + public Object doHandle(Channel channel, RenewDatumRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doHandle: request={}", request); + } + + if (!renewEnabled.get()) { + LOGGER.warn("[forward] Renew request refused, renewEnabled is false, request: {}", + request); + GenericResponse response = new GenericResponse(); + response.setSuccess(false); + response.setMessage("Renew request refused, renewEnabled is false yet"); + return response; + } + + boolean theSame = renewDatum(request); + + return new GenericResponse().fillSucceed(theSame); + } + + @Override + public CommonResponse buildFailedResponse(String msg) { + return CommonResponse.buildFailedResponse(msg); + } + + @Override + public HandlerType getType() { + return HandlerType.PROCESSER; + } + + @Override + public Class interest() { + return RenewDatumRequest.class; + } + + @Override + protected Node.NodeType getConnectNodeType() { + return Node.NodeType.DATA; + } + + /** + * 1. Update the timestamp corresponding to connectId in datumCache + * 2. Compare checksum: Get all pubs corresponding to the connId from datumCache and calculate checksum. + */ + private boolean renewDatum(RenewDatumRequest request) { + String connectId = request.getConnectId(); + String renewDigest = request.getDigestSum(); + + // Get all pubs corresponding to the connectId from datumCache + Map publisherMap = datumCache.getOwnByConnectId(connectId); + String cacheDigest = null; + if (publisherMap != null && publisherMap.values().size() > 0) { + cacheDigest = String.valueOf(PublisherDigestUtil.getDigestValueSum(publisherMap + .values())); + } + + // record the renew timestamp + datumLeaseManager.renew(connectId); + + boolean result = StringUtils.equals(renewDigest, cacheDigest); + + if (!result) { + RENEW_LOGGER.info("Digest different! renewDatumRequest={}", request); + } + return result; + } + + @Override + public void afterWorkingProcess() { + /* + * After the snapshot data is synchronized during startup, it is queued and then placed asynchronously into + * DatumCache. When the notification becomes WORKING, there may be data in the queue that is not executed + * to DatumCache. So it need to sleep for a while. + */ + try { + TimeUnit.MILLISECONDS.sleep(dataServerConfig.getRenewEnableDelaySec()); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage(), e); + } + renewEnabled.set(true); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/SessionServerRegisterHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/SessionServerRegisterHandler.java index a136fa06f..d4ff45166 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/SessionServerRegisterHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/SessionServerRegisterHandler.java @@ -16,6 +16,11 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.dataserver.SessionServerRegisterRequest; @@ -24,10 +29,6 @@ import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.SessionServerConnectionFactory; import com.alipay.sofa.registry.util.ParaCheckUtil; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.HashSet; -import java.util.Set; /** * @@ -47,11 +48,11 @@ public void checkParam(SessionServerRegisterRequest request) throws RuntimeExcep @Override public Object doHandle(Channel channel, SessionServerRegisterRequest request) { - Set clientHosts = request.getClientHosts(); - if (clientHosts == null) { - clientHosts = new HashSet<>(); + Set connectIds = request.getConnectIds(); + if (connectIds == null) { + connectIds = new HashSet<>(); } - sessionServerConnectionFactory.register(request.getProcessId(), clientHosts, + sessionServerConnectionFactory.register(request.getProcessId(), connectIds, ((BoltChannel) channel).getConnection()); return CommonResponse.buildSuccessResponse(); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/UnPublishDataHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/UnPublishDataHandler.java index 2a297ed6b..42e335664 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/UnPublishDataHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/remoting/sessionserver/handler/UnPublishDataHandler.java @@ -16,19 +16,28 @@ */ package com.alipay.sofa.registry.server.data.remoting.sessionserver.handler; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.UnPublishDataRequest; +import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.data.cache.UnPublisher; import com.alipay.sofa.registry.server.data.change.event.DataChangeEventCenter; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.data.remoting.sessionserver.forward.ForwardService; +import com.alipay.sofa.registry.server.data.renew.DatumLeaseManager; import com.alipay.sofa.registry.util.ParaCheckUtil; -import org.springframework.beans.factory.annotation.Autowired; /** * processor to unPublish specific data @@ -50,6 +59,20 @@ public class UnPublishDataHandler extends AbstractServerHandler pubMap = datum.getPubMap(); + if (pubMap != null) { + Publisher publisher = pubMap.get(request.getRegisterId()); + if (publisher != null) { + return publisher.getSourceAddress().getAddressString(); + } + } + } + return null; + } + @Override public CommonResponse buildFailedResponse(String msg) { return CommonResponse.buildFailedResponse(msg); diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/DatumLeaseManager.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/DatumLeaseManager.java new file mode 100644 index 000000000..b42069686 --- /dev/null +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/DatumLeaseManager.java @@ -0,0 +1,316 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.data.renew; + +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang.time.DateFormatUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.server.data.event.AfterWorkingProcess; +import com.alipay.sofa.registry.server.data.node.DataNodeStatus; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.ClientDisconnectEvent; +import com.alipay.sofa.registry.server.data.remoting.sessionserver.disconnect.DisconnectEventHandler; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +/** + * + * @author kezhu.wukz + * @version $Id: DatumExpiredCleaner.java, v 0.1 2019-06-03 21:08 kezhu.wukz Exp $ + */ +public class DatumLeaseManager implements AfterWorkingProcess { + private static final Logger LOGGER = LoggerFactory + .getLogger(DatumLeaseManager.class); + private static final TimeZone TIME_ZONE = TimeZone + .getTimeZone("Asia/Shanghai"); + private static final Logger RENEW_LOGGER = LoggerFactory + .getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[DatumLeaseManager]"); + + /** record the latest heartbeat time for each connectId, format: connectId -> lastRenewTimestamp */ + private final Map connectIdRenewTimestampMap = new ConcurrentHashMap<>(); + + /** lock for connectId , format: connectId -> true */ + private ConcurrentHashMap locksForConnectId = new ConcurrentHashMap(); + + private volatile boolean serverWorking = false; + + private volatile boolean renewEnable = true; + + private AsyncHashedWheelTimer datumAsyncHashedWheelTimer; + + @Autowired + private DataServerConfig dataServerConfig; + + @Autowired + private DisconnectEventHandler disconnectEventHandler; + + @Autowired + private DatumCache datumCache; + + @Autowired + private DataNodeStatus dataNodeStatus; + + private ScheduledThreadPoolExecutor executorForHeartbeatLess; + + private ScheduledFuture futureForHeartbeatLess; + + /** + * constructor + */ + @PostConstruct + public void init() { + ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); + threadFactoryBuilder.setDaemon(true); + datumAsyncHashedWheelTimer = new AsyncHashedWheelTimer(threadFactoryBuilder.setNameFormat( + "Registry-DatumLeaseManager-WheelTimer").build(), 100, TimeUnit.MILLISECONDS, 1024, + dataServerConfig.getDatumLeaseManagerExecutorThreadSize(), + dataServerConfig.getDatumLeaseManagerExecutorQueueSize(), threadFactoryBuilder + .setNameFormat("Registry-DatumLeaseManager-WheelExecutor-%d").build(), + new TaskFailedCallback() { + @Override + public void executionRejected(Throwable e) { + LOGGER.error("executionRejected: " + e.getMessage(), e); + } + + @Override + public void executionFailed(Throwable e) { + LOGGER.error("executionFailed: " + e.getMessage(), e); + } + }); + + executorForHeartbeatLess = new ScheduledThreadPoolExecutor(1, threadFactoryBuilder + .setNameFormat("Registry-DatumLeaseManager-ExecutorForHeartbeatLess").build()); + scheduleEvictTaskForHeartbeatLess(); + } + + /** + * reset EvictTaskForHeartbeatLess + */ + public synchronized void reset() { + LOGGER.info("reset is called, EvictTaskForHeartbeatLess will delay {}s", + dataServerConfig.getDatumTimeToLiveSec()); + if (futureForHeartbeatLess != null) { + futureForHeartbeatLess.cancel(false); + } + scheduleEvictTaskForHeartbeatLess(); + } + + private void scheduleEvictTaskForHeartbeatLess() { + futureForHeartbeatLess = executorForHeartbeatLess.scheduleWithFixedDelay( + new EvictTaskForHeartbeatLess(), dataServerConfig.getDatumTimeToLiveSec(), + dataServerConfig.getDatumTimeToLiveSec(), TimeUnit.SECONDS); + } + + /** + * record the renew timestamp + */ + public void renew(String connectId) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("renew: connectId={}", connectId); + } + + // record the renew timestamp + connectIdRenewTimestampMap.put(connectId, System.currentTimeMillis()); + // try to trigger evict task + scheduleEvictTask(connectId, 0); + } + + /** + * remove connectId if clientOff + */ + public void remove(String connectId) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("remove: connectId={}", connectId); + } + + Long removed = connectIdRenewTimestampMap.remove(connectId); + if (removed != null) { + LOGGER.info("remove connectId({}) because it is clientOff", connectId); + } + } + + /** + * trigger evict task: if connectId expired, create ClientDisconnectEvent to cleanup datums bind to the connectId + * PS: every connectId allows only one task to be created + */ + private void scheduleEvictTask(String connectId, long delaySec) { + delaySec = (delaySec <= 0) ? dataServerConfig.getDatumTimeToLiveSec() : delaySec; + + // lock for connectId: every connectId allows only one task to be created + Boolean ifAbsent = locksForConnectId.putIfAbsent(connectId, true); + if (ifAbsent != null) { + return; + } + + datumAsyncHashedWheelTimer.newTimeout(_timeout -> { + boolean continued = true; + long nextDelaySec = 0; + try { + // release lock + locksForConnectId.remove(connectId); + + // get lastRenewTime of this connectId + Long lastRenewTime = connectIdRenewTimestampMap.get(connectId); + if (lastRenewTime == null) { + // connectId is already clientOff + LOGGER.info("EvictTask(connectId={}) stop because already disconnected", connectId); + return; + } + + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("EvictTask: connectId={}, lastRenewTime={}", connectId, format(lastRenewTime)); + } + + /* + * 1. lastRenewTime expires, then: + * - build ClientOffEvent and hand it to DataChangeEventCenter. + * - It will not be scheduled next time, so terminated. + * 2. lastRenewTime not expires, then: + * - trigger the next schedule + */ + boolean isExpired = + System.currentTimeMillis() - lastRenewTime > dataServerConfig.getDatumTimeToLiveSec() * 1000L; + if (!isRenewEnable()) { + LOGGER.info( + "scheduleEvictTask({}) skipped because isRenewEnable() is false, lastRenewTime is {}, DataNodeStatus is {}, will retry after {}s", + connectId, format(lastRenewTime), dataNodeStatus.getStatus(), + dataServerConfig.getDatumTimeToLiveSec()); + nextDelaySec = dataServerConfig.getDatumTimeToLiveSec(); + } else if (isExpired) { + int ownPubSize = getOwnPubSize(connectId); + if (ownPubSize > 0) { + LOGGER.info("Evict connectId({}) because expired, lastRenewTime is {}, pub.size is {}", + connectId, format(lastRenewTime), ownPubSize); + evict(connectId); + } + connectIdRenewTimestampMap.remove(connectId, lastRenewTime); + continued = false; + } else { + nextDelaySec = dataServerConfig.getDatumTimeToLiveSec() + - (System.currentTimeMillis() - lastRenewTime) / 1000L; + nextDelaySec = nextDelaySec <= 0 ? 1 : nextDelaySec; + } + + } catch (Exception e) { + LOGGER.error("Error in task of datumAsyncHashedWheelTimer", e); + } + if (continued) { + scheduleEvictTask(connectId, nextDelaySec); + } + }, delaySec, TimeUnit.SECONDS); + + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("scheduleEvictTask: connectId={}, delaySec={}", connectId, delaySec); + } + + } + + private int getOwnPubSize(String connectId) { + Map ownPubs = datumCache.getOwnByConnectId(connectId); + return ownPubs != null ? ownPubs.size() : 0; + } + + private void evict(String connectId) { + disconnectEventHandler.receive(new ClientDisconnectEvent(connectId, System + .currentTimeMillis(), 0)); + } + + private String format(long lastRenewTime) { + return DateFormatUtils.format(lastRenewTime, "yyyy-MM-dd HH:mm:ss", TIME_ZONE); + } + + @Override + public void afterWorkingProcess() { + /* + * After the snapshot data is synchronized during startup, it is queued and then placed asynchronously into + * DatumCache. When the notification becomes WORKING, there may be data in the queue that is not executed + * to DatumCache. So it need to sleep for a while. + */ + try { + TimeUnit.MILLISECONDS.sleep(dataServerConfig.getRenewEnableDelaySec()); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage(), e); + } + serverWorking = true; + } + + @Override + public int getOrder() { + return 0; + } + + /** + * evict own connectIds with heartbeat less + */ + private class EvictTaskForHeartbeatLess implements Runnable { + + @Override + public void run() { + // If in a non-working state, cannot clean up because the renew request cannot be received at this time. + if (!isRenewEnable()) { + LOGGER + .info( + "EvictTaskForHeartbeatLess skipped because isRenewEnable() is false, DataNodeStatus is {}, will retry after {}s", + dataNodeStatus.getStatus(), dataServerConfig.getDatumTimeToLiveSec()); + return; + } + + Set allConnectIds = datumCache.getAllConnectIds(); + for (String connectId : allConnectIds) { + Long timestamp = connectIdRenewTimestampMap.get(connectId); + // no heartbeat + if (timestamp == null) { + int ownPubSize = getOwnPubSize(connectId); + if (ownPubSize > 0) { + LOGGER.info("Evict connectId({}) because no heartbeat, pub.size is {}", + connectId, ownPubSize); + evict(connectId); + } + } + } + + LOGGER.info("connectIdRenewTimestampMap.size is {}", connectIdRenewTimestampMap.size()); + } + } + + public void setRenewEnable(boolean renewEnable) { + this.renewEnable = renewEnable; + } + + private boolean isRenewEnable() { + return renewEnable && serverWorking; + } + +} \ No newline at end of file diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/correction/LocalDataServerCleanHandler.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/LocalDataServerCleanHandler.java similarity index 92% rename from server/server/data/src/main/java/com/alipay/sofa/registry/server/data/correction/LocalDataServerCleanHandler.java rename to server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/LocalDataServerCleanHandler.java index fe498dbae..b6aa61547 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/correction/LocalDataServerCleanHandler.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/renew/LocalDataServerCleanHandler.java @@ -14,7 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alipay.sofa.registry.server.data.correction; +package com.alipay.sofa.registry.server.data.renew; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.springframework.beans.factory.annotation.Autowired; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.metaserver.DataNode; @@ -29,13 +37,6 @@ import com.alipay.sofa.registry.server.data.change.event.DataChangeEventCenter; import com.alipay.sofa.registry.server.data.executor.ExecutorFactory; import com.alipay.sofa.registry.server.data.util.DelayItem; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; /** * @@ -51,7 +52,7 @@ public class LocalDataServerCleanHandler { .getLogger("DATA-START-LOGS"); @Autowired - private DataServerConfig dataServerBootstrapConfig; + private DataServerConfig dataServerConfig; @Autowired private DataServerCache dataServerCache; @@ -59,6 +60,9 @@ public class LocalDataServerCleanHandler { @Autowired private DataChangeEventCenter dataChangeEventCenter; + @Autowired + private DatumCache datumCache; + private LocalCleanTask task; /** @@ -70,8 +74,7 @@ public class LocalDataServerCleanHandler { * constructor */ public LocalDataServerCleanHandler() { - Executor executor = ExecutorFactory - .newSingleThreadExecutor(LocalDataServerCleanHandler.class.getSimpleName()); + Executor executor = ExecutorFactory.newSingleThreadExecutor(LocalDataServerCleanHandler.class.getSimpleName()); executor.execute(() -> { while (true) { try { @@ -96,7 +99,7 @@ public void reset() { EVENT_QUEUE.clear(); } } - EVENT_QUEUE.add(new DelayItem<>(new LocalCleanTask(), dataServerBootstrapConfig + EVENT_QUEUE.add(new DelayItem<>(new LocalCleanTask(), dataServerConfig .getLocalDataServerCleanDelay())); } @@ -112,16 +115,16 @@ public void run() { try { Map dataNodeMap = dataServerCache - .getDataServers(dataServerBootstrapConfig.getLocalDataCenter()); + .getDataServers(dataServerConfig.getLocalDataCenter()); if (dataNodeMap == null || dataNodeMap.isEmpty()) { LOGGER.warn("Calculate Old BackupTriad,old dataServer list is empty!"); return; } ConsistentHash consistentHash = new ConsistentHash<>( - dataServerBootstrapConfig.getNumberOfReplicas(), dataNodeMap.values()); + dataServerConfig.getNumberOfReplicas(), dataNodeMap.values()); - Map> dataMapAll = DatumCache.getAll(); + Map> dataMapAll = datumCache.getAll(); for (Entry> entryAll : dataMapAll.entrySet()) { String dataCenter = entryAll.getKey(); @@ -139,7 +142,7 @@ public void run() { BackupTriad backupTriad = new BackupTriad(dataInfoId, consistentHash.getNUniqueNodesFor(dataInfoId, - dataServerBootstrapConfig.getStoreNodes())); + dataServerConfig.getStoreNodes())); if (!backupTriad.containsSelf()) { if (datum != null) { int size = datum.getPubMap() != null ? datum.getPubMap().size() @@ -156,7 +159,7 @@ public void run() { } catch (Throwable e) { LOGGER.error("[LocalDataServerCleanHandler] clean local datum task error!", e); } finally { - EVENT_QUEUE.add(new DelayItem<>(new LocalCleanTask(), dataServerBootstrapConfig + EVENT_QUEUE.add(new DelayItem<>(new LocalCleanTask(), dataServerConfig .getLocalDataServerCleanDelay())); } } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/DataDigestResource.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/DataDigestResource.java index d61ea6da3..de514156e 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/DataDigestResource.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/DataDigestResource.java @@ -16,6 +16,25 @@ */ package com.alipay.sofa.registry.server.data.resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.remoting.Connection; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.store.DataInfo; @@ -27,23 +46,6 @@ import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerNodeFactory; import com.alipay.sofa.registry.server.data.remoting.metaserver.MetaServerConnectionFactory; import com.alipay.sofa.registry.server.data.remoting.sessionserver.SessionServerConnectionFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.stream.Collectors; /** * @@ -68,6 +70,9 @@ public class DataDigestResource { @Autowired private DataServerConfig dataServerConfig; + @Autowired + private DatumCache datumCache; + @GET @Path("datum/query") @Produces(MediaType.APPLICATION_JSON) @@ -81,9 +86,9 @@ public Map getDatumByDataInfoId(@QueryParam("dataId") String data String dataInfoId = DataInfo.toDataInfoId(dataId, instanceId, group); if (isBlank(dataCenter)) { - retList = DatumCache.get(dataInfoId); + retList = datumCache.get(dataInfoId); } else { - retList.put(dataCenter, DatumCache.get(dataCenter, dataInfoId)); + retList.put(dataCenter, datumCache.get(dataCenter, dataInfoId)); } } @@ -99,7 +104,7 @@ public Map> getPublishersByConnectId(Map { String connectId = NetUtil.genHost(ip, Integer.valueOf(port)); if (!connectId.isEmpty()) { - Map publisherMap = DatumCache.getByHost(connectId); + Map publisherMap = datumCache.getByConnectId(connectId); if (publisherMap != null && !publisherMap.isEmpty()) { ret.put(connectId, publisherMap); } @@ -116,17 +121,15 @@ public String getDatumCount() { StringBuilder sb = new StringBuilder("CacheDigest"); try { - Map> allMap = DatumCache.getAll(); + Map> allMap = datumCache.getAll(); if (!allMap.isEmpty()) { for (Entry> dataCenterEntry : allMap.entrySet()) { String dataCenter = dataCenterEntry.getKey(); Map datumMap = dataCenterEntry.getValue(); - sb.append(String.format(" [Datum] size of datum in %s is %s", - dataCenter, datumMap.size())); + sb.append(String.format(" [Datum] size of datum in %s is %s", dataCenter, datumMap.size())); int pubCount = datumMap.values().stream().map(Datum::getPubMap) .filter(map -> map != null && !map.isEmpty()).mapToInt(Map::size).sum(); - sb.append(String.format(",[Publisher] size of publisher in %s is %s", - dataCenter, pubCount)); + sb.append(String.format(",[Publisher] size of publisher in %s is %s", dataCenter, pubCount)); } } else { sb.append(" datum cache is empty"); @@ -172,24 +175,25 @@ public Map> getServerListAll(@PathParam("type") String type } public List getSessionServerList() { - List connections = sessionServerConnectionFactory.getConnections().stream().filter(connection -> connection != null && connection.isFine()) + List connections = sessionServerConnectionFactory.getConnections().stream() + .filter(connection -> connection != null && connection.isFine()) .map(connection -> connection.getRemoteIP() + ":" + connection.getRemotePort()) .collect(Collectors.toList()); return connections; } - public Map> getDataServerList() { + public Map> getDataServerList() { - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); Set allDataCenter = new HashSet<>(DataServerNodeFactory.getAllDataCenters()); - for (String dataCenter:allDataCenter) { + for (String dataCenter : allDataCenter) { - List list = map.computeIfAbsent(dataCenter,k->new ArrayList<>()); + List list = map.computeIfAbsent(dataCenter, k -> new ArrayList<>()); Map dataNodes = DataServerNodeFactory.getDataServerNodes(dataCenter); - if(dataNodes != null && !dataNodes.isEmpty()){ + if (dataNodes != null && !dataNodes.isEmpty()) { - dataNodes.forEach((ip,dataServerNode)->{ + dataNodes.forEach((ip, dataServerNode) -> { if (ip != null && !ip.equals(DataServerConfig.IP)) { Connection connection = dataServerNode.getConnection(); if (connection != null && connection.isFine()) { @@ -202,18 +206,18 @@ public Map> getDataServerList() { return map; } - public Map> getMetaServerList() { + public Map> getMetaServerList() { - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); Set allDataCenter = new HashSet<>(metaServerConnectionFactory.getAllDataCenters()); - for (String dataCenter:allDataCenter) { + for (String dataCenter : allDataCenter) { - List list = map.computeIfAbsent(dataCenter,k->new ArrayList<>()); + List list = map.computeIfAbsent(dataCenter, k -> new ArrayList<>()); Map metaConnections = metaServerConnectionFactory.getConnections(dataCenter); - if(metaConnections != null && !metaConnections.isEmpty()){ + if (metaConnections != null && !metaConnections.isEmpty()) { - metaConnections.forEach((ip,connection)->{ + metaConnections.forEach((ip, connection) -> { if (connection != null && connection.isFine()) { list.add(connection.getRemoteIP()); } diff --git a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/HealthResource.java b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/HealthResource.java index c61a8bcf8..99e867c8a 100644 --- a/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/HealthResource.java +++ b/server/server/data/src/main/java/com/alipay/sofa/registry/server/data/resource/HealthResource.java @@ -16,16 +16,24 @@ */ package com.alipay.sofa.registry.server.data.resource; -import com.alipay.sofa.registry.common.model.CommonResponse; -import com.alipay.sofa.registry.server.data.bootstrap.DataServerBootstrap; -import com.alipay.sofa.registry.server.data.node.DataNodeStatus; -import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; -import org.springframework.beans.factory.annotation.Autowired; - +import javax.annotation.PostConstruct; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.metrics.ReporterUtils; +import com.alipay.sofa.registry.server.data.bootstrap.DataServerBootstrap; +import com.alipay.sofa.registry.server.data.node.DataNodeStatus; +import com.alipay.sofa.registry.server.data.util.LocalServerStatusEnum; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.MetricRegistry; /** * @@ -41,11 +49,29 @@ public class HealthResource { @Autowired private DataNodeStatus dataNodeStatus; + @PostConstruct + public void init() { + MetricRegistry metrics = new MetricRegistry(); + metrics.register("healthCheck", (Gauge) () -> getHealthCheckResult()); + ReporterUtils.startSlf4jReporter(60, metrics); + } + @GET @Path("check") @Produces(MediaType.APPLICATION_JSON) - public CommonResponse checkHealth() { + public Response checkHealth() { + + ResponseBuilder builder = Response.status(Response.Status.OK); + CommonResponse response = getHealthCheckResult(); + builder.entity(response); + if (!response.isSuccess()) { + builder.status(Status.INTERNAL_SERVER_ERROR); + } + + return builder.build(); + } + private CommonResponse getHealthCheckResult() { CommonResponse response; StringBuilder sb = new StringBuilder("DataServerBoot "); @@ -76,6 +102,11 @@ public CommonResponse checkHealth() { response = CommonResponse.buildFailedResponse(sb.toString()); } + if (ret) { + response = CommonResponse.buildSuccessResponse(sb.toString()); + } else { + response = CommonResponse.buildFailedResponse(sb.toString()); + } return response; } } \ No newline at end of file diff --git a/server/server/data/src/main/resources/application.properties b/server/server/data/src/main/resources/application.properties index d172a1405..a65d7295f 100644 --- a/server/server/data/src/main/resources/application.properties +++ b/server/server/data/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.main.banner-mode=LOG -#nodes.metaNode=: -#nodes.localDataCenter= +nodes.metaNode=DefaultDataCenter:localhost +nodes.localDataCenter=DefaultDataCenter #data.server.logging.level=INFO #data.server.logging.home=/home/admin/logs/registry/data @@ -16,4 +16,5 @@ data.server.rpcTimeout=3000 data.server.metaServerPort=9611 data.server.storeNodes=3 data.server.numberOfReplicas=1000 +data.server.datumTimeToLiveSec=900 diff --git a/server/server/data/src/main/resources/logback-spring.xml b/server/server/data/src/main/resources/logback-spring.xml index f64cde75d..bc99d0067 100644 --- a/server/server/data/src/main/resources/logback-spring.xml +++ b/server/server/data/src/main/resources/logback-spring.xml @@ -71,6 +71,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${DATA_LOG_HOME}/registry-renew.log + + ${DATA_LOG_HOME}/registry-renew.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -213,6 +233,46 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${DATA_LOG_HOME}/registry-metrics.log + + ${DATA_LOG_HOME}/registry-metrics.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${DATA_LOG_HOME}/registry-datum-lease.log + + ${DATA_LOG_HOME}/registry-datum-lease.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -225,6 +285,11 @@ + + + + + @@ -281,6 +346,17 @@ + + + + + + + + + + + diff --git a/server/server/data/src/main/resources/security/blacklist.txt b/server/server/data/src/main/resources/security/blacklist.txt new file mode 100644 index 000000000..e3413f8d4 --- /dev/null +++ b/server/server/data/src/main/resources/security/blacklist.txt @@ -0,0 +1,78 @@ +org.codehaus.groovy.runtime.MethodClosure +clojure.core$constantly +clojure.main$eval_opt +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactory +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactoryImpl +com.alibaba.citrus.springext.util.SpringExtUtil.AbstractProxy +com.alipay.custrelation.service.model.redress.Pair +com.caucho.hessian.test.TestCons +com.mchange.v2.c3p0.JndiRefForwardingDataSource +com.mchange.v2.c3p0.WrapperConnectionPoolDataSource +com.rometools.rome.feed.impl.EqualsBean +com.rometools.rome.feed.impl.ToStringBean +com.sun.jndi.rmi.registry.BindingEnumeration +com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl +com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl +com.sun.rowset.JdbcRowSetImpl +com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data +java.rmi.server.UnicastRemoteObject +java.security.SignedObject +java.util.ServiceLoader$LazyIterator +javax.imageio.ImageIO$ContainsFilter +javax.imageio.spi.ServiceRegistry +javax.management.BadAttributeValueExpException +javax.naming.InitialContext +javax.naming.spi.ObjectFactory +javax.script.ScriptEngineManager +javax.sound.sampled.AudioFormat$Encoding +org.apache.carbondata.core.scan.expression.ExpressionResult +org.apache.commons.dbcp +org.apache.commons.dbcp2 +org.apache.commons.beanutils +org.apache.ibatis.executor.loader.AbstractSerialStateHolder +org.apache.ibatis.executor.loader.CglibSerialStateHolder +org.apache.ibatis.executor.loader.JavassistSerialStateHolder +org.apache.ibatis.executor.loader.cglib.CglibProxyFactory +org.apache.ibatis.executor.loader.javassist.JavassistSerialStateHolder +org.apache.tomcat.dbcp.dbcp.datasources.SharedPoolDataSource +org.apache.wicket.util.upload.DiskFileItem +org.apache.xalan.xsltc.trax.TemplatesImpl +org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding +org.apache.xpath.XPathContext +org.eclipse.jetty.util.log.LoggerLog +org.geotools.filter.ConstantExpression +org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder +org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor +org.springframework.beans.factory.BeanFactory +org.springframework.beans.factory.config.PropertyPathFactoryBean +org.springframework.beans.factory.support.DefaultListableBeanFactory +org.springframework.jndi.support.SimpleJndiBeanFactory +org.springframework.orm.jpa.AbstractEntityManagerFactoryBean +org.springframework.transaction.jta.JtaTransactionManager +org.yaml.snakeyaml.tokens.DirectiveToken +sun.rmi.server.UnicastRef +javax.management.ImmutableDescriptor +org.springframework.jndi.JndiObjectTargetSource +ch.qos.logback.core.db.JNDIConnectionSource +java.beans.Expression +javassist.bytecode +javassist.tools.web.Viewer +javassist.util.proxy.SerializedProxy +org.apache.ibatis.javassist.bytecode +org.apache.ibatis.javassist.tools.web.Viewer +org.apache.ibatis.javassist.util.proxy.SerializedProxy +org.springframework.beans.factory.config.MethodInvokingFactoryBean +com.alibaba.druid +com.sun.corba +com.sun.org.apache.bcel +com.sun.org.apache.xml +com.sun.org.apache.xpath +org.apache.zookeeper.Shell +org.apache.tomcat.dbcp.dbcp.BasicDataSource +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +org.jboss.resteasy.plugins +org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler +org.apache.velocity.runtime.resource.Resource +org.springframework.expression.spel.ast.Indexer$PropertyIndexingValueRef +org.mortbay.log.Slf4jLog +org.springframework.expression.spel.ast.MethodReference$MethodValueRef \ No newline at end of file diff --git a/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/BackupTriadTest.java b/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/BackupTriadTest.java index 3f5e7985d..f601b07f0 100644 --- a/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/BackupTriadTest.java +++ b/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/BackupTriadTest.java @@ -16,20 +16,21 @@ */ package com.alipay.sofa.registry.server.data; -import com.alipay.sofa.registry.common.model.metaserver.DataNode; -import com.alipay.sofa.registry.common.model.store.URL; -import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; -import com.alipay.sofa.registry.server.data.cache.BackupTriad; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; + +import com.alipay.sofa.registry.common.model.metaserver.DataNode; +import com.alipay.sofa.registry.common.model.store.URL; +import com.alipay.sofa.registry.server.data.bootstrap.DataServerConfig; +import com.alipay.sofa.registry.server.data.cache.BackupTriad; /** * @author xuanbei diff --git a/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/TestSyncData.java b/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/TestSyncData.java index d1cf8ebad..26044eeed 100644 --- a/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/TestSyncData.java +++ b/server/server/data/src/test/java/com/alipay/sofa/registry/server/data/TestSyncData.java @@ -16,15 +16,18 @@ */ package com.alipay.sofa.registry.server.data; -import com.alipay.sofa.registry.common.model.dataserver.Datum; -import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; -import com.alipay.sofa.registry.server.data.datasync.Operator; -import com.alipay.sofa.registry.server.data.datasync.sync.Acceptor; +import java.util.Collection; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.util.Collection; +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.server.data.change.DataSourceTypeEnum; +import com.alipay.sofa.registry.server.data.datasync.Operator; +import com.alipay.sofa.registry.server.data.datasync.sync.Acceptor; +import com.alipay.sofa.registry.util.DatumVersionUtil; /** * @@ -75,15 +78,15 @@ public void setup() { @Test public void testAcceptExpired() throws InterruptedException { - Acceptor acceptor = new Acceptor(30, "11", "DefaultDataCenter"); + Acceptor acceptor = new Acceptor(30, "11", "DefaultDataCenter", new DatumCache()); - Operator operator1 = new Operator(System.currentTimeMillis(), 0L, datum1, + Operator operator1 = new Operator(DatumVersionUtil.nextId(), 0L, datum1, DataSourceTypeEnum.SYNC); Thread.sleep(1000); - Operator operator2 = new Operator(System.currentTimeMillis(), operator1.getVersion(), + Operator operator2 = new Operator(DatumVersionUtil.nextId(), operator1.getVersion(), datum2, DataSourceTypeEnum.SYNC); Thread.sleep(2000); - Operator operator5 = new Operator(System.currentTimeMillis(), operator2.getVersion(), + Operator operator5 = new Operator(DatumVersionUtil.nextId(), operator2.getVersion(), datum5, DataSourceTypeEnum.SYNC); acceptor.appendOperator(operator1); @@ -100,4 +103,5 @@ public void testAcceptExpired() throws InterruptedException { Assert.assertTrue(ops[0].getVersion().equals(operator2.getVersion())); Assert.assertTrue(ops[1].getVersion().equals(operator5.getVersion())); } + } \ No newline at end of file diff --git a/server/server/integration/pom.xml b/server/server/integration/pom.xml index a53fa378f..fbe1f0316 100644 --- a/server/server/integration/pom.xml +++ b/server/server/integration/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/server/integration/src/main/resources/application.properties b/server/server/integration/src/main/resources/application.properties index 08a6b78f2..a99778c10 100644 --- a/server/server/integration/src/main/resources/application.properties +++ b/server/server/integration/src/main/resources/application.properties @@ -1,7 +1,7 @@ spring.main.banner-mode=LOG -#nodes.metaNode=: -#nodes.localDataCenter= -#nodes.localRegion= +nodes.metaNode=DefaultDataCenter:localhost +nodes.localDataCenter=DefaultDataCenter +nodes.localRegion=DEFAULT_ZONE #server.logging.home=/home/admin/logs/registry #meta.server.logging.level=INFO @@ -25,6 +25,7 @@ data.server.rpcTimeout=3000 data.server.metaServerPort=9611 data.server.storeNodes=3 data.server.numberOfReplicas=1000 +data.server.datumTimeToLiveSec=20 #session.server.logging.level=INFO #session.server.logging.home=/home/admin/logs/registry/session @@ -48,6 +49,7 @@ session.server.schedulerHeartbeatExpBackOffBound=10 session.server.schedulerFetchDataTimeout=3 session.server.schedulerFetchDataFirstDelay=3 session.server.schedulerFetchDataExpBackOffBound=10 +session.server.renewAndSnapshotSilentPeriodSec=20 #session.server.invalidForeverZones=; #session.server.invalidIgnoreDataidRegex= #session.server.pushEmptyDataDataIdPrefixes= \ No newline at end of file diff --git a/server/server/integration/src/main/resources/logback-spring.xml b/server/server/integration/src/main/resources/logback-spring.xml index 167ae8744..5b5142bb5 100644 --- a/server/server/integration/src/main/resources/logback-spring.xml +++ b/server/server/integration/src/main/resources/logback-spring.xml @@ -97,6 +97,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${LOG_HOME}/registry-renew.log + + ${LOG_HOME}/registry-renew.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -281,6 +301,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${DATA_LOG_HOME}/registry-datum-lease.log + + ${DATA_LOG_HOME}/registry-datum-lease.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -451,6 +491,11 @@ + + + + + @@ -496,6 +541,11 @@ + + + + + diff --git a/server/server/integration/src/main/resources/security/blacklist.txt b/server/server/integration/src/main/resources/security/blacklist.txt new file mode 100644 index 000000000..e3413f8d4 --- /dev/null +++ b/server/server/integration/src/main/resources/security/blacklist.txt @@ -0,0 +1,78 @@ +org.codehaus.groovy.runtime.MethodClosure +clojure.core$constantly +clojure.main$eval_opt +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactory +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactoryImpl +com.alibaba.citrus.springext.util.SpringExtUtil.AbstractProxy +com.alipay.custrelation.service.model.redress.Pair +com.caucho.hessian.test.TestCons +com.mchange.v2.c3p0.JndiRefForwardingDataSource +com.mchange.v2.c3p0.WrapperConnectionPoolDataSource +com.rometools.rome.feed.impl.EqualsBean +com.rometools.rome.feed.impl.ToStringBean +com.sun.jndi.rmi.registry.BindingEnumeration +com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl +com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl +com.sun.rowset.JdbcRowSetImpl +com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data +java.rmi.server.UnicastRemoteObject +java.security.SignedObject +java.util.ServiceLoader$LazyIterator +javax.imageio.ImageIO$ContainsFilter +javax.imageio.spi.ServiceRegistry +javax.management.BadAttributeValueExpException +javax.naming.InitialContext +javax.naming.spi.ObjectFactory +javax.script.ScriptEngineManager +javax.sound.sampled.AudioFormat$Encoding +org.apache.carbondata.core.scan.expression.ExpressionResult +org.apache.commons.dbcp +org.apache.commons.dbcp2 +org.apache.commons.beanutils +org.apache.ibatis.executor.loader.AbstractSerialStateHolder +org.apache.ibatis.executor.loader.CglibSerialStateHolder +org.apache.ibatis.executor.loader.JavassistSerialStateHolder +org.apache.ibatis.executor.loader.cglib.CglibProxyFactory +org.apache.ibatis.executor.loader.javassist.JavassistSerialStateHolder +org.apache.tomcat.dbcp.dbcp.datasources.SharedPoolDataSource +org.apache.wicket.util.upload.DiskFileItem +org.apache.xalan.xsltc.trax.TemplatesImpl +org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding +org.apache.xpath.XPathContext +org.eclipse.jetty.util.log.LoggerLog +org.geotools.filter.ConstantExpression +org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder +org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor +org.springframework.beans.factory.BeanFactory +org.springframework.beans.factory.config.PropertyPathFactoryBean +org.springframework.beans.factory.support.DefaultListableBeanFactory +org.springframework.jndi.support.SimpleJndiBeanFactory +org.springframework.orm.jpa.AbstractEntityManagerFactoryBean +org.springframework.transaction.jta.JtaTransactionManager +org.yaml.snakeyaml.tokens.DirectiveToken +sun.rmi.server.UnicastRef +javax.management.ImmutableDescriptor +org.springframework.jndi.JndiObjectTargetSource +ch.qos.logback.core.db.JNDIConnectionSource +java.beans.Expression +javassist.bytecode +javassist.tools.web.Viewer +javassist.util.proxy.SerializedProxy +org.apache.ibatis.javassist.bytecode +org.apache.ibatis.javassist.tools.web.Viewer +org.apache.ibatis.javassist.util.proxy.SerializedProxy +org.springframework.beans.factory.config.MethodInvokingFactoryBean +com.alibaba.druid +com.sun.corba +com.sun.org.apache.bcel +com.sun.org.apache.xml +com.sun.org.apache.xpath +org.apache.zookeeper.Shell +org.apache.tomcat.dbcp.dbcp.BasicDataSource +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +org.jboss.resteasy.plugins +org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler +org.apache.velocity.runtime.resource.Resource +org.springframework.expression.spel.ast.Indexer$PropertyIndexingValueRef +org.mortbay.log.Slf4jLog +org.springframework.expression.spel.ast.MethodReference$MethodValueRef \ No newline at end of file diff --git a/server/server/meta/pom.xml b/server/server/meta/pom.xml index 0d425bf3e..8bedc1a01 100644 --- a/server/server/meta/pom.xml +++ b/server/server/meta/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/AbstractNodeConfigBean.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/AbstractNodeConfigBean.java index 430e29b45..ddcb5e4b5 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/AbstractNodeConfigBean.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/AbstractNodeConfigBean.java @@ -16,10 +16,6 @@ */ package com.alipay.sofa.registry.server.meta.bootstrap; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; -import com.alipay.sofa.registry.net.NetUtil; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -29,6 +25,10 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.net.NetUtil; + /** * * @author shangyu.wh @@ -105,7 +105,6 @@ public String getMetaDataCenter(String metaIpAddress) { } }); - dataCenterRet = ret.get(); } return dataCenterRet; diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerBootstrap.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerBootstrap.java index 613b338cf..9e700c199 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerBootstrap.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerBootstrap.java @@ -16,6 +16,20 @@ */ package com.alipay.sofa.registry.server.meta.bootstrap; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.annotation.Resource; +import javax.ws.rs.Path; +import javax.ws.rs.ext.Provider; + +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; @@ -27,18 +41,6 @@ import com.alipay.sofa.registry.server.meta.remoting.RaftExchanger; import com.alipay.sofa.registry.server.meta.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.task.batcher.TaskDispatchers; -import org.glassfish.jersey.server.ResourceConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; - -import javax.annotation.Resource; -import javax.ws.rs.Path; -import javax.ws.rs.ext.Provider; -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; /** * @@ -99,8 +101,10 @@ public class MetaServerBootstrap { /** * Do initialized. */ - public void doInitialized() { + public void start() { try { + LOGGER.info("the configuration items are as follows: " + metaServerConfig.toString()); + openSessionRegisterServer(); openDataRegisterServer(); diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfigBean.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfigBean.java index bb484c923..68864e817 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfigBean.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfigBean.java @@ -16,10 +16,13 @@ */ package com.alipay.sofa.registry.server.meta.bootstrap; -import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import java.io.File; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.io.File; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; /** * @@ -599,4 +602,9 @@ public boolean isEnableMetrics() { public void setEnableMetrics(boolean enableMetrics) { this.enableMetrics = enableMetrics; } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } } \ No newline at end of file diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfiguration.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfiguration.java index 745881be0..e605d40c7 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfiguration.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerConfiguration.java @@ -16,6 +16,17 @@ */ package com.alipay.sofa.registry.server.meta.bootstrap; +import java.util.ArrayList; +import java.util.Collection; + +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + import com.alipay.sofa.registry.jraft.service.PersistenceDataDBService; import com.alipay.sofa.registry.remoting.bolt.exchange.BoltExchange; import com.alipay.sofa.registry.remoting.exchange.Exchange; @@ -45,7 +56,7 @@ import com.alipay.sofa.registry.server.meta.remoting.handler.FetchProvideDataRequestHandler; import com.alipay.sofa.registry.server.meta.remoting.handler.GetChangeListRequestHandler; import com.alipay.sofa.registry.server.meta.remoting.handler.GetNodesRequestHandler; -import com.alipay.sofa.registry.server.meta.remoting.handler.ReNewNodesRequestHandler; +import com.alipay.sofa.registry.server.meta.remoting.handler.RenewNodesRequestHandler; import com.alipay.sofa.registry.server.meta.remoting.handler.SessionNodeHandler; import com.alipay.sofa.registry.server.meta.repository.NodeConfirmStatusService; import com.alipay.sofa.registry.server.meta.repository.RepositoryService; @@ -57,11 +68,13 @@ import com.alipay.sofa.registry.server.meta.repository.service.SessionConfirmStatusService; import com.alipay.sofa.registry.server.meta.repository.service.SessionRepositoryService; import com.alipay.sofa.registry.server.meta.repository.service.SessionVersionRepositoryService; +import com.alipay.sofa.registry.server.meta.resource.BlacklistDataResource; import com.alipay.sofa.registry.server.meta.resource.DecisionModeResource; import com.alipay.sofa.registry.server.meta.resource.HealthResource; import com.alipay.sofa.registry.server.meta.resource.MetaDigestResource; import com.alipay.sofa.registry.server.meta.resource.MetaStoreResource; import com.alipay.sofa.registry.server.meta.resource.PersistentDataResource; +import com.alipay.sofa.registry.server.meta.resource.RenewSwitchResource; import com.alipay.sofa.registry.server.meta.resource.StopPushDataResource; import com.alipay.sofa.registry.server.meta.store.DataStoreService; import com.alipay.sofa.registry.server.meta.store.MetaStoreService; @@ -76,16 +89,6 @@ import com.alipay.sofa.registry.task.listener.TaskListener; import com.alipay.sofa.registry.task.listener.TaskListenerManager; import com.alipay.sofa.registry.util.PropertySplitter; -import org.glassfish.jersey.jackson.JacksonFeature; -import org.glassfish.jersey.server.ResourceConfig; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - -import java.util.ArrayList; -import java.util.Collection; /** * @@ -228,7 +231,7 @@ public Collection sessionServerHandlers() { Collection list = new ArrayList<>(); list.add(sessionConnectionHandler()); list.add(sessionNodeHandler()); - list.add(reNewNodesRequestHandler()); + list.add(renewNodesRequestHandler()); list.add(getNodesRequestHandler()); list.add(fetchProvideDataRequestHandler()); return list; @@ -240,7 +243,8 @@ public Collection dataServerHandlers() { list.add(dataConnectionHandler()); list.add(getNodesRequestHandler()); list.add(dataNodeHandler()); - list.add(reNewNodesRequestHandler()); + list.add(renewNodesRequestHandler()); + list.add(fetchProvideDataRequestHandler()); return list; } @@ -284,8 +288,8 @@ public AbstractServerHandler sessionNodeHandler() { } @Bean - public AbstractServerHandler reNewNodesRequestHandler() { - return new ReNewNodesRequestHandler(); + public AbstractServerHandler renewNodesRequestHandler() { + return new RenewNodesRequestHandler(); } @Bean @@ -358,6 +362,16 @@ public MetaStoreResource metaStoreResource() { public StopPushDataResource stopPushDataResource() { return new StopPushDataResource(); } + + @Bean + public BlacklistDataResource blacklistDataResource() { + return new BlacklistDataResource(); + } + + @Bean + public RenewSwitchResource renewSwitchResource() { + return new RenewSwitchResource(); + } } @Configuration diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerInitializerConfiguration.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerInitializerConfiguration.java index 1add54080..cca6532fc 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerInitializerConfiguration.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/bootstrap/MetaServerInitializerConfiguration.java @@ -16,12 +16,13 @@ */ package com.alipay.sofa.registry.server.meta.bootstrap; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; +import java.util.concurrent.atomic.AtomicBoolean; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.SmartLifecycle; -import java.util.concurrent.atomic.AtomicBoolean; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; /** * @@ -47,7 +48,7 @@ public boolean isAutoStartup() { public void start() { try { - metaServerBootstrap.doInitialized(); + metaServerBootstrap.start(); LOGGER.info("Started MetaServer"); MetaServerInitializerConfiguration.this.running.set(true); diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/DataNodeService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/DataNodeService.java index 9fc3efccc..10f77b834 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/DataNodeService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/DataNodeService.java @@ -18,6 +18,7 @@ import com.alipay.sofa.registry.common.model.metaserver.DataNode; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; +import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; import com.alipay.sofa.registry.common.model.metaserver.StatusConfirmRequest; import java.util.Map; @@ -33,4 +34,6 @@ void pushDataNodes(NodeChangeResult nodeChangeResult, Map targ boolean confirm, String confirmNodeIp); void notifyStatusConfirm(StatusConfirmRequest statusConfirmRequest); + + void notifyProvideDataChange(NotifyProvideDataChange notifyProvideDataChange); } \ No newline at end of file diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/DataNodeServiceImpl.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/DataNodeServiceImpl.java index d7bb82df1..a8300f1b5 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/DataNodeServiceImpl.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/DataNodeServiceImpl.java @@ -21,6 +21,7 @@ import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; import com.alipay.sofa.registry.common.model.metaserver.DataNode; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; +import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; import com.alipay.sofa.registry.common.model.metaserver.StatusConfirmRequest; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; @@ -134,7 +135,7 @@ public URL getRequestUrl() { } } catch (RequestException e) { - LOGGER.error("Push dataNode list error! " + e.getRequestMessage(), e); + LOGGER.error("Push dataNode list error! " + e.getMessage(), e); exceptions.add(e); } catch (RuntimeException e) { LOGGER.error("Push dataNode list runtime error! ", e); @@ -178,8 +179,56 @@ public URL getRequestUrl() { } } catch (RequestException e) { - LOGGER.error("Notify status confirm error! " + e.getRequestMessage(), e); - throw new RuntimeException("Notify status confirm error! ", e); + throw new RuntimeException("Notify status confirm error: " + e.getMessage(), e); + } + } + + @Override + public void notifyProvideDataChange(NotifyProvideDataChange notifyProvideDataChange) { + + NodeConnectManager nodeConnectManager = getNodeConnectManager(); + Collection connections = nodeConnectManager.getConnections(null); + + if (connections == null || connections.isEmpty()) { + LOGGER.error("Push dataNode list error! No data node connected!"); + throw new RuntimeException("Push dataNode list error! No data node connected!"); + } + + // add register confirm + StoreService storeService = ServiceFactory.getStoreService(NodeType.DATA); + Map dataNodes = storeService.getNodes(); + + if (dataNodes == null || dataNodes.isEmpty()) { + LOGGER.error("Push dataNode list error! No data node registered!"); + throw new RuntimeException("Push dataNode list error! No data node registered!"); + } + + for (InetSocketAddress connection : connections) { + + if (!dataNodes.keySet().contains(connection.getAddress().getHostAddress())) { + continue; + } + + try { + Request request = new Request() { + + @Override + public NotifyProvideDataChange getRequestBody() { + return notifyProvideDataChange; + } + + @Override + public URL getRequestUrl() { + return new URL(connection); + } + }; + + dataNodeExchanger.request(request); + + } catch (RequestException e) { + throw new RuntimeException("Notify provide data change to dataServer error: " + + e.getMessage(), e); + } } } diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/MetaNodeServiceImpl.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/MetaNodeServiceImpl.java index e0aead477..255287c97 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/MetaNodeServiceImpl.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/MetaNodeServiceImpl.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.server.meta.node.impl; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; import com.alipay.sofa.registry.common.model.metaserver.GetChangeListRequest; @@ -27,7 +29,6 @@ import com.alipay.sofa.registry.remoting.exchange.message.Response; import com.alipay.sofa.registry.server.meta.node.MetaNodeService; import com.alipay.sofa.registry.server.meta.remoting.MetaClientExchanger; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -69,9 +70,8 @@ public URL getRequestUrl() { } } catch (RequestException e) { - LOGGER.error("MetaNodeService get DataCenter Nodes error! " + e.getRequestMessage(), e); throw new RuntimeException("MetaNodeService get DataCenter Nodes error! " - + e.getRequestMessage(), e); + + e.getMessage(), e); } } diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/SessionNodeServiceImpl.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/SessionNodeServiceImpl.java index 9e3da8ab4..9aa2e3ff7 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/SessionNodeServiceImpl.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/node/impl/SessionNodeServiceImpl.java @@ -16,6 +16,12 @@ */ package com.alipay.sofa.registry.server.meta.node.impl; +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; @@ -32,11 +38,6 @@ import com.alipay.sofa.registry.server.meta.remoting.connection.NodeConnectManager; import com.alipay.sofa.registry.server.meta.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.meta.store.StoreService; -import org.springframework.beans.factory.annotation.Autowired; - -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.Map; /** * @@ -113,8 +114,7 @@ public URL getRequestUrl() { confirmNodeIp); } catch (RequestException e) { - LOGGER.error("Push sessionNode list error! " + e.getRequestMessage(), e); - throw new RuntimeException("SessionNodeService push sessionNode list error!"); + throw new RuntimeException("Push sessionNode list error: " + e.getMessage(), e); } } @@ -163,8 +163,7 @@ public URL getRequestUrl() { sessionNodeExchanger.request(nodeChangeRequestRequest); } catch (RequestException e) { - LOGGER.error("Push sessionNode list error! " + e.getRequestMessage(), e); - throw new RuntimeException("SessionNodeService push dataNode list error!"); + throw new RuntimeException("Push sessionNode list error: " + e.getMessage(), e); } } } @@ -212,8 +211,7 @@ public URL getRequestUrl() { sessionNodeExchanger.request(request); } catch (RequestException e) { - LOGGER.error("Notify provide data change error! " + e.getRequestMessage(), e); - throw new RuntimeException("Notify provide data change error!"); + throw new RuntimeException("Notify provide data change error: " + e.getMessage(), e); } } } diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/MetaServerRegistry.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/MetaServerRegistry.java index 589c5ce4c..2c6f9642b 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/MetaServerRegistry.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/MetaServerRegistry.java @@ -16,6 +16,9 @@ */ package com.alipay.sofa.registry.server.meta.registry; +import java.util.Collection; +import java.util.List; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; @@ -25,9 +28,6 @@ import com.alipay.sofa.registry.server.meta.bootstrap.ServiceFactory; import com.alipay.sofa.registry.server.meta.store.StoreService; -import java.util.Collection; -import java.util.List; - /** * factory func to operate StoreService * @author shangyu.wh @@ -73,9 +73,9 @@ public void evict() { } @Override - public void reNew(Node node, int duration) { + public void renew(Node node, int duration) { StoreService storeService = ServiceFactory.getStoreService(node.getNodeType()); - storeService.reNew(node, duration); + storeService.renew(node, duration); } @Override diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/Registry.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/Registry.java index 2bda79a84..ec8b92988 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/Registry.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/registry/Registry.java @@ -16,13 +16,13 @@ */ package com.alipay.sofa.registry.server.meta.registry; +import java.util.List; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; -import java.util.List; - /** * * @author shangyu.wh @@ -62,7 +62,7 @@ public interface Registry { * renew node expire time * @param node */ - void reNew(T node, int duration); + void renew(T node, int duration); /** * get other dataCenter Nodes change scheduled diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/RaftExchanger.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/RaftExchanger.java index 981c1a19e..f64c15ced 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/RaftExchanger.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/RaftExchanger.java @@ -16,6 +16,15 @@ */ package com.alipay.sofa.registry.server.meta.remoting; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.jraft.CliService; import com.alipay.sofa.jraft.Status; import com.alipay.sofa.jraft.conf.Configuration; @@ -38,14 +47,6 @@ import com.alipay.sofa.registry.server.meta.bootstrap.NodeConfig; import com.alipay.sofa.registry.server.meta.executor.ExecutorManager; import com.alipay.sofa.registry.server.meta.registry.Registry; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; /** * @@ -100,8 +101,9 @@ public void startProcess() { LOGGER_START.info("Initialize server scheduler success!"); PeerId leader = new PeerId(NetUtil.getLocalAddress().getHostAddress(), metaServerConfig.getRaftServerPort()); - raftServer.sendNotify(leader, "leader"); + // refer: https://github.com/sofastack/sofa-registry/issues/30 registerCurrentNode(); + raftServer.sendNotify(leader, "leader"); } @Override @@ -119,8 +121,14 @@ public void stopProcess() { @Override public void startProcess(PeerId leader) { LOGGER_START.info("Start follower process leader {}...", leader); - raftServer.sendNotify(leader, "follower"); + // refer: https://github.com/sofastack/sofa-registry/issues/31 + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + LOGGER_START.error(e.getMessage(), e); + } registerCurrentNode(); + raftServer.sendNotify(leader, "follower"); } @Override diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/ReNewNodesRequestHandler.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/RenewNodesRequestHandler.java similarity index 73% rename from server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/ReNewNodesRequestHandler.java rename to server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/RenewNodesRequestHandler.java index 7425ce141..e30229d2d 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/ReNewNodesRequestHandler.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/remoting/handler/RenewNodesRequestHandler.java @@ -16,42 +16,43 @@ */ package com.alipay.sofa.registry.server.meta.remoting.handler; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; -import com.alipay.sofa.registry.common.model.metaserver.ReNewNodesRequest; +import com.alipay.sofa.registry.common.model.metaserver.RenewNodesRequest; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.server.meta.registry.Registry; -import org.springframework.beans.factory.annotation.Autowired; /** * Handle session/data node's heartbeat request * @author shangyu.wh - * @version $Id: ReNewNodesRequestHandler.java, v 0.1 2018-03-30 19:58 shangyu.wh Exp $ + * @version $Id: RenewNodesRequestHandler.java, v 0.1 2018-03-30 19:58 shangyu.wh Exp $ */ -public class ReNewNodesRequestHandler extends AbstractServerHandler { +public class RenewNodesRequestHandler extends AbstractServerHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(ReNewNodesRequestHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RenewNodesRequestHandler.class); @Autowired private Registry metaServerRegistry; @Override - public Object reply(Channel channel, ReNewNodesRequest reNewNodesRequest) { - Node reNewNode = null; + public Object reply(Channel channel, RenewNodesRequest renewNodesRequest) { + Node renewNode = null; try { - reNewNode = reNewNodesRequest.getNode(); - metaServerRegistry.reNew(reNewNode, reNewNodesRequest.getDuration()); + renewNode = renewNodesRequest.getNode(); + metaServerRegistry.renew(renewNode, renewNodesRequest.getDuration()); } catch (Exception e) { - LOGGER.error("Node " + reNewNode + "reNew error!", e); - throw new RuntimeException("Node reNew error!", e); + LOGGER.error("Node " + renewNode + "renew error!", e); + throw new RuntimeException("Node renew error!", e); } return null; } @Override public Class interest() { - return ReNewNodesRequest.class; + return RenewNodesRequest.class; } @Override diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/DataRepositoryService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/DataRepositoryService.java index 716359bb3..91c02428c 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/DataRepositoryService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/DataRepositoryService.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.meta.repository.service; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.metaserver.DataNode; import com.alipay.sofa.registry.jraft.processor.AbstractSnapshotProcess; import com.alipay.sofa.registry.jraft.processor.SnapshotProcess; @@ -26,15 +36,6 @@ import com.alipay.sofa.registry.server.meta.repository.RepositoryService; import com.alipay.sofa.registry.server.meta.store.RenewDecorate; import com.alipay.sofa.registry.store.api.annotation.RaftService; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @@ -170,7 +171,7 @@ public RenewDecorate replace(String ipAddress, RenewDecorate RenewDecorate oldRenewDecorate = dataNodes.get(ipAddress); if (oldRenewDecorate != null && oldRenewDecorate.getRenewal() != null) { oldRenewDecorate.setRenewal(dataNode.getRenewal()); - oldRenewDecorate.reNew(); + oldRenewDecorate.renew(); } else { LOGGER.error("Data node with ipAddress {} has not existed!", ipAddress); throw new RuntimeException(String.format( diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/MetaRepositoryService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/MetaRepositoryService.java index 927247aa9..a7f5bcdd2 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/MetaRepositoryService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/MetaRepositoryService.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.meta.repository.service; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.metaserver.MetaNode; import com.alipay.sofa.registry.jraft.processor.AbstractSnapshotProcess; import com.alipay.sofa.registry.jraft.processor.SnapshotProcess; @@ -26,15 +36,6 @@ import com.alipay.sofa.registry.server.meta.repository.RepositoryService; import com.alipay.sofa.registry.server.meta.store.RenewDecorate; import com.alipay.sofa.registry.store.api.annotation.RaftService; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @@ -168,7 +169,7 @@ public RenewDecorate replace(String ipAddress, RenewDecorate RenewDecorate oldRenewDecorate = dataNodes.get(ipAddress); if (oldRenewDecorate != null && oldRenewDecorate.getRenewal() != null) { oldRenewDecorate.setRenewal(metaNode.getRenewal()); - oldRenewDecorate.reNew(); + oldRenewDecorate.renew(); metaNodeRepository.setVersion(System.currentTimeMillis()); } else { diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/SessionRepositoryService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/SessionRepositoryService.java index 4a4f4d10f..445c194ac 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/SessionRepositoryService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/repository/service/SessionRepositoryService.java @@ -16,6 +16,14 @@ */ package com.alipay.sofa.registry.server.meta.repository.service; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.metaserver.SessionNode; import com.alipay.sofa.registry.jraft.processor.AbstractSnapshotProcess; import com.alipay.sofa.registry.jraft.processor.SnapshotProcess; @@ -26,13 +34,6 @@ import com.alipay.sofa.registry.server.meta.repository.RepositoryService; import com.alipay.sofa.registry.server.meta.store.RenewDecorate; import com.alipay.sofa.registry.store.api.annotation.RaftService; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /** * @@ -115,7 +116,7 @@ public RenewDecorate replace(String ipAddress, RenewDecorate oldRenewDecorate = registry.get(ipAddress); if (oldRenewDecorate != null && oldRenewDecorate.getRenewal() != null) { oldRenewDecorate.setRenewal(sessionNode.getRenewal()); - oldRenewDecorate.reNew(); + oldRenewDecorate.renew(); } else { LOGGER.error("Session node with ipAddress {} has not existed!", ipAddress); throw new RuntimeException(String.format( diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/BlacklistDataResource.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/BlacklistDataResource.java new file mode 100644 index 000000000..f11320812 --- /dev/null +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/BlacklistDataResource.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.meta.resource; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.console.PersistenceData; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.metaserver.DataOperator; +import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; +import com.alipay.sofa.registry.common.model.store.DataInfo; +import com.alipay.sofa.registry.core.model.Result; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.store.api.DBService; +import com.alipay.sofa.registry.store.api.annotation.RaftReference; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; + +/** + * + * @author shangyu.wh + * @version $Id: StopPushDataResource.java, v 0.1 2018-07-25 11:40 shangyu.wh Exp $ + */ +@Path("blacklist") +public class BlacklistDataResource { + + private static final Logger DB_LOGGER = LoggerFactory.getLogger(BlacklistDataResource.class, + "[DBService]"); + + private static final Logger TASK_LOGGER = LoggerFactory.getLogger(BlacklistDataResource.class, + "[Task]"); + + @RaftReference + private DBService persistenceDataDBService; + + @Autowired + private TaskListenerManager taskListenerManager; + + /** + * update blacklist + * e.g. curl -d '{"FORBIDDEN_PUB":{"IP_FULL":["1.1.1.1","10.15.233.150"]},"FORBIDDEN_SUB_BY_PREFIX":{"IP_FULL":["1.1.1.1"]}}' -H "Content-Type: application/json" -X POST http://localhost:9615/blacklist/update + */ + @POST + @Path("update") + @Produces(MediaType.APPLICATION_JSON) + public Result blacklistPush(String config) { + PersistenceData persistenceData = createDataInfo(); + persistenceData.setData(config); + try { + boolean ret = persistenceDataDBService.update(ValueConstants.BLACK_LIST_DATA_ID, + persistenceData); + DB_LOGGER.info("Success update blacklist to DB result {}!", ret); + } catch (Exception e) { + DB_LOGGER.error("Error update blacklist to DB!", e); + throw new RuntimeException("Update blacklist to error!"); + } + + fireDataChangeNotify(persistenceData.getVersion(), ValueConstants.BLACK_LIST_DATA_ID, + DataOperator.UPDATE); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + private PersistenceData createDataInfo() { + DataInfo dataInfo = DataInfo.valueOf(ValueConstants.BLACK_LIST_DATA_ID); + PersistenceData persistenceData = new PersistenceData(); + persistenceData.setDataId(dataInfo.getDataId()); + persistenceData.setGroup(dataInfo.getDataType()); + persistenceData.setInstanceId(dataInfo.getInstanceId()); + persistenceData.setVersion(System.currentTimeMillis()); + return persistenceData; + } + + private void fireDataChangeNotify(Long version, String dataInfoId, DataOperator dataOperator) { + + NotifyProvideDataChange notifyProvideDataChange = new NotifyProvideDataChange(dataInfoId, + version, dataOperator); + + TaskEvent taskEvent = new TaskEvent(notifyProvideDataChange, + TaskType.PERSISTENCE_DATA_CHANGE_NOTIFY_TASK); + TASK_LOGGER.info("send PERSISTENCE_DATA_CHANGE_NOTIFY_TASK notifyProvideDataChange:" + + notifyProvideDataChange); + taskListenerManager.sendTaskEvent(taskEvent); + } + +} \ No newline at end of file diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/HealthResource.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/HealthResource.java index 8e6970390..e284a05d9 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/HealthResource.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/HealthResource.java @@ -16,16 +16,24 @@ */ package com.alipay.sofa.registry.server.meta.resource; -import com.alipay.sofa.registry.common.model.CommonResponse; -import com.alipay.sofa.registry.jraft.bootstrap.ServiceStateMachine; -import com.alipay.sofa.registry.server.meta.bootstrap.MetaServerBootstrap; -import com.alipay.sofa.registry.server.meta.remoting.RaftExchanger; -import org.springframework.beans.factory.annotation.Autowired; - +import javax.annotation.PostConstruct; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.jraft.bootstrap.ServiceStateMachine; +import com.alipay.sofa.registry.metrics.ReporterUtils; +import com.alipay.sofa.registry.server.meta.bootstrap.MetaServerBootstrap; +import com.alipay.sofa.registry.server.meta.remoting.RaftExchanger; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.MetricRegistry; /** * @@ -41,11 +49,28 @@ public class HealthResource { @Autowired private RaftExchanger raftExchanger; + @PostConstruct + public void init() { + MetricRegistry metrics = new MetricRegistry(); + metrics.register("healthCheck", (Gauge) () -> getHealthCheckResult()); + ReporterUtils.startSlf4jReporter(60, metrics); + } + @GET @Path("check") @Produces(MediaType.APPLICATION_JSON) - public CommonResponse checkHealth() { + public Response checkHealth() { + ResponseBuilder builder = Response.status(Response.Status.OK); + CommonResponse response = getHealthCheckResult(); + builder.entity(response); + if (!response.isSuccess()) { + builder.status(Status.INTERNAL_SERVER_ERROR); + } + + return builder.build(); + } + private CommonResponse getHealthCheckResult() { CommonResponse response; StringBuilder sb = new StringBuilder("MetaServerBoot "); @@ -96,7 +121,6 @@ public CommonResponse checkHealth() { } else { response = CommonResponse.buildFailedResponse(sb.toString()); } - return response; } } \ No newline at end of file diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/MetaDigestResource.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/MetaDigestResource.java index 538614f15..42211be7c 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/MetaDigestResource.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/MetaDigestResource.java @@ -16,26 +16,32 @@ */ package com.alipay.sofa.registry.server.meta.resource; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.console.PersistenceData; import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.metrics.ReporterUtils; import com.alipay.sofa.registry.server.meta.registry.Registry; import com.alipay.sofa.registry.store.api.DBResponse; import com.alipay.sofa.registry.store.api.DBService; import com.alipay.sofa.registry.store.api.OperationStatus; import com.alipay.sofa.registry.store.api.annotation.RaftReference; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import java.util.HashMap; -import java.util.Map; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.MetricRegistry; /** * @@ -57,6 +63,16 @@ public class MetaDigestResource { @RaftReference private DBService persistenceDataDBService; + @PostConstruct + public void init() { + MetricRegistry metrics = new MetricRegistry(); + metrics.register("metaNodeList", (Gauge) () -> getRegisterNodeByType("meta")); + metrics.register("dataNodeList", (Gauge) () -> getRegisterNodeByType("data")); + metrics.register("sessionNodeList", (Gauge) () -> getRegisterNodeByType("session")); + metrics.register("pushSwitch", (Gauge) () -> getPushSwitch()); + ReporterUtils.startSlf4jReporter(60, metrics); + } + @GET @Path("{type}/node/query") @Produces(MediaType.APPLICATION_JSON) diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/RenewSwitchResource.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/RenewSwitchResource.java new file mode 100644 index 000000000..1594661b1 --- /dev/null +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/resource/RenewSwitchResource.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.meta.resource; + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.Node.NodeType; +import com.alipay.sofa.registry.common.model.console.PersistenceData; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.metaserver.DataOperator; +import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; +import com.alipay.sofa.registry.common.model.store.DataInfo; +import com.alipay.sofa.registry.core.model.Result; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.store.api.DBResponse; +import com.alipay.sofa.registry.store.api.DBService; +import com.alipay.sofa.registry.store.api.annotation.RaftReference; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; + +/** + * + * @author shangyu.wh + * @version $Id: StopPushDataResource.java, v 0.1 2018-07-25 11:40 shangyu.wh Exp $ + */ +@Path("renewSwitch") +public class RenewSwitchResource { + + private static final Logger DB_LOGGER = LoggerFactory.getLogger(RenewSwitchResource.class, + "[DBService]"); + + private static final Logger TASK_LOGGER = LoggerFactory.getLogger(RenewSwitchResource.class, + "[Task]"); + + @RaftReference + private DBService persistenceDataDBService; + + @Autowired + private TaskListenerManager taskListenerManager; + + /** + * get + */ + @GET + @Path("get") + @Produces(MediaType.APPLICATION_JSON) + public Map getPushSwitch() throws Exception { + Map resultMap = new HashMap<>(1); + DBResponse enableDataRenewSnapshot = persistenceDataDBService + .get(ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT); + DBResponse enableDataDatumExpire = persistenceDataDBService + .get(ValueConstants.ENABLE_DATA_DATUM_EXPIRE); + + resultMap + .put( + "enableDataRenewSnapshot", + enableDataRenewSnapshot != null && enableDataRenewSnapshot.getEntity() != null ? ((PersistenceData) enableDataRenewSnapshot + .getEntity()).getData() : "null"); + resultMap + .put( + "enableDataDatumExpire", + enableDataDatumExpire != null && enableDataDatumExpire.getEntity() != null ? ((PersistenceData) enableDataDatumExpire + .getEntity()).getData() : "null"); + + return resultMap; + } + + /** + * enable both + */ + @GET + @Path("enable") + @Produces(MediaType.APPLICATION_JSON) + public Result enableRenew() { + invokeSession("true"); + invokeData("true"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + /** + * disable both + */ + @GET + @Path("disable") + @Produces(MediaType.APPLICATION_JSON) + public Result disableRenew() { + invokeSession("false"); + invokeData("false"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + /** + * enable session + */ + @GET + @Path("session/enable") + @Produces(MediaType.APPLICATION_JSON) + public Result enableSessionRenew() { + invokeSession("true"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + /** + * disable session + */ + @GET + @Path("session/disable") + @Produces(MediaType.APPLICATION_JSON) + public Result disableSessionRenew() { + invokeSession("false"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + /** + * enable data + */ + @GET + @Path("data/enable") + @Produces(MediaType.APPLICATION_JSON) + public Result enableDataRenew() { + invokeData("true"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + /** + * disable data + */ + @GET + @Path("data/disable") + @Produces(MediaType.APPLICATION_JSON) + public Result disableDataRenew() { + invokeData("false"); + + Result result = new Result(); + result.setSuccess(true); + return result; + } + + private void invokeSession(String data) { + String msg = "put ENABLE_DATA_RENEW_SNAPSHOT to DB"; + PersistenceData persistenceData = createPersistenceData(ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT); + persistenceData.setData(data); + try { + boolean ret = persistenceDataDBService.put(ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT, + persistenceData); + DB_LOGGER.info(String.format("%s result %s", msg, ret)); + } catch (Exception e) { + DB_LOGGER.error(String.format("Error %s: %s", msg, e.getMessage())); + throw new RuntimeException(String.format("Error %s: %s", msg, e.getMessage()), e); + } + + fireDataChangeNotify(NodeType.SESSION, persistenceData.getVersion(), + ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT, DataOperator.UPDATE); + } + + private void invokeData(String data) { + String msg = "put ENABLE_DATA_DATUM_EXPIRE to DB"; + PersistenceData persistenceData = createPersistenceData(ValueConstants.ENABLE_DATA_DATUM_EXPIRE); + persistenceData.setData(data); + try { + boolean ret = persistenceDataDBService.put(ValueConstants.ENABLE_DATA_DATUM_EXPIRE, + persistenceData); + DB_LOGGER.info(String.format("%s result %s", msg, ret)); + } catch (Exception e) { + DB_LOGGER.error(String.format("Error %s: %s", msg, e.getMessage())); + throw new RuntimeException(String.format("Error %s: %s", msg, e.getMessage()), e); + } + + fireDataChangeNotify(NodeType.DATA, persistenceData.getVersion(), + ValueConstants.ENABLE_DATA_DATUM_EXPIRE, DataOperator.UPDATE); + } + + private PersistenceData createPersistenceData(String dataId) { + DataInfo dataInfo = DataInfo.valueOf(dataId); + PersistenceData persistenceData = new PersistenceData(); + persistenceData.setDataId(dataInfo.getDataId()); + persistenceData.setGroup(dataInfo.getDataType()); + persistenceData.setInstanceId(dataInfo.getInstanceId()); + persistenceData.setVersion(System.currentTimeMillis()); + return persistenceData; + } + + private void fireDataChangeNotify(NodeType nodeType, Long version, String dataInfoId, + DataOperator dataOperator) { + NotifyProvideDataChange notifyProvideDataChange = new NotifyProvideDataChange(dataInfoId, + version, dataOperator); + notifyProvideDataChange.setNodeType(nodeType); + + TaskEvent taskEvent = new TaskEvent(notifyProvideDataChange, + TaskType.PERSISTENCE_DATA_CHANGE_NOTIFY_TASK); + TASK_LOGGER.info("send PERSISTENCE_DATA_CHANGE_NOTIFY_TASK notifyProvideDataChange:" + + notifyProvideDataChange); + taskListenerManager.sendTaskEvent(taskEvent); + } + +} \ No newline at end of file diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/DataStoreService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/DataStoreService.java index ff324ff19..cbde82c74 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/DataStoreService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/DataStoreService.java @@ -16,6 +16,21 @@ */ package com.alipay.sofa.registry.server.meta.store; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; import com.alipay.sofa.registry.common.model.metaserver.DataNode; @@ -36,20 +51,6 @@ import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; /** * @@ -110,7 +111,7 @@ public NodeChangeResult addNode(DataNode dataNode) { dataRepositoryService.put(ipAddress, new RenewDecorate(dataNode, RenewDecorate.DEFAULT_DURATION_SECS)); - reNew(dataNode, 30); + renew(dataNode, 30); nodeChangeResult = getNodeChangeResult(); @@ -170,15 +171,15 @@ public void removeNodes(Collection nodes) { } @Override - public void reNew(DataNode dataNode, int duration) { + public void renew(DataNode dataNode, int duration) { long startAll = System.currentTimeMillis(); write.lock(); try { String ipAddress = dataNode.getNodeUrl().getIpAddress(); - RenewDecorate reNewer = dataRepositoryService.get(ipAddress); + RenewDecorate renewer = dataRepositoryService.get(ipAddress); - if (reNewer == null) { + if (renewer == null) { LOGGER.warn("Renew Data node with ipAddress:" + ipAddress + " has not existed!It will be registered again!"); addNode(dataNode); @@ -206,7 +207,7 @@ public void reNew(DataNode dataNode, int duration) { */ @Override public Collection getExpired() { - Collection reNewerList = new ArrayList<>(); + Collection renewerList = new ArrayList<>(); read.lock(); try { Map> dataMap = dataRepositoryService.getAllData(); @@ -216,7 +217,7 @@ public Collection getExpired() { String dataCenter = dataNode.getRenewal().getDataCenter(); if (dataCenter.equals(nodeConfig.getLocalDataCenter())) { if (dataNode.isExpired()) { - reNewerList.add(dataNode.getRenewal()); + renewerList.add(dataNode.getRenewal()); } } }); @@ -224,7 +225,7 @@ public Collection getExpired() { } finally { read.unlock(); } - return reNewerList; + return renewerList; } @Override diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/MetaStoreService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/MetaStoreService.java index f50ce3b80..a57b53b31 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/MetaStoreService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/MetaStoreService.java @@ -167,7 +167,7 @@ public void confirmNodeStatus(String connectId, String ip) { } @Override - public void reNew(MetaNode node, int duration) { + public void renew(MetaNode node, int duration) { } @Override @@ -335,9 +335,8 @@ private void firePushDataListTask(NodeChangeResult nodeChangeResult, String node taskEvent.setAttribute(Constant.PUSH_TARGET_TYPE, NodeType.DATA); taskEvent.setAttribute(Constant.PUSH_TARGET_OPERATOR_TYPE, nodeOperate); - LOGGER.info("send " + taskEvent.getTaskType() + " NodeType:" + NodeType.DATA + " Operator:" - + nodeOperate); - + LOGGER.info("send {} NodeType:{} Operator:{}", taskEvent.getTaskType(), NodeType.DATA, + nodeOperate); taskListenerManager.sendTaskEvent(taskEvent); } @@ -347,8 +346,8 @@ private void firePushSessionListTask(NodeChangeResult nodeChangeResult, String n TaskEvent taskEvent = new TaskEvent(nodeChangeResult, TaskType.DATA_NODE_CHANGE_PUSH_TASK); taskEvent.setAttribute(Constant.PUSH_TARGET_TYPE, NodeType.SESSION); taskEvent.setAttribute(Constant.PUSH_TARGET_OPERATOR_TYPE, nodeOperate); - LOGGER.info("send " + taskEvent.getTaskType() + " NodeType:" + NodeType.SESSION - + " Operator:" + nodeOperate); + LOGGER.info("send {} NodeType:{} Operator:{}", taskEvent.getTaskType(), NodeType.SESSION, + nodeOperate); taskListenerManager.sendTaskEvent(taskEvent); } diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/RenewDecorate.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/RenewDecorate.java index e642ba557..2127a2c1b 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/RenewDecorate.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/RenewDecorate.java @@ -21,7 +21,7 @@ /** * heartbeat info for node * @author shangyu.wh - * @version $Id: ReNewer.java, v 0.1 2018-01-16 17:10 shangyu.wh Exp $ + * @version $Id: Renewer.java, v 0.1 2018-01-16 17:10 shangyu.wh Exp $ */ public class RenewDecorate implements Serializable { @@ -66,7 +66,7 @@ public boolean isExpired() { /** * refresh lastUpdateTimestamp */ - public void reNew() { + public void renew() { lastUpdateTimestamp = System.currentTimeMillis() + duration; } @@ -74,7 +74,7 @@ public void reNew() { * refresh lastUpdateTimestamp by durationSECS * @param durationSECS */ - public void reNew(long durationSECS) { + public void renew(long durationSECS) { lastUpdateTimestamp = System.currentTimeMillis() + durationSECS * 1000; } diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/SessionStoreService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/SessionStoreService.java index 5123a9f43..b5d204ce9 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/SessionStoreService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/SessionStoreService.java @@ -16,6 +16,21 @@ */ package com.alipay.sofa.registry.server.meta.store; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; + +import javax.ws.rs.NotSupportedException; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; @@ -34,19 +49,6 @@ import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.ws.rs.NotSupportedException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; /** * @@ -106,7 +108,7 @@ public NodeChangeResult addNode(SessionNode sessionNode) { sessionVersionRepositoryService.checkAndUpdateVersions(nodeConfig.getLocalDataCenter(), System.currentTimeMillis()); - reNew(sessionNode, 30); + renew(sessionNode, 30); sessionConfirmStatusService.putConfirmNode(sessionNode, DataOperator.ADD); @@ -173,15 +175,15 @@ public void removeNodes(Collection nodes) { } @Override - public void reNew(SessionNode sessionNode, int duration) { + public void renew(SessionNode sessionNode, int duration) { write.lock(); try { String ipAddress = sessionNode.getNodeUrl().getIpAddress(); - RenewDecorate reNewer = sessionRepositoryService.get(ipAddress); + RenewDecorate renewer = sessionRepositoryService.get(ipAddress); - if (reNewer == null) { - LOGGER.warn("ReNew session node with ipAddress:" + ipAddress + if (renewer == null) { + LOGGER.warn("Renew session node with ipAddress:" + ipAddress + " has not existed!It will be registered again!"); addNode(sessionNode); } else { @@ -200,19 +202,19 @@ public void reNew(SessionNode sessionNode, int duration) { @Override public Collection getExpired() { - Collection reNewerList = new ArrayList<>(); + Collection renewerList = new ArrayList<>(); read.lock(); try { Map> map = sessionRepositoryService.getAllData(); map.forEach((key, value) -> { if (value.isExpired()) { - reNewerList.add(value.getRenewal()); + renewerList.add(value.getRenewal()); } }); } finally { read.unlock(); } - return reNewerList; + return renewerList; } @Override diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/StoreService.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/StoreService.java index 05d38de1b..420e29dc5 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/StoreService.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/store/StoreService.java @@ -16,15 +16,15 @@ */ package com.alipay.sofa.registry.server.meta.store; +import java.util.Collection; +import java.util.List; +import java.util.Map; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataCenterNodes; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; -import java.util.Collection; -import java.util.List; -import java.util.Map; - /** * interface for node store service * @author shangyu.wh @@ -72,7 +72,7 @@ public interface StoreService { * @param node * @return */ - void reNew(T node, int duration); + void renew(T node, int duration); /** * get expired node list diff --git a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/task/PersistenceDataChangeNotifyTask.java b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/task/PersistenceDataChangeNotifyTask.java index 63d986fcc..20cf9643e 100644 --- a/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/task/PersistenceDataChangeNotifyTask.java +++ b/server/server/meta/src/main/java/com/alipay/sofa/registry/server/meta/task/PersistenceDataChangeNotifyTask.java @@ -20,6 +20,7 @@ import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; import com.alipay.sofa.registry.server.meta.bootstrap.MetaServerConfig; import com.alipay.sofa.registry.server.meta.bootstrap.ServiceFactory; +import com.alipay.sofa.registry.server.meta.node.DataNodeService; import com.alipay.sofa.registry.server.meta.node.SessionNodeService; import com.alipay.sofa.registry.task.listener.TaskEvent; @@ -32,6 +33,8 @@ public class PersistenceDataChangeNotifyTask extends AbstractMetaServerTask { private final SessionNodeService sessionNodeService; + private final DataNodeService dataNodeService; + final private MetaServerConfig metaServerConfig; private NotifyProvideDataChange notifyProvideDataChange; @@ -40,11 +43,17 @@ public PersistenceDataChangeNotifyTask(MetaServerConfig metaServerConfig) { this.metaServerConfig = metaServerConfig; this.sessionNodeService = (SessionNodeService) ServiceFactory .getNodeService(NodeType.SESSION); + + this.dataNodeService = (DataNodeService) ServiceFactory.getNodeService(NodeType.DATA); } @Override public void execute() { - sessionNodeService.notifyProvideDataChange(notifyProvideDataChange); + if (notifyProvideDataChange.getNodeType() == NodeType.DATA) { + dataNodeService.notifyProvideDataChange(notifyProvideDataChange); + } else { + sessionNodeService.notifyProvideDataChange(notifyProvideDataChange); + } } @Override diff --git a/server/server/meta/src/main/resources/application.properties b/server/server/meta/src/main/resources/application.properties index 2449af5b3..4ad2a2b2d 100644 --- a/server/server/meta/src/main/resources/application.properties +++ b/server/server/meta/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.main.banner-mode=LOG -#nodes.metaNode=: -#nodes.localDataCenter= +nodes.metaNode=DefaultDataCenter:localhost +nodes.localDataCenter=DefaultDataCenter #meta.server.logging.level=INFO #meta.server.logging.home=/home/admin/logs/registry/meta diff --git a/server/server/meta/src/main/resources/logback-spring.xml b/server/server/meta/src/main/resources/logback-spring.xml index 6294f4dcf..0d5cb2faa 100644 --- a/server/server/meta/src/main/resources/logback-spring.xml +++ b/server/server/meta/src/main/resources/logback-spring.xml @@ -173,6 +173,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${META_LOG_HOME}/registry-metrics.log + + ${META_LOG_HOME}/registry-metrics.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -231,6 +251,12 @@ + + + + + + diff --git a/server/server/meta/src/main/resources/security/blacklist.txt b/server/server/meta/src/main/resources/security/blacklist.txt new file mode 100644 index 000000000..e3413f8d4 --- /dev/null +++ b/server/server/meta/src/main/resources/security/blacklist.txt @@ -0,0 +1,78 @@ +org.codehaus.groovy.runtime.MethodClosure +clojure.core$constantly +clojure.main$eval_opt +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactory +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactoryImpl +com.alibaba.citrus.springext.util.SpringExtUtil.AbstractProxy +com.alipay.custrelation.service.model.redress.Pair +com.caucho.hessian.test.TestCons +com.mchange.v2.c3p0.JndiRefForwardingDataSource +com.mchange.v2.c3p0.WrapperConnectionPoolDataSource +com.rometools.rome.feed.impl.EqualsBean +com.rometools.rome.feed.impl.ToStringBean +com.sun.jndi.rmi.registry.BindingEnumeration +com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl +com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl +com.sun.rowset.JdbcRowSetImpl +com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data +java.rmi.server.UnicastRemoteObject +java.security.SignedObject +java.util.ServiceLoader$LazyIterator +javax.imageio.ImageIO$ContainsFilter +javax.imageio.spi.ServiceRegistry +javax.management.BadAttributeValueExpException +javax.naming.InitialContext +javax.naming.spi.ObjectFactory +javax.script.ScriptEngineManager +javax.sound.sampled.AudioFormat$Encoding +org.apache.carbondata.core.scan.expression.ExpressionResult +org.apache.commons.dbcp +org.apache.commons.dbcp2 +org.apache.commons.beanutils +org.apache.ibatis.executor.loader.AbstractSerialStateHolder +org.apache.ibatis.executor.loader.CglibSerialStateHolder +org.apache.ibatis.executor.loader.JavassistSerialStateHolder +org.apache.ibatis.executor.loader.cglib.CglibProxyFactory +org.apache.ibatis.executor.loader.javassist.JavassistSerialStateHolder +org.apache.tomcat.dbcp.dbcp.datasources.SharedPoolDataSource +org.apache.wicket.util.upload.DiskFileItem +org.apache.xalan.xsltc.trax.TemplatesImpl +org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding +org.apache.xpath.XPathContext +org.eclipse.jetty.util.log.LoggerLog +org.geotools.filter.ConstantExpression +org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder +org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor +org.springframework.beans.factory.BeanFactory +org.springframework.beans.factory.config.PropertyPathFactoryBean +org.springframework.beans.factory.support.DefaultListableBeanFactory +org.springframework.jndi.support.SimpleJndiBeanFactory +org.springframework.orm.jpa.AbstractEntityManagerFactoryBean +org.springframework.transaction.jta.JtaTransactionManager +org.yaml.snakeyaml.tokens.DirectiveToken +sun.rmi.server.UnicastRef +javax.management.ImmutableDescriptor +org.springframework.jndi.JndiObjectTargetSource +ch.qos.logback.core.db.JNDIConnectionSource +java.beans.Expression +javassist.bytecode +javassist.tools.web.Viewer +javassist.util.proxy.SerializedProxy +org.apache.ibatis.javassist.bytecode +org.apache.ibatis.javassist.tools.web.Viewer +org.apache.ibatis.javassist.util.proxy.SerializedProxy +org.springframework.beans.factory.config.MethodInvokingFactoryBean +com.alibaba.druid +com.sun.corba +com.sun.org.apache.bcel +com.sun.org.apache.xml +com.sun.org.apache.xpath +org.apache.zookeeper.Shell +org.apache.tomcat.dbcp.dbcp.BasicDataSource +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +org.jboss.resteasy.plugins +org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler +org.apache.velocity.runtime.resource.Resource +org.springframework.expression.spel.ast.Indexer$PropertyIndexingValueRef +org.mortbay.log.Slf4jLog +org.springframework.expression.spel.ast.MethodReference$MethodValueRef \ No newline at end of file diff --git a/server/server/pom.xml b/server/server/pom.xml index 3ff53a5e2..742c1fa75 100644 --- a/server/server/pom.xml +++ b/server/server/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/server/session/pom.xml b/server/server/session/pom.xml index 3a9a152f9..ff54e7abc 100644 --- a/server/server/session/pom.xml +++ b/server/server/session/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptor.java new file mode 100644 index 000000000..3f844b234 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptor.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.acceptor; + +/** + * + * @author kezhu.wukz + * @author shangyu.wh + * @version 1.0: WriteDataAcceptor.java, v 0.1 2019-06-11 15:08 shangyu.wh Exp $ + */ +public interface WriteDataAcceptor { + + /** + * accept all write data request + * @param request + */ + void accept(WriteDataRequest request); + + /** + * remove processor of connectId + * @param connectId + */ + void remove(String connectId); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptorImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptorImpl.java new file mode 100644 index 000000000..7dd839c01 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataAcceptorImpl.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.acceptor; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.renew.RenewService; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; + +/** + * + * @author kezhu.wukz + * @author shangyu.wh + * @version 1.0: WriteDataAcceptor.java, v 0.1 2019-06-06 12:45 shangyu.wh Exp $ + */ +public class WriteDataAcceptorImpl implements WriteDataAcceptor { + + @Autowired + private TaskListenerManager taskListenerManager; + + @Autowired + private SessionServerConfig sessionServerConfig; + + @Autowired + private RenewService renewService; + + /** + * acceptor for all write data request + * key:connectId + * value:writeRequest processor + * + */ + private Map writeDataProcessors = new ConcurrentHashMap(); + + public void accept(WriteDataRequest request) { + String connectId = request.getConnectId(); + WriteDataProcessor writeDataProcessor = writeDataProcessors.computeIfAbsent(connectId, + key -> new WriteDataProcessor(connectId, taskListenerManager, sessionServerConfig, renewService)); + + writeDataProcessor.process(request); + } + + public void remove(String connectId) { + writeDataProcessors.remove(connectId); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataProcessor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataProcessor.java new file mode 100644 index 000000000..3e9e497b5 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataProcessor.java @@ -0,0 +1,330 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.acceptor; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.acceptor.WriteDataRequest.WriteDataRequestType; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.renew.RenewService; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; +import com.google.common.collect.Lists; + +/** + * + * @author kezhu.wukz + * @author shangyu.wh + * @version 1.0: WriteDataProcessor.java, v 0.1 2019-06-06 12:50 shangyu.wh Exp $ + */ +public class WriteDataProcessor { + + private static final Logger LOGGER = LoggerFactory + .getLogger(WriteDataProcessor.class); + + private static final Logger RENEW_LOGGER = LoggerFactory + .getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[WriteDataProcessor]"); + + private static final Logger taskLogger = LoggerFactory + .getLogger( + WriteDataProcessor.class, + "[Task]"); + + private final TaskListenerManager taskListenerManager; + + private final SessionServerConfig sessionServerConfig; + + private final RenewService renewService; + + private final String connectId; + + private Map lastUpdateTimestampMap = new ConcurrentHashMap<>(); + + private AtomicBoolean writeDataLock = new AtomicBoolean( + false); + + private ConcurrentLinkedQueue acceptorQueue = new ConcurrentLinkedQueue(); + + private AtomicInteger acceptorQueueSize = new AtomicInteger(0); + + public WriteDataProcessor(String connectId, TaskListenerManager taskListenerManager, + SessionServerConfig sessionServerConfig, RenewService renewService) { + this.connectId = connectId; + this.taskListenerManager = taskListenerManager; + this.sessionServerConfig = sessionServerConfig; + this.renewService = renewService; + } + + private boolean halt() { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("halt: connectId={}", connectId); + } + return writeDataLock.compareAndSet(false, true); + } + + public void resume() { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("resume: connectId={}", connectId); + } + flushQueue(); + writeDataLock.compareAndSet(true, false); + flushQueue(); + } + + public void process(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("process: connectId={}, requestType={}, requestBody={}", connectId, + request.getRequestType(), request.getRequestBody()); + } + + // record the last update time by pub/unpub + if (isWriteRequest(request)) { + refreshUpdateTime(request.getDataServerIP()); + } + + if (request.getRequestType() == WriteDataRequestType.DATUM_SNAPSHOT) { + // snapshot has high priority, so handle directly + doHandle(request); + } else { + // If locked, insert the queue; + // otherwise, try emptying the queue (to avoid residue) before processing the request. + if (writeDataLock.get()) { + addQueue(request); + } else { + flushQueue(); + doHandle(request); + } + } + + } + + private void addQueue(WriteDataRequest request) { + if (acceptorQueueSize.incrementAndGet() <= sessionServerConfig + .getWriteDataAcceptorQueueSize()) { + acceptorQueue.add(request); + } else { + RENEW_LOGGER + .error( + "acceptorQueueSize({}) reached the limit : connectId={}, requestType={}, requestBody={}", + acceptorQueue.size(), connectId, request.getRequestType(), + request.getRequestBody()); + } + } + + /** + * + * @param request + * @return + */ + private boolean isWriteRequest(WriteDataRequest request) { + return request.getRequestType() == WriteDataRequestType.PUBLISHER + || request.getRequestType() == WriteDataRequestType.UN_PUBLISHER; + } + + /** + * Ensure that the queue data is sent out + */ + private void flushQueue() { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("flushQueue: connectId={}", connectId); + } + + while (!acceptorQueue.isEmpty()) { + WriteDataRequest writeDataRequest = acceptorQueue.poll(); + if (writeDataRequest == null) { + break; + } + acceptorQueueSize.decrementAndGet(); + doHandle(writeDataRequest); + } + } + + private void doHandle(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doHandle: connectId={}, requestType={}, requestBody={}", connectId, + request.getRequestType(), request.getRequestBody()); + } + + switch (request.getRequestType()) { + case PUBLISHER: { + doPublishAsync(request); + } + break; + case UN_PUBLISHER: { + doUnPublishAsync(request); + } + break; + case CLIENT_OFF: { + doClientOffAsync(request); + } + break; + case RENEW_DATUM: { + if (renewAndSnapshotInSilence(request.getDataServerIP())) { + return; + } + doRenewAsync(request); + } + break; + case DATUM_SNAPSHOT: { + if (renewAndSnapshotInSilenceAndRefreshUpdateTime(request.getDataServerIP())) { + return; + } + halt(); + try { + doSnapshotAsync(request); + } finally { + resume(); + } + } + break; + default: + LOGGER.warn("Unknown request type, requestType={}, requestBody={}", connectId, + request.getRequestType(), request.getRequestBody()); + + } + } + + private void doRenewAsync(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doRenewAsync: connectId={}, requestType={}, requestBody={}", + connectId, request.getRequestType(), request.getRequestBody()); + } + + sendEvent(request.getRequestBody(), TaskType.RENEW_DATUM_TASK); + } + + private void doClientOffAsync(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doClientOffAsync: connectId={}, requestType={}, requestBody={}", + connectId, request.getRequestType(), request.getRequestBody()); + } + + String connectId = request.getConnectId(); + sendEvent(Lists.newArrayList(connectId), TaskType.CANCEL_DATA_TASK); + } + + private void doUnPublishAsync(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doUnPublishAsync: connectId={}, requestType={}, requestBody={}", + connectId, request.getRequestType(), request.getRequestBody()); + } + + sendEvent(request.getRequestBody(), TaskType.UN_PUBLISH_DATA_TASK); + } + + private void doPublishAsync(WriteDataRequest request) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("doPublishAsync: connectId={}, requestType={}, requestBody={}", + connectId, request.getRequestType(), request.getRequestBody()); + } + + sendEvent(request.getRequestBody(), TaskType.PUBLISH_DATA_TASK); + } + + private void sendEvent(Object eventObj, TaskType taskType) { + TaskEvent taskEvent = new TaskEvent(eventObj, taskType); + + //print but ignore if from renew module, cause renew request is too much + if (taskType != TaskType.RENEW_DATUM_TASK) { + taskLogger.info("send " + taskType + " taskEvent:{}", taskEvent); + } + + taskListenerManager.sendTaskEvent(taskEvent); + } + + private void doSnapshotAsync(WriteDataRequest request) { + RENEW_LOGGER.info( + "doSnapshotAsync: connectId={}, dataServerIP={}, requestType={}, requestBody={}", + connectId, request.getDataServerIP(), request.getRequestType(), + request.getRequestBody()); + + String connectId = (String) request.getRequestBody(); + DatumSnapshotRequest datumSnapshotRequest = renewService.getDatumSnapshotRequest(connectId, + request.getDataServerIP()); + if (datumSnapshotRequest != null) { + TaskEvent taskEvent = new TaskEvent(datumSnapshotRequest, TaskType.DATUM_SNAPSHOT_TASK); + taskListenerManager.sendTaskEvent(taskEvent); + } else { + RENEW_LOGGER + .info( + "datumSnapshotRequest is null when doSnapshotAsync: connectId={}, dataServerIP={}, requestType={}", + connectId, request.getDataServerIP(), request.getRequestType()); + } + + } + + /** + * In silence, do not renew and snapshot + */ + private boolean renewAndSnapshotInSilence(String dataServerIP) { + boolean renewAndSnapshotInSilence = System.currentTimeMillis() + - getLastUpdateTime(dataServerIP).get() < this.sessionServerConfig + .getRenewAndSnapshotSilentPeriodSec() * 1000L; + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug( + "renewAndSnapshotInSilence: connectId={}, renewAndSnapshotInSilence={}", connectId, + renewAndSnapshotInSilence); + } + return renewAndSnapshotInSilence; + } + + /** + * In silence, do not renew and snapshot + */ + private boolean renewAndSnapshotInSilenceAndRefreshUpdateTime(String dataServerIP) { + boolean renewAndSnapshotInSilence = System.currentTimeMillis() + - refreshUpdateTime(dataServerIP) < this.sessionServerConfig + .getRenewAndSnapshotSilentPeriodSec() * 1000L; + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER + .debug( + "renewAndSnapshotInSilenceAndRefreshUpdateTime: connectId={}, renewAndSnapshotInSilence={}", + connectId, renewAndSnapshotInSilence); + } + return renewAndSnapshotInSilence; + } + + private long refreshUpdateTime(String dataServerIP) { + AtomicLong lastUpdateTimestamp = getLastUpdateTime(dataServerIP); + return lastUpdateTimestamp.getAndSet(System.currentTimeMillis()); + } + + private AtomicLong getLastUpdateTime(String dataServerIP) { + AtomicLong lastUpdateTimestamp = lastUpdateTimestampMap.get(dataServerIP); + if (lastUpdateTimestamp == null) { + lastUpdateTimestamp = new AtomicLong(0); + AtomicLong _lastUpdateTimestamp = lastUpdateTimestampMap.putIfAbsent(dataServerIP, + lastUpdateTimestamp); + if (_lastUpdateTimestamp != null) { + lastUpdateTimestamp = _lastUpdateTimestamp; + } + } + return lastUpdateTimestamp; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataRequest.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataRequest.java new file mode 100644 index 000000000..0e71f8ab1 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/acceptor/WriteDataRequest.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.acceptor; + +/** + * + * @author kezhu.wukz + * @author shangyu.wh + * @version 1.0: WriteDataRequest.java, v 0.1 2019-06-06 18:42 shangyu.wh Exp $ + */ +public interface WriteDataRequest { + + /** + * The enum for request type + */ + enum WriteDataRequestType { + PUBLISHER, UN_PUBLISHER, CLIENT_OFF, RENEW_DATUM, DATUM_SNAPSHOT + } + + /** + * Gets request body. + * + * @return the request body + */ + T getRequestBody(); + + WriteDataRequestType getRequestType(); + + String getConnectId(); + + String getDataServerIP(); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/CommonConfig.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/CommonConfig.java index 71e4f81a2..7ae7a8cec 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/CommonConfig.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/CommonConfig.java @@ -16,11 +16,13 @@ */ package com.alipay.sofa.registry.server.session.bootstrap; -import org.springframework.beans.factory.annotation.Value; - import java.util.Collection; import java.util.Map; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.springframework.beans.factory.annotation.Value; + /** * * @author shangyu.wh @@ -85,4 +87,9 @@ public String getLocalRegion() { return localRegion; } + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } + } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerBootstrap.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerBootstrap.java index 87b01b6bb..3ed3279cd 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerBootstrap.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerBootstrap.java @@ -16,6 +16,21 @@ */ package com.alipay.sofa.registry.server.session.bootstrap; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.annotation.Resource; +import javax.ws.rs.Path; +import javax.ws.rs.ext.Provider; + +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.util.CollectionUtils; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.metaserver.FetchProvideDataRequest; @@ -31,27 +46,16 @@ import com.alipay.sofa.registry.remoting.Server; import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.remoting.exchange.NodeExchanger; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistManager; import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.node.NodeManagerFactory; import com.alipay.sofa.registry.server.session.node.RaftClientManager; import com.alipay.sofa.registry.server.session.node.SessionProcessIdGenerator; +import com.alipay.sofa.registry.server.session.registry.Registry; import com.alipay.sofa.registry.server.session.remoting.handler.AbstractClientHandler; import com.alipay.sofa.registry.server.session.remoting.handler.AbstractServerHandler; import com.alipay.sofa.registry.server.session.scheduler.ExecutorManager; import com.alipay.sofa.registry.task.batcher.TaskDispatchers; -import org.glassfish.jersey.server.ResourceConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.util.CollectionUtils; - -import javax.annotation.Resource; -import javax.ws.rs.Path; -import javax.ws.rs.ext.Provider; -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; /** * The type Session server bootstrap. @@ -99,6 +103,12 @@ public class SessionServerBootstrap { @Autowired private RaftClientManager raftClientManager; + @Autowired + private BlacklistManager blacklistManager; + + @Autowired + private Registry sessionRegistry; + private Server server; private Server httpServer; @@ -120,8 +130,10 @@ public class SessionServerBootstrap { /** * Do initialized. */ - public void doInitialized() { + public void start() { try { + LOGGER.info("the configuration items are as follows: " + sessionServerConfig.toString()); + initEnvironment(); startRaftClient(); @@ -260,6 +272,10 @@ private void connectMetaServer() { fetchStopPushSwitch(leaderUrl); + fetchEnableDataRenewSnapshot(leaderUrl); + + fetchBlackList(); + LOGGER.info("MetaServer connected {} server! Port:{}", size, sessionServerConfig.getMetaServerPort()); } @@ -312,6 +328,29 @@ private void fetchStopPushSwitch(URL leaderUrl) { } } + private void fetchEnableDataRenewSnapshot(URL leaderUrl) { + FetchProvideDataRequest fetchProvideDataRequest = new FetchProvideDataRequest( + ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT); + Object data = sendMetaRequest(fetchProvideDataRequest, leaderUrl); + if (data instanceof ProvideData) { + ProvideData provideData = (ProvideData) data; + if (provideData == null || provideData.getProvideData() == null + || provideData.getProvideData().getObject() == null) { + LOGGER + .info("Fetch enableDataRenewSnapshot but no data existed, current config not change!"); + return; + } + boolean enableDataRenewSnapshot = Boolean.parseBoolean((String) provideData + .getProvideData().getObject()); + LOGGER.info("Fetch enableDataRenewSnapshot {} success!", enableDataRenewSnapshot); + this.sessionRegistry.setEnableDataRenewSnapshot(enableDataRenewSnapshot); + } + } + + private void fetchBlackList() { + blacklistManager.load(); + } + private Object sendMetaRequest(Object request, URL leaderUrl) { Object ret; try { diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfig.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfig.java index 98668f574..d0c5277a4 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfig.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfig.java @@ -63,10 +63,30 @@ public interface SessionServerConfig { int getCancelDataTaskRetryTimes(); - int getCancelDataTaskRetryFirstDelay(); + long getCancelDataTaskRetryFirstDelay(); long getCancelDataTaskRetryIncrementDelay(); + int getPublishDataTaskRetryTimes(); + + long getPublishDataTaskRetryFirstDelay(); + + long getPublishDataTaskRetryIncrementDelay(); + + int getUnPublishDataTaskRetryTimes(); + + long getUnPublishDataTaskRetryFirstDelay(); + + long getUnPublishDataTaskRetryIncrementDelay(); + + int getDatumSnapshotTaskRetryTimes(); + + long getDatumSnapshotTaskRetryFirstDelay(); + + long getDatumSnapshotTaskRetryIncrementDelay(); + + int getRenewDatumTaskRetryTimes(); + int getDataChangeFetchTaskRetryTimes(); int getSubscriberRegisterFetchRetryTimes(); @@ -85,6 +105,12 @@ public interface SessionServerConfig { int getSchedulerConnectDataExpBackOffBound(); + int getSchedulerCleanInvalidClientTimeOut(); + + int getSchedulerCleanInvalidClientFirstDelay(); + + int getSchedulerCleanInvalidClientBackOffBound(); + int getAccessDataExecutorMinPoolSize(); int getAccessDataExecutorMaxPoolSize(); @@ -109,11 +135,11 @@ public interface SessionServerConfig { long getPushTaskExecutorKeepAliveTime(); - int getDisconnectClientExecutorMinPoolSize(); + int getConnectClientExecutorMinPoolSize(); - int getDisconnectClientExecutorMaxPoolSize(); + int getConnectClientExecutorMaxPoolSize(); - int getDisconnectClientExecutorQueueSize(); + int getConnectClientExecutorQueueSize(); int getDataChangeFetchTaskMaxBufferSize(); @@ -123,10 +149,26 @@ public interface SessionServerConfig { int getUserDataPushRetryWheelTicksDuration(); + int getUserDataPushRetryExecutorQueueSize(); + + int getUserDataPushRetryExecutorThreadSize(); + int getPushDataTaskRetryFirstDelay(); long getPushDataTaskRetryIncrementDelay(); + int getRenewDatumWheelTicksSize(); + + int getRenewDatumWheelTicksDuration(); + + int getRenewDatumWheelTaskDelaySec(); + + int getRenewDatumWheelTaskRandomFirstDelaySec(); + + String getBlacklistPubDataIdRegex(); + + String getBlacklistSubDataIdRegex(); + int getNumberOfReplicas(); boolean isStopPushSwitch(); @@ -140,4 +182,36 @@ public interface SessionServerConfig { boolean isInvalidForeverZone(String zoneId); boolean isInvalidIgnored(String dataId); + + int getRenewAndSnapshotSilentPeriodSec(); + + int getWriteDataAcceptorQueueSize(); + + int getDataNodeRetryExecutorQueueSize(); + + int getDataNodeRetryExecutorThreadSize(); + + int getRenewDatumWheelThreadSize(); + + int getRenewDatumWheelQueueSize(); + + long getPushTaskConfirmWaitTimeout(); + + int getPushTaskConfirmCheckWheelTicksSize(); + + int getPushTaskConfirmCheckWheelTicksDuration(); + + int getPushTaskConfirmCheckExecutorQueueSize(); + + int getPushTaskConfirmCheckExecutorThreadSize(); + + int getPublishDataExecutorMinPoolSize(); + + int getPublishDataExecutorMaxPoolSize(); + + int getPublishDataExecutorQueueSize(); + + long getPublishDataExecutorKeepAliveTime(); + + double getAccessLimitRate(); } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfigBean.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfigBean.java index 916c5d641..aba075070 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfigBean.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfigBean.java @@ -16,9 +16,10 @@ */ package com.alipay.sofa.registry.server.session.bootstrap; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -74,11 +75,37 @@ public class SessionServerConfigBean implements SessionServerConfig { private int schedulerConnectDataExpBackOffBound = 10; - private int cancelDataTaskRetryTimes = 5; + private int schedulerCleanInvalidClientTimeOut = 3; - private int cancelDataTaskRetryFirstDelay = 100; + private int schedulerCleanInvalidClientFirstDelay = 10; - private long cancelDataTaskRetryIncrementDelay = 200; + private int schedulerCleanInvalidClientBackOffBound = 5; + + private int cancelDataTaskRetryTimes = 2; + + private long cancelDataTaskRetryFirstDelay = 500; + + private long cancelDataTaskRetryIncrementDelay = 500; + + private int publishDataTaskRetryTimes = 2; + + private long publishDataTaskRetryFirstDelay = 3000; + + private long publishDataTaskRetryIncrementDelay = 5000; + + private int unPublishDataTaskRetryTimes = 2; + + private long unPublishDataTaskRetryFirstDelay = 3000; + + private long unPublishDataTaskRetryIncrementDelay = 5000; + + private int datumSnapshotTaskRetryTimes = 1; + + private long datumSnapshotTaskRetryFirstDelay = 5000; + + private long datumSnapshotTaskRetryIncrementDelay = 5000; + + private int renewDatumTaskRetryTimes = 1; private int dataChangeFetchTaskRetryTimes = 3; @@ -118,11 +145,11 @@ public class SessionServerConfigBean implements SessionServerConfig { private long dataChangeExecutorKeepAliveTime = 60; - private int disconnectClientExecutorMinPoolSize = 40; + private int connectClientExecutorMinPoolSize = 60; - private int disconnectClientExecutorMaxPoolSize = 200; + private int connectClientExecutorMaxPoolSize = 400; - private int disconnectClientExecutorQueueSize = 10000; + private int connectClientExecutorQueueSize = 10000; private int dataChangeFetchTaskMaxBufferSize = 1000000; @@ -140,10 +167,46 @@ public class SessionServerConfigBean implements SessionServerConfig { private int userDataPushRetryWheelTicksDuration = 100; + private int userDataPushRetryExecutorQueueSize = 1000000; + + private int userDataPushRetryExecutorThreadSize = 10; + + private int renewDatumWheelTicksSize = 2048; + + private int renewDatumWheelTicksDuration = 500; + + private int renewDatumWheelTaskDelaySec = 180; + + private int renewDatumWheelTaskRandomFirstDelaySec = 200; + + private int renewDatumWheelThreadSize = 10; + + private int renewDatumWheelQueueSize = 10000; + private int pushDataTaskRetryFirstDelay = 500; private long pushDataTaskRetryIncrementDelay = 500; + private long pushTaskConfirmWaitTimeout = 10000; + + private int pushTaskConfirmCheckWheelTicksSize = 1024; + + private int pushTaskConfirmCheckWheelTicksDuration = 100; + + private int pushTaskConfirmCheckExecutorQueueSize = 10000; + + private int pushTaskConfirmCheckExecutorThreadSize = 10; + + private int publishDataExecutorMinPoolSize = 100; + + private int publishDataExecutorMaxPoolSize = 400; + + private int publishDataExecutorQueueSize = 10000; + + private long publishDataExecutorKeepAliveTime = 60; + + private double accessLimitRate = 100000.0; + private String sessionServerRegion; private String sessionServerDataCenter; @@ -163,9 +226,17 @@ public class SessionServerConfigBean implements SessionServerConfig { private Pattern invalidIgnoreDataIdPattern = null; - private String pushEmptyDataDataIdPrefixes = ""; + private String blacklistPubDataIdRegex = ""; + + private String blacklistSubDataIdRegex = ""; + + private int renewAndSnapshotSilentPeriodSec = 20; - private Set pushEmptyDataDataIdPrefixesSet; + private int writeDataAcceptorQueueSize = 10000; + + private int dataNodeRetryExecutorQueueSize = 1000000; + + private int dataNodeRetryExecutorThreadSize = 100; //end config for enterprise version @@ -179,6 +250,230 @@ public SessionServerConfigBean(CommonConfig commonConfig) { this.commonConfig = commonConfig; } + /** + * Getter method for property renewDatumWheelThreadSize. + * + * @return property value of renewDatumWheelThreadSize + */ + public int getRenewDatumWheelThreadSize() { + return renewDatumWheelThreadSize; + } + + /** + * Setter method for property renewDatumWheelThreadSize . + * + * @param renewDatumWheelThreadSize value to be assigned to property renewDatumWheelThreadSize + */ + public void setRenewDatumWheelThreadSize(int renewDatumWheelThreadSize) { + this.renewDatumWheelThreadSize = renewDatumWheelThreadSize; + } + + /** + * Getter method for property renewDatumWheelQueueSize. + * + * @return property value of renewDatumWheelQueueSize + */ + public int getRenewDatumWheelQueueSize() { + return renewDatumWheelQueueSize; + } + + /** + * Setter method for property renewDatumWheelQueueSize . + * + * @param renewDatumWheelQueueSize value to be assigned to property renewDatumWheelQueueSize + */ + public void setRenewDatumWheelQueueSize(int renewDatumWheelQueueSize) { + this.renewDatumWheelQueueSize = renewDatumWheelQueueSize; + } + + /** + * Getter method for property userDataPushRetryExecutorQueueSize. + * + * @return property value of userDataPushRetryExecutorQueueSize + */ + @Override + public int getUserDataPushRetryExecutorQueueSize() { + return userDataPushRetryExecutorQueueSize; + } + + /** + * Setter method for property userDataPushRetryExecutorQueueSize . + * + * @param userDataPushRetryExecutorQueueSize value to be assigned to property userDataPushRetryExecutorQueueSize + */ + public void setUserDataPushRetryExecutorQueueSize(int userDataPushRetryExecutorQueueSize) { + this.userDataPushRetryExecutorQueueSize = userDataPushRetryExecutorQueueSize; + } + + /** + * Getter method for property userDataPushRetryExecutorThreadSize. + * + * @return property value of userDataPushRetryExecutorThreadSize + */ + @Override + public int getUserDataPushRetryExecutorThreadSize() { + return userDataPushRetryExecutorThreadSize; + } + + /** + * Setter method for property userDataPushRetryExecutorThreadSize . + * + * @param userDataPushRetryExecutorThreadSize value to be assigned to property userDataPushRetryExecutorThreadSize + */ + public void setUserDataPushRetryExecutorThreadSize(int userDataPushRetryExecutorThreadSize) { + this.userDataPushRetryExecutorThreadSize = userDataPushRetryExecutorThreadSize; + } + + /** + * Getter method for property dataNodeRetryExecutorThreadSize. + * + * @return property value of dataNodeRetryExecutorThreadSize + */ + @Override + public int getDataNodeRetryExecutorThreadSize() { + return dataNodeRetryExecutorThreadSize; + } + + /** + * Setter method for property dataNodeRetryExecutorThreadSize . + * + * @param dataNodeRetryExecutorThreadSize value to be assigned to property dataNodeRetryExecutorThreadSize + */ + public void setDataNodeRetryExecutorThreadSize(int dataNodeRetryExecutorThreadSize) { + this.dataNodeRetryExecutorThreadSize = dataNodeRetryExecutorThreadSize; + } + + /** + * Getter method for property dataNodeRetryExecutorQueueSize. + * + * @return property value of dataNodeRetryExecutorQueueSize + */ + @Override + public int getDataNodeRetryExecutorQueueSize() { + return dataNodeRetryExecutorQueueSize; + } + + /** + * Setter method for property dataNodeRetryExecutorQueueSize . + * + * @param dataNodeRetryExecutorQueueSize value to be assigned to property dataNodeRetryExecutorQueueSize + */ + public void setDataNodeRetryExecutorQueueSize(int dataNodeRetryExecutorQueueSize) { + this.dataNodeRetryExecutorQueueSize = dataNodeRetryExecutorQueueSize; + } + + /** + * Getter method for property writeDataAcceptorQueueSize. + * + * @return property value of writeDataAcceptorQueueSize + */ + public int getWriteDataAcceptorQueueSize() { + return writeDataAcceptorQueueSize; + } + + /** + * Setter method for property writeDataAcceptorQueueSize . + * + * @param writeDataAcceptorQueueSize value to be assigned to property writeDataAcceptorQueueSize + */ + public void setWriteDataAcceptorQueueSize(int writeDataAcceptorQueueSize) { + this.writeDataAcceptorQueueSize = writeDataAcceptorQueueSize; + } + + /** + * Getter method for property renewAndSnapshotSilentPeriodSec. + * + * @return property value of renewAndSnapshotSilentPeriodSec + */ + public int getRenewAndSnapshotSilentPeriodSec() { + return renewAndSnapshotSilentPeriodSec; + } + + /** + * Setter method for property renewAndSnapshotSilentPeriodSec . + * + * @param renewAndSnapshotSilentPeriodSec value to be assigned to property renewAndSnapshotSilentPeriodSec + */ + public void setRenewAndSnapshotSilentPeriodSec(int renewAndSnapshotSilentPeriodSec) { + this.renewAndSnapshotSilentPeriodSec = renewAndSnapshotSilentPeriodSec; + } + + /** + * Getter method for property publishDataTaskRetryTimes. + * + * @return property value of publishDataTaskRetryTimes + */ + @Override + public int getPublishDataTaskRetryTimes() { + return publishDataTaskRetryTimes; + } + + /** + * Setter method for property publishDataTaskRetryTimes . + * + * @param publishDataTaskRetryTimes value to be assigned to property publishDataTaskRetryTimes + */ + public void setPublishDataTaskRetryTimes(int publishDataTaskRetryTimes) { + this.publishDataTaskRetryTimes = publishDataTaskRetryTimes; + } + + /** + * Getter method for property unPublishDataTaskRetryTimes. + * + * @return property value of unPublishDataTaskRetryTimes + */ + @Override + public int getUnPublishDataTaskRetryTimes() { + return unPublishDataTaskRetryTimes; + } + + /** + * Setter method for property unPublishDataTaskRetryTimes . + * + * @param unPublishDataTaskRetryTimes value to be assigned to property unPublishDataTaskRetryTimes + */ + public void setUnPublishDataTaskRetryTimes(int unPublishDataTaskRetryTimes) { + this.unPublishDataTaskRetryTimes = unPublishDataTaskRetryTimes; + } + + /** + * Getter method for property datumSnapshotTaskRetryTimes. + * + * @return property value of datumSnapshotTaskRetryTimes + */ + @Override + public int getDatumSnapshotTaskRetryTimes() { + return datumSnapshotTaskRetryTimes; + } + + /** + * Setter method for property datumSnapshotTaskRetryTimes . + * + * @param datumSnapshotTaskRetryTimes value to be assigned to property datumSnapshotTaskRetryTimes + */ + public void setDatumSnapshotTaskRetryTimes(int datumSnapshotTaskRetryTimes) { + this.datumSnapshotTaskRetryTimes = datumSnapshotTaskRetryTimes; + } + + /** + * Getter method for property renewDatumTaskRetryTimes. + * + * @return property value of renewDatumTaskRetryTimes + */ + @Override + public int getRenewDatumTaskRetryTimes() { + return renewDatumTaskRetryTimes; + } + + /** + * Setter method for property renewDatumTaskRetryTimes . + * + * @param renewDatumTaskRetryTimes value to be assigned to property renewDatumTaskRetryTimes + */ + public void setRenewDatumTaskRetryTimes(int renewDatumTaskRetryTimes) { + this.renewDatumTaskRetryTimes = renewDatumTaskRetryTimes; + } + /** * Getter method for property serverPort. * @@ -337,19 +632,10 @@ public void setCancelDataTaskRetryTimes(int cancelDataTaskRetryTimes) { * @return property value of cancelDataTaskRetryFirstDelay */ @Override - public int getCancelDataTaskRetryFirstDelay() { + public long getCancelDataTaskRetryFirstDelay() { return cancelDataTaskRetryFirstDelay; } - /** - * Setter method for property cancelDataTaskRetryFirstDelay. - * - * @param cancelDataTaskRetryFirstDelay value to be assigned to property cancelDataTaskRetryFirstDelay - */ - public void setCancelDataTaskRetryFirstDelay(int cancelDataTaskRetryFirstDelay) { - this.cancelDataTaskRetryFirstDelay = cancelDataTaskRetryFirstDelay; - } - /** * Getter method for property cancelDataTaskRetryIncrementDelay. * @@ -369,6 +655,129 @@ public void setCancelDataTaskRetryIncrementDelay(long cancelDataTaskRetryIncreme this.cancelDataTaskRetryIncrementDelay = cancelDataTaskRetryIncrementDelay; } + /** + * Setter method for property cancelDataTaskRetryFirstDelay . + * + * @param cancelDataTaskRetryFirstDelay value to be assigned to property cancelDataTaskRetryFirstDelay + */ + public void setCancelDataTaskRetryFirstDelay(long cancelDataTaskRetryFirstDelay) { + this.cancelDataTaskRetryFirstDelay = cancelDataTaskRetryFirstDelay; + } + + /** + * Getter method for property publishDataTaskRetryFirstDelay. + * + * @return property value of publishDataTaskRetryFirstDelay + */ + @Override + public long getPublishDataTaskRetryFirstDelay() { + return publishDataTaskRetryFirstDelay; + } + + /** + * Setter method for property publishDataTaskRetryFirstDelay . + * + * @param publishDataTaskRetryFirstDelay value to be assigned to property publishDataTaskRetryFirstDelay + */ + public void setPublishDataTaskRetryFirstDelay(long publishDataTaskRetryFirstDelay) { + this.publishDataTaskRetryFirstDelay = publishDataTaskRetryFirstDelay; + } + + /** + * Getter method for property publishDataTaskRetryIncrementDelay. + * + * @return property value of publishDataTaskRetryIncrementDelay + */ + @Override + public long getPublishDataTaskRetryIncrementDelay() { + return publishDataTaskRetryIncrementDelay; + } + + /** + * Setter method for property publishDataTaskRetryIncrementDelay . + * + * @param publishDataTaskRetryIncrementDelay value to be assigned to property publishDataTaskRetryIncrementDelay + */ + public void setPublishDataTaskRetryIncrementDelay(long publishDataTaskRetryIncrementDelay) { + this.publishDataTaskRetryIncrementDelay = publishDataTaskRetryIncrementDelay; + } + + /** + * Getter method for property unPublishDataTaskRetryFirstDelay. + * + * @return property value of unPublishDataTaskRetryFirstDelay + */ + @Override + public long getUnPublishDataTaskRetryFirstDelay() { + return unPublishDataTaskRetryFirstDelay; + } + + /** + * Setter method for property unPublishDataTaskRetryFirstDelay . + * + * @param unPublishDataTaskRetryFirstDelay value to be assigned to property unPublishDataTaskRetryFirstDelay + */ + public void setUnPublishDataTaskRetryFirstDelay(long unPublishDataTaskRetryFirstDelay) { + this.unPublishDataTaskRetryFirstDelay = unPublishDataTaskRetryFirstDelay; + } + + /** + * Getter method for property unPublishDataTaskRetryIncrementDelay. + * + * @return property value of unPublishDataTaskRetryIncrementDelay + */ + @Override + public long getUnPublishDataTaskRetryIncrementDelay() { + return unPublishDataTaskRetryIncrementDelay; + } + + /** + * Setter method for property unPublishDataTaskRetryIncrementDelay . + * + * @param unPublishDataTaskRetryIncrementDelay value to be assigned to property unPublishDataTaskRetryIncrementDelay + */ + public void setUnPublishDataTaskRetryIncrementDelay(long unPublishDataTaskRetryIncrementDelay) { + this.unPublishDataTaskRetryIncrementDelay = unPublishDataTaskRetryIncrementDelay; + } + + /** + * Getter method for property datumSnapshotTaskRetryFirstDelay. + * + * @return property value of datumSnapshotTaskRetryFirstDelay + */ + @Override + public long getDatumSnapshotTaskRetryFirstDelay() { + return datumSnapshotTaskRetryFirstDelay; + } + + /** + * Setter method for property datumSnapshotTaskRetryFirstDelay . + * + * @param datumSnapshotTaskRetryFirstDelay value to be assigned to property datumSnapshotTaskRetryFirstDelay + */ + public void setDatumSnapshotTaskRetryFirstDelay(long datumSnapshotTaskRetryFirstDelay) { + this.datumSnapshotTaskRetryFirstDelay = datumSnapshotTaskRetryFirstDelay; + } + + /** + * Getter method for property datumSnapshotTaskRetryIncrementDelay. + * + * @return property value of datumSnapshotTaskRetryIncrementDelay + */ + @Override + public long getDatumSnapshotTaskRetryIncrementDelay() { + return datumSnapshotTaskRetryIncrementDelay; + } + + /** + * Setter method for property datumSnapshotTaskRetryIncrementDelay . + * + * @param datumSnapshotTaskRetryIncrementDelay value to be assigned to property datumSnapshotTaskRetryIncrementDelay + */ + public void setDatumSnapshotTaskRetryIncrementDelay(long datumSnapshotTaskRetryIncrementDelay) { + this.datumSnapshotTaskRetryIncrementDelay = datumSnapshotTaskRetryIncrementDelay; + } + /** * Getter method for property receivedDataMultiPushTaskRetryTimes. * @@ -782,6 +1191,60 @@ public void setSchedulerConnectDataExpBackOffBound(int schedulerConnectDataExpBa this.schedulerConnectDataExpBackOffBound = schedulerConnectDataExpBackOffBound; } + /** + * Getter method for property schedulerCleanInvolidClientTimeOut. + * + * @return property value of schedulerCleanInvolidClientTimeOut + */ + public int getSchedulerCleanInvalidClientTimeOut() { + return schedulerCleanInvalidClientTimeOut; + } + + /** + * Getter method for property schedulerCleanInvolidClientFirstDelay. + * + * @return property value of schedulerCleanInvolidClientFirstDelay + */ + public int getSchedulerCleanInvalidClientFirstDelay() { + return schedulerCleanInvalidClientFirstDelay; + } + + /** + * Getter method for property schedulerCleanInvolidClientBackOffBound. + * + * @return property value of schedulerCleanInvolidClientBackOffBound + */ + public int getSchedulerCleanInvalidClientBackOffBound() { + return schedulerCleanInvalidClientBackOffBound; + } + + /** + * Setter method for property schedulerCleanInvolidClientTimeOut. + * + * @param schedulerCleanInvalidClientTimeOut value to be assigned to property schedulerCleanInvolidClientTimeOut + */ + public void setSchedulerCleanInvalidClientTimeOut(int schedulerCleanInvalidClientTimeOut) { + this.schedulerCleanInvalidClientTimeOut = schedulerCleanInvalidClientTimeOut; + } + + /** + * Setter method for property schedulerCleanInvolidClientFirstDelay. + * + * @param schedulerCleanInvalidClientFirstDelay value to be assigned to property schedulerCleanInvolidClientFirstDelay + */ + public void setSchedulerCleanInvalidClientFirstDelay(int schedulerCleanInvalidClientFirstDelay) { + this.schedulerCleanInvalidClientFirstDelay = schedulerCleanInvalidClientFirstDelay; + } + + /** + * Setter method for property schedulerCleanInvolidClientBackOffBound. + * + * @param schedulerCleanInvalidClientBackOffBound value to be assigned to property schedulerCleanInvolidClientBackOffBound + */ + public void setSchedulerCleanInvalidClientBackOffBound(int schedulerCleanInvalidClientBackOffBound) { + this.schedulerCleanInvalidClientBackOffBound = schedulerCleanInvalidClientBackOffBound; + } + /** * Getter method for property stopPushSwitch. * @@ -904,10 +1367,6 @@ public void setAccessDataExecutorKeepAliveTime(long accessDataExecutorKeepAliveT this.accessDataExecutorKeepAliveTime = accessDataExecutorKeepAliveTime; } - public String getPushEmptyDataDataIdPrefixes() { - return pushEmptyDataDataIdPrefixes; - } - /** * Getter method for property dataChangeExecutorMinPoolSize. * @@ -984,15 +1443,6 @@ public void setDataChangeExecutorKeepAliveTime(long dataChangeExecutorKeepAliveT this.dataChangeExecutorKeepAliveTime = dataChangeExecutorKeepAliveTime; } - /** - * Setter method for property pushEmptyDataDataIdPrefixes. - * - * @param pushEmptyDataDataIdPrefixes value to be assigned to property pushEmptyDataDataIdPrefixes - */ - public void setPushEmptyDataDataIdPrefixes(String pushEmptyDataDataIdPrefixes) { - this.pushEmptyDataDataIdPrefixes = pushEmptyDataDataIdPrefixes; - } - /** * Getter method for property pushTaskExecutorMinPoolSize. * @@ -1069,29 +1519,6 @@ public void setPushTaskExecutorKeepAliveTime(long pushTaskExecutorKeepAliveTime) this.pushTaskExecutorKeepAliveTime = pushTaskExecutorKeepAliveTime; } - public Set getPushEmptyDataDataIdPrefixesSet() { - if (pushEmptyDataDataIdPrefixesSet == null || pushEmptyDataDataIdPrefixesSet.isEmpty()) { - Set s = new HashSet<>(); - String[] arr = pushEmptyDataDataIdPrefixes.split(";"); - for (String str : arr) { - if (str.trim().length() > 0) { - s.add(str); - } - } - pushEmptyDataDataIdPrefixesSet = Collections.unmodifiableSet(s); - } - return pushEmptyDataDataIdPrefixesSet; - } - - /** - * Setter method for property pushEmptyDataDataIdPrefixesSet. - * - * @param pushEmptyDataDataIdPrefixesSet value to be assigned to property pushEmptyDataDataIdPrefixesSet - */ - public void setPushEmptyDataDataIdPrefixesSet(Set pushEmptyDataDataIdPrefixesSet) { - this.pushEmptyDataDataIdPrefixesSet = pushEmptyDataDataIdPrefixesSet; - } - /** * Getter method for property defaultSessionExecutorMinPoolSize. * @@ -1147,60 +1574,57 @@ public void setDefaultSessionExecutorKeepAliveTime(long defaultSessionExecutorKe } /** - * Getter method for property disconnectClientExecutorMinPoolSize. + * Getter method for property connectClientExecutorMinPoolSize. * - * @return property value of disconnectClientExecutorMinPoolSize + * @return property value of connectClientExecutorMinPoolSize */ - @Override - public int getDisconnectClientExecutorMinPoolSize() { - return disconnectClientExecutorMinPoolSize; + public int getConnectClientExecutorMinPoolSize() { + return connectClientExecutorMinPoolSize; } /** - * Setter method for property disconnectClientExecutorMinPoolSize. + * Getter method for property connectClientExecutorMaxPoolSize. * - * @param disconnectClientExecutorMinPoolSize value to be assigned to property disconnectClientExecutorMinPoolSize + * @return property value of connectClientExecutorMaxPoolSize */ - public void setDisconnectClientExecutorMinPoolSize(int disconnectClientExecutorMinPoolSize) { - this.disconnectClientExecutorMinPoolSize = disconnectClientExecutorMinPoolSize; + public int getConnectClientExecutorMaxPoolSize() { + return connectClientExecutorMaxPoolSize; } /** - * Getter method for property disconnectClientExecutorMaxPoolSize. + * Getter method for property connectClientExecutorQueueSize. * - * @return property value of disconnectClientExecutorMaxPoolSize + * @return property value of connectClientExecutorQueueSize */ - @Override - public int getDisconnectClientExecutorMaxPoolSize() { - return disconnectClientExecutorMaxPoolSize; + public int getConnectClientExecutorQueueSize() { + return connectClientExecutorQueueSize; } /** - * Setter method for property disconnectClientExecutorMaxPoolSize. + * Setter method for property connectClientExecutorMinPoolSize. * - * @param disconnectClientExecutorMaxPoolSize value to be assigned to property disconnectClientExecutorMaxPoolSize + * @param connectClientExecutorMinPoolSize value to be assigned to property connectClientExecutorMinPoolSize */ - public void setDisconnectClientExecutorMaxPoolSize(int disconnectClientExecutorMaxPoolSize) { - this.disconnectClientExecutorMaxPoolSize = disconnectClientExecutorMaxPoolSize; + public void setConnectClientExecutorMinPoolSize(int connectClientExecutorMinPoolSize) { + this.connectClientExecutorMinPoolSize = connectClientExecutorMinPoolSize; } /** - * Getter method for property disconnectClientExecutorQueueSize. + * Setter method for property connectClientExecutorMaxPoolSize. * - * @return property value of disconnectClientExecutorQueueSize + * @param connectClientExecutorMaxPoolSize value to be assigned to property connectClientExecutorMaxPoolSize */ - @Override - public int getDisconnectClientExecutorQueueSize() { - return disconnectClientExecutorQueueSize; + public void setConnectClientExecutorMaxPoolSize(int connectClientExecutorMaxPoolSize) { + this.connectClientExecutorMaxPoolSize = connectClientExecutorMaxPoolSize; } /** - * Setter method for property disconnectClientExecutorQueueSize. + * Setter method for property connectClientExecutorQueueSize. * - * @param disconnectClientExecutorQueueSize value to be assigned to property disconnectClientExecutorQueueSize + * @param connectClientExecutorQueueSize value to be assigned to property connectClientExecutorQueueSize */ - public void setDisconnectClientExecutorQueueSize(int disconnectClientExecutorQueueSize) { - this.disconnectClientExecutorQueueSize = disconnectClientExecutorQueueSize; + public void setConnectClientExecutorQueueSize(int connectClientExecutorQueueSize) { + this.connectClientExecutorQueueSize = connectClientExecutorQueueSize; } /** @@ -1308,6 +1732,78 @@ public long getPushDataTaskRetryIncrementDelay() { return pushDataTaskRetryIncrementDelay; } + /** + * Getter method for property renewDatumWheelTicksSize. + * + * @return property value of renewDatumWheelTicksSize + */ + public int getRenewDatumWheelTicksSize() { + return renewDatumWheelTicksSize; + } + + /** + * Getter method for property renewDatumWheelTicksDuration. + * + * @return property value of renewDatumWheelTicksDuration + */ + public int getRenewDatumWheelTicksDuration() { + return renewDatumWheelTicksDuration; + } + + /** + * Getter method for property renewDatumWheelTaskDelaySec. + * + * @return property value of renewDatumWheelTaskDelaySec + */ + public int getRenewDatumWheelTaskDelaySec() { + return renewDatumWheelTaskDelaySec; + } + + /** + * Setter method for property renewDatumWheelTaskDelaySec . + * + * @param renewDatumWheelTaskDelaySec value to be assigned to property renewDatumWheelTaskDelaySec + */ + public void setRenewDatumWheelTaskDelaySec(int renewDatumWheelTaskDelaySec) { + this.renewDatumWheelTaskDelaySec = renewDatumWheelTaskDelaySec; + } + + /** + * Getter method for property renewDatumWheelTaskRandomFirstDelaySec. + * + * @return property value of renewDatumWheelTaskRandomFirstDelaySec + */ + public int getRenewDatumWheelTaskRandomFirstDelaySec() { + return renewDatumWheelTaskRandomFirstDelaySec; + } + + /** + * Setter method for property renewDatumWheelTaskRandomFirstDelaySec . + * + * @param renewDatumWheelTaskRandomFirstDelaySec value to be assigned to property renewDatumWheelTaskRandomFirstDelaySec + */ + public void setRenewDatumWheelTaskRandomFirstDelaySec(int renewDatumWheelTaskRandomFirstDelaySec) { + this.renewDatumWheelTaskRandomFirstDelaySec = renewDatumWheelTaskRandomFirstDelaySec; + } + + /** + * Setter method for property renewDatumWheelTicksSize. + * + * @param renewDatumWheelTicksSize value to be assigned to property renewDatumWheelTicksSize + */ + public void setRenewDatumWheelTicksSize(int renewDatumWheelTicksSize) { + this.renewDatumWheelTicksSize = renewDatumWheelTicksSize; + } + + /** + * Setter method for property renewDatumWheelTicksDuration. + * + * @param renewDatumWheelTicksDuration value to be assigned to property renewDatumWheelTicksDuration + */ + public void setRenewDatumWheelTicksDuration(int renewDatumWheelTicksDuration) { + this.renewDatumWheelTicksDuration = renewDatumWheelTicksDuration; + } + /** * Setter method for property pushDataTaskRetryIncrementDelay. * @@ -1317,6 +1813,222 @@ public void setPushDataTaskRetryIncrementDelay(long pushDataTaskRetryIncrementDe this.pushDataTaskRetryIncrementDelay = pushDataTaskRetryIncrementDelay; } + /** + * Getter method for property blacklistPubDataIdRegex. + * + * @return property value of blacklistPubDataIdRegex + */ + public String getBlacklistPubDataIdRegex() { + return blacklistPubDataIdRegex; + } + + /** + * Getter method for property blacklistSubDataIdRegex. + * + * @return property value of blacklistSubDataIdRegex + */ + public String getBlacklistSubDataIdRegex() { + return blacklistSubDataIdRegex; + } + + /** + * Setter method for property blacklistPubDataIdRegex. + * + * @param blacklistPubDataIdRegex value to be assigned to property blacklistPubDataIdRegex + */ + public void setBlacklistPubDataIdRegex(String blacklistPubDataIdRegex) { + this.blacklistPubDataIdRegex = blacklistPubDataIdRegex; + } + + /** + * Setter method for property blacklistSubDataIdRegex. + * + * @param blacklistSubDataIdRegex value to be assigned to property blacklistSubDataIdRegex + */ + public void setBlacklistSubDataIdRegex(String blacklistSubDataIdRegex) { + this.blacklistSubDataIdRegex = blacklistSubDataIdRegex; + } + + /** + * Getter method for property pushTaskConfirmWaitTimeout. + * + * @return property value of pushTaskConfirmWaitTimeout + */ + public long getPushTaskConfirmWaitTimeout() { + return pushTaskConfirmWaitTimeout; + } + + /** + * Setter method for property pushTaskConfirmWaitTimeout. + * + * @param pushTaskConfirmWaitTimeout value to be assigned to property pushTaskConfirmWaitTimeout + */ + public void setPushTaskConfirmWaitTimeout(long pushTaskConfirmWaitTimeout) { + this.pushTaskConfirmWaitTimeout = pushTaskConfirmWaitTimeout; + } + + /** + * Getter method for property pushTaskConfirmCheckWheelTicksSize. + * + * @return property value of pushTaskConfirmCheckWheelTicksSize + */ + public int getPushTaskConfirmCheckWheelTicksSize() { + return pushTaskConfirmCheckWheelTicksSize; + } + + /** + * Getter method for property pushTaskConfirmCheckWheelTicksDuration. + * + * @return property value of pushTaskConfirmCheckWheelTicksDuration + */ + public int getPushTaskConfirmCheckWheelTicksDuration() { + return pushTaskConfirmCheckWheelTicksDuration; + } + + /** + * Getter method for property pushTaskConfirmCheckExecutorQueueSize. + * + * @return property value of pushTaskConfirmCheckExecutorQueueSize + */ + public int getPushTaskConfirmCheckExecutorQueueSize() { + return pushTaskConfirmCheckExecutorQueueSize; + } + + /** + * Getter method for property pushTaskConfirmCheckExecutorThreadSize. + * + * @return property value of pushTaskConfirmCheckExecutorThreadSize + */ + public int getPushTaskConfirmCheckExecutorThreadSize() { + return pushTaskConfirmCheckExecutorThreadSize; + } + + /** + * Setter method for property pushTaskConfirmCheckWheelTicksSize. + * + * @param pushTaskConfirmCheckWheelTicksSize value to be assigned to property pushTaskConfirmCheckWheelTicksSize + */ + public void setPushTaskConfirmCheckWheelTicksSize(int pushTaskConfirmCheckWheelTicksSize) { + this.pushTaskConfirmCheckWheelTicksSize = pushTaskConfirmCheckWheelTicksSize; + } + + /** + * Setter method for property pushTaskConfirmCheckWheelTicksDuration. + * + * @param pushTaskConfirmCheckWheelTicksDuration value to be assigned to property pushTaskConfirmCheckWheelTicksDuration + */ + public void setPushTaskConfirmCheckWheelTicksDuration(int pushTaskConfirmCheckWheelTicksDuration) { + this.pushTaskConfirmCheckWheelTicksDuration = pushTaskConfirmCheckWheelTicksDuration; + } + + /** + * Setter method for property pushTaskConfirmCheckExecutorQueueSize. + * + * @param pushTaskConfirmCheckExecutorQueueSize value to be assigned to property pushTaskConfirmCheckExecutorQueueSize + */ + public void setPushTaskConfirmCheckExecutorQueueSize(int pushTaskConfirmCheckExecutorQueueSize) { + this.pushTaskConfirmCheckExecutorQueueSize = pushTaskConfirmCheckExecutorQueueSize; + } + + /** + * Setter method for property pushTaskConfirmCheckExecutorThreadSize. + * + * @param pushTaskConfirmCheckExecutorThreadSize value to be assigned to property pushTaskConfirmCheckExecutorThreadSize + */ + public void setPushTaskConfirmCheckExecutorThreadSize(int pushTaskConfirmCheckExecutorThreadSize) { + this.pushTaskConfirmCheckExecutorThreadSize = pushTaskConfirmCheckExecutorThreadSize; + } + + /** + * Getter method for property publishDataExecutorMinPoolSize. + * + * @return property value of publishDataExecutorMinPoolSize + */ + public int getPublishDataExecutorMinPoolSize() { + return publishDataExecutorMinPoolSize; + } + + /** + * Getter method for property publishDataExecutorMaxPoolSize. + * + * @return property value of publishDataExecutorMaxPoolSize + */ + public int getPublishDataExecutorMaxPoolSize() { + return publishDataExecutorMaxPoolSize; + } + + /** + * Getter method for property publishDataExecutorQueueSize. + * + * @return property value of publishDataExecutorQueueSize + */ + public int getPublishDataExecutorQueueSize() { + return publishDataExecutorQueueSize; + } + + /** + * Getter method for property publishDataExecutorKeepAliveTime. + * + * @return property value of publishDataExecutorKeepAliveTime + */ + public long getPublishDataExecutorKeepAliveTime() { + return publishDataExecutorKeepAliveTime; + } + + /** + * Setter method for property publishDataExecutorMinPoolSize. + * + * @param publishDataExecutorMinPoolSize value to be assigned to property publishDataExecutorMinPoolSize + */ + public void setPublishDataExecutorMinPoolSize(int publishDataExecutorMinPoolSize) { + this.publishDataExecutorMinPoolSize = publishDataExecutorMinPoolSize; + } + + /** + * Setter method for property publishDataExecutorMaxPoolSize. + * + * @param publishDataExecutorMaxPoolSize value to be assigned to property publishDataExecutorMaxPoolSize + */ + public void setPublishDataExecutorMaxPoolSize(int publishDataExecutorMaxPoolSize) { + this.publishDataExecutorMaxPoolSize = publishDataExecutorMaxPoolSize; + } + + /** + * Setter method for property publishDataExecutorQueueSize. + * + * @param publishDataExecutorQueueSize value to be assigned to property publishDataExecutorQueueSize + */ + public void setPublishDataExecutorQueueSize(int publishDataExecutorQueueSize) { + this.publishDataExecutorQueueSize = publishDataExecutorQueueSize; + } + + /** + * Setter method for property publishDataExecutorKeepAliveTime. + * + * @param publishDataExecutorKeepAliveTime value to be assigned to property publishDataExecutorKeepAliveTime + */ + public void setPublishDataExecutorKeepAliveTime(long publishDataExecutorKeepAliveTime) { + this.publishDataExecutorKeepAliveTime = publishDataExecutorKeepAliveTime; + } + + /** + * Getter method for property accessLimitRate. + * + * @return property value of accessLimitRate + */ + public double getAccessLimitRate() { + return accessLimitRate; + } + + /** + * Setter method for property accessLimitRate. + * + * @param accessLimitRate value to be assigned to property accessLimitRate + */ + public void setAccessLimitRate(double accessLimitRate) { + this.accessLimitRate = accessLimitRate; + } + @Override public boolean isInvalidForeverZone(String zoneId) { @@ -1348,4 +2060,9 @@ public boolean isInvalidIgnored(String dataId) { public static int cpus() { return Runtime.getRuntime().availableProcessors(); } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfiguration.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfiguration.java index 63dff75e1..1faa2628c 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfiguration.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerConfiguration.java @@ -20,20 +20,37 @@ import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.remoting.exchange.NodeExchanger; import com.alipay.sofa.registry.remoting.jersey.exchange.JerseyExchange; +import com.alipay.sofa.registry.server.session.acceptor.WriteDataAcceptor; +import com.alipay.sofa.registry.server.session.acceptor.WriteDataAcceptorImpl; import com.alipay.sofa.registry.server.session.cache.CacheGenerator; import com.alipay.sofa.registry.server.session.cache.CacheService; import com.alipay.sofa.registry.server.session.cache.DatumCacheGenerator; import com.alipay.sofa.registry.server.session.cache.SessionCacheService; +import com.alipay.sofa.registry.server.session.filter.DataIdMatchStrategy; +import com.alipay.sofa.registry.server.session.filter.IPMatchStrategy; +import com.alipay.sofa.registry.server.session.filter.ProcessFilter; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistManager; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistManagerImpl; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistMatchProcessFilter; +import com.alipay.sofa.registry.server.session.filter.blacklist.DefaultDataIdMatchStrategy; +import com.alipay.sofa.registry.server.session.filter.blacklist.DefaultIPMatchStrategy; +import com.alipay.sofa.registry.server.session.limit.AccessLimitService; +import com.alipay.sofa.registry.server.session.limit.AccessLimitServiceImpl; import com.alipay.sofa.registry.server.session.listener.CancelDataTaskListener; import com.alipay.sofa.registry.server.session.listener.DataChangeFetchCloudTaskListener; import com.alipay.sofa.registry.server.session.listener.DataChangeFetchTaskListener; import com.alipay.sofa.registry.server.session.listener.DataPushTaskListener; +import com.alipay.sofa.registry.server.session.listener.DatumSnapshotTaskListener; import com.alipay.sofa.registry.server.session.listener.ProvideDataChangeFetchTaskListener; +import com.alipay.sofa.registry.server.session.listener.PublishDataTaskListener; import com.alipay.sofa.registry.server.session.listener.ReceivedConfigDataPushTaskListener; import com.alipay.sofa.registry.server.session.listener.ReceivedDataMultiPushTaskListener; +import com.alipay.sofa.registry.server.session.listener.RenewDatumTaskListener; import com.alipay.sofa.registry.server.session.listener.SessionRegisterDataTaskListener; import com.alipay.sofa.registry.server.session.listener.SubscriberMultiFetchTaskListener; +import com.alipay.sofa.registry.server.session.listener.SubscriberPushEmptyTaskListener; import com.alipay.sofa.registry.server.session.listener.SubscriberRegisterFetchTaskListener; +import com.alipay.sofa.registry.server.session.listener.UnPublishDataTaskListener; import com.alipay.sofa.registry.server.session.listener.WatcherRegisterFetchTaskListener; import com.alipay.sofa.registry.server.session.node.DataNodeManager; import com.alipay.sofa.registry.server.session.node.MetaNodeManager; @@ -70,6 +87,8 @@ import com.alipay.sofa.registry.server.session.remoting.handler.SubscriberHandler; import com.alipay.sofa.registry.server.session.remoting.handler.SyncConfigHandler; import com.alipay.sofa.registry.server.session.remoting.handler.WatcherHandler; +import com.alipay.sofa.registry.server.session.renew.DefaultRenewService; +import com.alipay.sofa.registry.server.session.renew.RenewService; import com.alipay.sofa.registry.server.session.resource.ClientsOpenResource; import com.alipay.sofa.registry.server.session.resource.HealthResource; import com.alipay.sofa.registry.server.session.resource.SessionDigestResource; @@ -104,6 +123,11 @@ import com.alipay.sofa.registry.server.session.strategy.impl.DefaultSubscriberRegisterFetchTaskStrategy; import com.alipay.sofa.registry.server.session.strategy.impl.DefaultSyncConfigHandlerStrategy; import com.alipay.sofa.registry.server.session.strategy.impl.DefaultWatcherHandlerStrategy; +import com.alipay.sofa.registry.server.session.wrapper.AccessLimitWrapperInterceptor; +import com.alipay.sofa.registry.server.session.wrapper.BlacklistWrapperInterceptor; +import com.alipay.sofa.registry.server.session.wrapper.ClientCheckWrapperInterceptor; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInterceptor; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInterceptorManager; import com.alipay.sofa.registry.task.batcher.TaskProcessor; import com.alipay.sofa.registry.task.listener.DefaultTaskListenerManager; import com.alipay.sofa.registry.task.listener.TaskListener; @@ -307,6 +331,7 @@ public HealthResource healthResource() { public ClientsOpenResource clientsOpenResource() { return new ClientsOpenResource(); } + } @Configuration @@ -502,12 +527,49 @@ public TaskListener receivedConfigDataPushTaskListener(TaskListenerManager taskL } @Bean + @ConditionalOnMissingBean(name = "cancelDataTaskListener") public TaskListener cancelDataTaskListener(TaskListenerManager taskListenerManager) { TaskListener taskListener = new CancelDataTaskListener(); taskListenerManager.addTaskListener(taskListener); return taskListener; } + @Bean + public TaskListener datumSnapshotTaskListener(TaskListenerManager taskListenerManager) { + TaskListener taskListener = new DatumSnapshotTaskListener(); + taskListenerManager.addTaskListener(taskListener); + return taskListener; + } + + @Bean + public TaskListener publishDataTaskListener(TaskListenerManager taskListenerManager) { + TaskListener taskListener = new PublishDataTaskListener(); + taskListenerManager.addTaskListener(taskListener); + return taskListener; + } + + @Bean + public TaskListener renewDatumTaskListener(TaskListenerManager taskListenerManager) { + TaskListener taskListener = new RenewDatumTaskListener(); + taskListenerManager.addTaskListener(taskListener); + return taskListener; + } + + @Bean + public TaskListener unPublishDataTaskListener(TaskListenerManager taskListenerManager) { + TaskListener taskListener = new UnPublishDataTaskListener(); + taskListenerManager.addTaskListener(taskListener); + return taskListener; + } + + @Bean + @ConditionalOnMissingBean(name = "subscriberPushEmptyTaskListener") + public TaskListener subscriberPushEmptyTaskListener(TaskListenerManager taskListenerManager) { + TaskListener taskListener = new SubscriberPushEmptyTaskListener(); + taskListenerManager.addTaskListener(taskListener); + return taskListener; + } + @Bean public TaskListenerManager taskListenerManager() { return new DefaultTaskListenerManager(); @@ -602,4 +664,78 @@ public ReceivedConfigDataPushTaskStrategy receivedConfigDataPushTaskStrategy() { return new DefaultReceivedConfigDataPushTaskStrategy(); } } + + @Configuration + public static class AccessLimitServiceConfiguration { + @Bean + public AccessLimitService accessLimitService(SessionServerConfig sessionServerConfig) { + return new AccessLimitServiceImpl(sessionServerConfig); + } + } + + @Configuration + public static class SessionFilterConfiguration { + + @Bean + public IPMatchStrategy ipMatchStrategy() { + return new DefaultIPMatchStrategy(); + } + + @Bean + public DataIdMatchStrategy dataIdMatchStrategy() { + return new DefaultDataIdMatchStrategy(); + } + + @Bean + @ConditionalOnMissingBean + public ProcessFilter processFilter() { + return new BlacklistMatchProcessFilter(); + } + + @Bean + public BlacklistManager blacklistManager() { + return new BlacklistManagerImpl(); + } + + @Bean + public WrapperInterceptorManager wrapperInterceptorManager() { + return new WrapperInterceptorManager(); + } + + @Bean + public WrapperInterceptor clientCheckWrapperInterceptor(WrapperInterceptorManager wrapperInterceptorManager) { + ClientCheckWrapperInterceptor clientCheckWrapperInterceptor = new ClientCheckWrapperInterceptor(); + wrapperInterceptorManager.addInterceptor(clientCheckWrapperInterceptor); + return clientCheckWrapperInterceptor; + } + + @Bean + public WrapperInterceptor blacklistWrapperInterceptor(WrapperInterceptorManager wrapperInterceptorManager) { + BlacklistWrapperInterceptor blacklistWrapperInterceptor = new BlacklistWrapperInterceptor(); + wrapperInterceptorManager.addInterceptor(blacklistWrapperInterceptor); + return blacklistWrapperInterceptor; + } + + @Bean + public WrapperInterceptor accessLimitWrapperInterceptor(WrapperInterceptorManager wrapperInterceptorManager) { + AccessLimitWrapperInterceptor accessLimitWrapperInterceptor = new AccessLimitWrapperInterceptor(); + wrapperInterceptorManager.addInterceptor(accessLimitWrapperInterceptor); + return accessLimitWrapperInterceptor; + } + + } + + @Configuration + public static class SessionRenewDatumConfiguration { + + @Bean + public WriteDataAcceptor writeDataAcceptor() { + return new WriteDataAcceptorImpl(); + } + + @Bean + public RenewService renewService() { + return new DefaultRenewService(); + } + } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerInitializer.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerInitializer.java index 163a152da..3d798072a 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerInitializer.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/bootstrap/SessionServerInitializer.java @@ -16,12 +16,13 @@ */ package com.alipay.sofa.registry.server.session.bootstrap; -import com.alipay.sofa.registry.log.Logger; -import com.alipay.sofa.registry.log.LoggerFactory; +import java.util.concurrent.atomic.AtomicBoolean; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.SmartLifecycle; -import java.util.concurrent.atomic.AtomicBoolean; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; /** * SmartLifecycle for SessionServerBootstrap @@ -46,7 +47,7 @@ public boolean isAutoStartup() { @Override public void start() { try { - sessionServerBootstrap.doInitialized(); + sessionServerBootstrap.start(); LOGGER.info("Started SessionServer"); SessionServerInitializer.this.running.set(true); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheAccessException.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheAccessException.java new file mode 100644 index 000000000..7d43cbf65 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheAccessException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.cache; + +/** + * exception inner cache, e.g. remote invoke error + * @author kezhu.wukz + * @version $Id: CacheAccessException.java, v 0.1 2019-09-02 17:55 kezhu.wukz Exp $ + */ +public class CacheAccessException extends Exception { + public CacheAccessException() { + } + + public CacheAccessException(String message) { + super(message); + } + + public CacheAccessException(String message, Throwable cause) { + super(message, cause); + } + + public CacheAccessException(Throwable cause) { + super(cause); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheService.java index 6b95977ab..30c791f14 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheService.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/CacheService.java @@ -30,9 +30,9 @@ public interface CacheService { * @param key * @return */ - Value getValue(Key key); + Value getValue(Key key) throws CacheAccessException; - Map getValues(final Iterable keys); + Map getValues(final Iterable keys) throws CacheAccessException; /** * invalidate cache by keys diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/SessionCacheService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/SessionCacheService.java index ba5c1aab3..65f6bb842 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/SessionCacheService.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/cache/SessionCacheService.java @@ -16,17 +16,17 @@ */ package com.alipay.sofa.registry.server.session.cache; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; /** * @@ -84,23 +84,25 @@ private Value generatePayload(Key key) { } @Override - public Value getValue(final Key key) { + public Value getValue(final Key key) throws CacheAccessException { Value payload = null; try { payload = readWriteCacheMap.get(key); - } catch (Throwable t) { - LOGGER.error("Cannot get value for key :" + key, t); + } catch (Throwable e) { + String msg = "Cannot get value for key is:" + key; + throw new CacheAccessException(msg, e); } return payload; } @Override - public Map getValues(final Iterable keys) { + public Map getValues(final Iterable keys) throws CacheAccessException { Map valueMap = null; try { valueMap = readWriteCacheMap.getAll(keys); - } catch (ExecutionException e) { - LOGGER.error("Cannot get value for keys :" + keys, e); + } catch (Throwable e) { + String msg = "Cannot get value for keys are:" + keys; + throw new CacheAccessException(msg, e); } return valueMap; } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/converter/ReceivedDataConverter.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/converter/ReceivedDataConverter.java index 5280cc0a5..70fcc9f15 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/converter/ReceivedDataConverter.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/converter/ReceivedDataConverter.java @@ -16,6 +16,13 @@ */ package com.alipay.sofa.registry.server.session.converter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Predicate; + import com.alipay.sofa.registry.common.model.ServerDataBox; import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -28,13 +35,7 @@ import com.alipay.sofa.registry.core.model.ScopeEnum; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Predicate; +import com.alipay.sofa.registry.util.DatumVersionUtil; /** * The type Received data converter. @@ -173,7 +174,7 @@ public static ReceivedData getReceivedDataMulti(Map datums, Scope String regionLocal = subscriber.getCell(); receivedData.setLocalZone(regionLocal); - receivedData.setVersion(System.currentTimeMillis()); + receivedData.setVersion(DatumVersionUtil.nextId()); Map> swizzMap = new HashMap<>(); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/DataIdMatchStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/DataIdMatchStrategy.java new file mode 100644 index 000000000..4f06c85e1 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/DataIdMatchStrategy.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter; + +import java.util.function.Supplier; + +/** + * + * @author shangyu.wh + * @version 1.0: DataIdMatchStrategy.java, v 0.1 2019-06-19 22:12 shangyu.wh Exp $ + */ +public interface DataIdMatchStrategy { + + boolean match(String dataId, Supplier getOperatorType); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/IPMatchStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/IPMatchStrategy.java new file mode 100644 index 000000000..76697a5af --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/IPMatchStrategy.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter; + +import java.util.function.Supplier; + +/** + * + * @author shangyu.wh + * @version 1.0: IPMatchStrategy.java, v 0.1 2019-06-19 22:14 shangyu.wh Exp $ + */ +public interface IPMatchStrategy { + + boolean match(String IP, Supplier getOperatorType); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/ProcessFilter.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/ProcessFilter.java new file mode 100644 index 000000000..040db92c5 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/ProcessFilter.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter; + +/** + * + * @author shangyu.wh + * @version 1.0: ProcessFilter.java, v 0.1 2019-06-19 17:01 shangyu.wh Exp $ + */ +public interface ProcessFilter { + + boolean match(T input); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConfig.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConfig.java new file mode 100644 index 000000000..7e63e6bd2 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConfig.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import java.io.Serializable; +import java.util.List; + +/** + * + * @author shangyu.wh + * @version 1.0: BlacklistConfig.java, v 0.1 2019-06-19 17:23 shangyu.wh Exp $ + */ +public class BlacklistConfig implements Serializable { + + /** UID*/ + private static final long serialVersionUID = -7607561981062791932L; + + /** blacklist type */ + private String type; + + /** match type */ + @SuppressWarnings("rawtypes") + private List matchTypes; + + /** + * Getter method for property type. + * + * @return property value of type + */ + public String getType() { + return type; + } + + /** + * Setter method for property type. + * + * @param type value to be assigned to property type + */ + public void setType(String type) { + this.type = type; + } + + /** + * Getter method for property matchTypes. + * + * @return property value of matchTypes + */ + @SuppressWarnings("rawtypes") + public List getMatchTypes() { + return matchTypes; + } + + /** + * Setter method for property matchTypes. + * + * @param matchTypes value to be assigned to property matchTypes + */ + @SuppressWarnings("rawtypes") + public void setMatchTypes(List matchTypes) { + this.matchTypes = matchTypes; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConstants.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConstants.java new file mode 100644 index 000000000..c5530f91d --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistConstants.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +/** + * + * @author shangyu.wh + * @version 1.0: BlacklistConstants.java, v 0.1 2019-06-19 17:56 shangyu.wh Exp $ + */ +public class BlacklistConstants { + + //*********************** Blacklist type ***********************// + /** forbidden pub */ + public static final String FORBIDDEN_PUB = "FORBIDDEN_PUB"; + + /** forbidden sub by prefix */ + public static final String FORBIDDEN_SUB_BY_PREFIX = "FORBIDDEN_SUB_BY_PREFIX"; + + //*********************** match type ***********************// + + /** match full ip */ + public static final String IP_FULL = "IP_FULL"; +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManager.java new file mode 100644 index 000000000..cf9a9733e --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManager.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author shangyu.wh + * @version 1.0: BlacklistManager.java, v 0.1 2019-06-19 18:27 shangyu.wh Exp $ + */ +public interface BlacklistManager { + /** + * load list first + */ + void load(); + + /** + * get list + * @return + */ + List getBlacklistConfigList(); + + /** + * set list + * @param blacklistConfigList + */ + void setBlacklistConfigList(List blacklistConfigList); + + /** + * convert blacklist map to blacklist config list + * @param config + * @return + * blacklistConfigMap key:blacklist type + * Map> key:MatchType + * set:match patterns + */ + Map>> convertBlacklistConfig(String config); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManagerImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManagerImpl.java new file mode 100644 index 000000000..f9ace0d5d --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistManagerImpl.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.metaserver.FetchProvideDataRequest; +import com.alipay.sofa.registry.common.model.metaserver.ProvideData; +import com.alipay.sofa.registry.common.model.store.URL; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.remoting.exchange.NodeExchanger; +import com.alipay.sofa.registry.remoting.exchange.message.Request; +import com.alipay.sofa.registry.remoting.exchange.message.Response; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.node.RaftClientManager; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * + * @author shangyu.wh + * @version 1.0: BlacklistManagerImpl.java, v 0.1 2019-06-19 18:30 shangyu.wh Exp $ + */ +public class BlacklistManagerImpl implements BlacklistManager { + + private static final Logger LOGGER = LoggerFactory + .getLogger(BlacklistManagerImpl.class); + + private static final Logger EXCHANGE_LOGGER = LoggerFactory.getLogger("SESSION-EXCHANGE"); + + @Autowired + private SessionServerConfig sessionServerConfig; + + @Autowired + protected NodeExchanger metaNodeExchanger; + + @Autowired + protected RaftClientManager raftClientManager; + + private List blacklistConfigList = new ArrayList(); + + @Override + public void load() { + fetchStopPushSwitch(); + } + + @Override + public List getBlacklistConfigList() { + return blacklistConfigList; + } + + @Override + public void setBlacklistConfigList(List blacklistConfigList) { + this.blacklistConfigList = blacklistConfigList; + } + + private void fetchStopPushSwitch() { + + Object ret = sendMetaRequest(); + if (ret instanceof ProvideData) { + ProvideData provideData = (ProvideData) ret; + if (provideData.getProvideData() == null + || provideData.getProvideData().getObject() == null) { + LOGGER.info("Fetch session blacklist no data existed,current config not change!"); + return; + } + String data = (String) provideData.getProvideData().getObject(); + if (data != null) { + convertBlacklistConfig(data); + EXCHANGE_LOGGER.info("Fetch session blacklist data switch {} success!", data); + } else { + LOGGER.info("Fetch session blacklist data null,current config not change!"); + } + } else { + LOGGER.info("Fetch session blacklist data null,config not change!"); + } + } + + private Object sendMetaRequest() { + try { + Request request = new Request() { + @Override + public FetchProvideDataRequest getRequestBody() { + return new FetchProvideDataRequest(ValueConstants.BLACK_LIST_DATA_ID); + } + + @Override + public URL getRequestUrl() { + return new URL(raftClientManager.getLeader().getIp(), + sessionServerConfig.getMetaServerPort()); + } + }; + + Response response = metaNodeExchanger.request(request); + + if (response != null && response.getResult() != null) { + EXCHANGE_LOGGER.info("Update blacklist info success!"); + return response.getResult(); + } else { + LOGGER.error("Get blacklist info error!No response receive!"); + throw new RuntimeException("Get blacklist info error!No response receive!"); + } + } catch (Exception e) { + LOGGER.error("Get blacklist info error!", e); + throw new RuntimeException("Get blacklist info error! ", e); + } + } + + /** + * @see BlacklistManager#convertBlacklistConfig(String) + */ + public Map>> convertBlacklistConfig(String config) { + + TypeReference>>> typeReference = new TypeReference>>>() { + }; + + ObjectMapper mapper = new ObjectMapper(); + + Map>> blacklistConfigMap; + try { + blacklistConfigMap = mapper.readValue(config, typeReference); + } catch (IOException e) { + LOGGER.error("Parser config json error!", e); + return null; + } + if (null == blacklistConfigMap) { + LOGGER.info("[cmd] setBlacklistConfig fail, params is null"); + return null; + } + try { + List blacklistConfigs = new ArrayList(); + for (Entry>> configEntry : blacklistConfigMap + .entrySet()) { + BlacklistConfig blacklistConfig = new BlacklistConfig(); + blacklistConfig.setType(configEntry.getKey()); + + List matchTypeList = new ArrayList(); + + Map> matchTypeMap = configEntry.getValue(); + for (Entry> typeEntry : matchTypeMap.entrySet()) { + String type = typeEntry.getKey(); + + MatchType ipFullMatchType = new MatchType(); + ipFullMatchType.setType(type); + ipFullMatchType.setPatternSet(typeEntry.getValue()); + matchTypeList.add(ipFullMatchType); + } + blacklistConfig.setMatchTypes(matchTypeList); + blacklistConfigs.add(blacklistConfig); + } + + setBlacklistConfigList(blacklistConfigs); + return blacklistConfigMap; + } catch (Exception e) { + LOGGER.error("[cmd] setBlacklistConfig error", e); + return null; + } + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistMatchProcessFilter.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistMatchProcessFilter.java new file mode 100644 index 000000000..5f1845915 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/BlacklistMatchProcessFilter.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import com.alipay.sofa.registry.common.model.store.BaseInfo; +import com.alipay.sofa.registry.common.model.store.URL; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.filter.DataIdMatchStrategy; +import com.alipay.sofa.registry.server.session.filter.IPMatchStrategy; +import com.alipay.sofa.registry.server.session.filter.ProcessFilter; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * + * @author shangyu.wh + * @version 1.0: BlacklistMatchProcessFilter.java, v 0.1 2019-06-19 22:01 shangyu.wh Exp $ + */ +public class BlacklistMatchProcessFilter implements ProcessFilter { + + @Autowired + private DataIdMatchStrategy dataIdMatchStrategy; + + @Autowired + private IPMatchStrategy ipMatchStrategy; + + @Autowired + private BlacklistManager blacklistManager; + + @Autowired + private SessionServerConfig sessionServerConfig; + + @Override + public boolean match(BaseInfo storeData) { + + final List configList = blacklistManager.getBlacklistConfigList(); + + // empty list proceed + if (null == configList || configList.size() == 0) { + return false; + } + + URL url = storeData.getSourceAddress(); + + if (url != null) { + + switch (storeData.getDataType()) { + case PUBLISHER: + if(dataIdMatchStrategy.match(storeData.getDataId(),()-> sessionServerConfig.getBlacklistPubDataIdRegex())){ + return ipMatchStrategy.match(url.getIpAddress(),()-> BlacklistConstants.FORBIDDEN_PUB); + } + case SUBSCRIBER: + if(dataIdMatchStrategy.match(storeData.getDataId(),()-> sessionServerConfig.getBlacklistSubDataIdRegex())){ + return ipMatchStrategy.match(url.getIpAddress(),()-> BlacklistConstants.FORBIDDEN_SUB_BY_PREFIX); + } + default: + return false; + } + + } + return false; + } + + /** + * Getter method for property dataIdMatchStrategy. + * + * @return property value of dataIdMatchStrategy + */ + public DataIdMatchStrategy getDataIdMatchStrategy() { + return dataIdMatchStrategy; + } + + /** + * Setter method for property dataIdMatchStrategy. + * + * @param dataIdMatchStrategy value to be assigned to property dataIdMatchStrategy + */ + public void setDataIdMatchStrategy(DataIdMatchStrategy dataIdMatchStrategy) { + this.dataIdMatchStrategy = dataIdMatchStrategy; + } + + /** + * Getter method for property ipMatchStrategy. + * + * @return property value of ipMatchStrategy + */ + public IPMatchStrategy getIpMatchStrategy() { + return ipMatchStrategy; + } + + /** + * Setter method for property ipMatchStrategy. + * + * @param ipMatchStrategy value to be assigned to property ipMatchStrategy + */ + public void setIpMatchStrategy(IPMatchStrategy ipMatchStrategy) { + this.ipMatchStrategy = ipMatchStrategy; + } + + /** + * Getter method for property blacklistManager. + * + * @return property value of blacklistManager + */ + public BlacklistManager getBlacklistManager() { + return blacklistManager; + } + + /** + * Setter method for property blacklistManager. + * + * @param blacklistManager value to be assigned to property blacklistManager + */ + public void setBlacklistManager(BlacklistManager blacklistManager) { + this.blacklistManager = blacklistManager; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultDataIdMatchStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultDataIdMatchStrategy.java new file mode 100644 index 000000000..23abfaecd --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultDataIdMatchStrategy.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import com.alipay.sofa.registry.server.session.filter.DataIdMatchStrategy; +import org.springframework.util.StringUtils; + +import java.util.function.Supplier; +import java.util.regex.Pattern; + +/** + * + * @author shangyu.wh + * @version 1.0: DefaultDataIdMatchStrategy.java, v 0.1 2019-06-19 22:15 shangyu.wh Exp $ + */ +public class DefaultDataIdMatchStrategy implements DataIdMatchStrategy { + + @Override + public boolean match(String dataId, Supplier getOperatorType) { + if (StringUtils.hasText(dataId) && StringUtils.hasText(getOperatorType.get())) { + return Pattern.matches(getOperatorType.get(), dataId); + } + return true; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultIPMatchStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultIPMatchStrategy.java new file mode 100644 index 000000000..f4289f374 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/DefaultIPMatchStrategy.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import com.alipay.sofa.registry.server.session.filter.IPMatchStrategy; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +/** + * + * @author shangyu.wh + * @version 1.0: DefaultIPMatchStrategy.java, v 0.1 2019-06-19 22:16 shangyu.wh Exp $ + */ +public class DefaultIPMatchStrategy implements IPMatchStrategy { + + @Autowired + private BlacklistManager blacklistManager; + + @Override + public boolean match(String IP, Supplier getOperatorType) { + return match(getOperatorType.get(), IP); + } + + private boolean match(String type, String matchPattern) { + + List configList = blacklistManager.getBlacklistConfigList(); + for (BlacklistConfig blacklistConfig : configList) { + + // 如黑名单类型不匹配则跳过 + if (!StringUtils.equals(type, blacklistConfig.getType())) { + continue; + } + + List matchTypeList = blacklistConfig.getMatchTypes(); + + // 匹配规则为空跳过 + if (null == matchTypeList || matchTypeList.size() == 0) { + continue; + } + + for (MatchType matchType : matchTypeList) { + if (null == matchType) { + continue; + } + + if (BlacklistConstants.IP_FULL.equals(matchType.getType())) { + // IP 全匹配时判断当前发布者IP是否在IP列表中,如命中则拒绝发布 + @SuppressWarnings("unchecked") + Set patterns = matchType.getPatternSet(); + + if (null == patterns || patterns.size() == 0) { + continue; + } + + if (patterns.contains(matchPattern)) { + return true; + } + } + } + } + return false; + } + +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/MatchType.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/MatchType.java new file mode 100644 index 000000000..6a1318770 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/filter/blacklist/MatchType.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.filter.blacklist; + +import java.io.Serializable; +import java.util.Set; + +/** + * + * @author shangyu.wh + * @version 1.0: MatchType.java, v 0.1 2019-06-19 17:25 shangyu.wh Exp $ + */ +public class MatchType implements Serializable { + /** UID */ + private static final long serialVersionUID = 4015181538538056685L; + + /** match type */ + private String type; + + /** match patterns */ + private Set patternSet; + + /** + * Getter method for property type. + * + * @return property value of type + */ + public String getType() { + return type; + } + + /** + * Setter method for property type. + * + * @param type value to be assigned to property type + */ + public void setType(String type) { + this.type = type; + } + + /** + * Getter method for property patternSet. + * + * @return property value of patternSet + */ + public Set getPatternSet() { + return patternSet; + } + + /** + * Setter method for property patternSet. + * + * @param patternSet value to be assigned to property patternSet + */ + public void setPatternSet(Set patternSet) { + this.patternSet = patternSet; + } + + /** + * @see Object#toString() + */ + @Override + public String toString() { + return "MatchType{" + "type='" + type + '\'' + ", patternSet=" + patternSet + '}'; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitService.java new file mode 100644 index 000000000..7ac67b0f2 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitService.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.limit; + +/** + * + * @author shangyu.wh + * @version 1.0: AccessLimitService.java, v 0.1 2019-08-26 20:35 shangyu.wh Exp $ + */ +public interface AccessLimitService { + boolean tryAcquire(); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitServiceImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitServiceImpl.java new file mode 100644 index 000000000..fef1c6a8f --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/limit/AccessLimitServiceImpl.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.limit; + +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.google.common.util.concurrent.RateLimiter; + +/** + * + * @author shangyu.wh + * @version 1.0: AccessLimitServiceImpl.java, v 0.1 2019-08-26 20:37 shangyu.wh Exp $ + */ +public class AccessLimitServiceImpl implements AccessLimitService { + + private SessionServerConfig sessionServerConfig; + + private RateLimiter rateLimiter; + + public AccessLimitServiceImpl(SessionServerConfig sessionServerConfig) { + this.sessionServerConfig = sessionServerConfig; + rateLimiter = RateLimiter.create(sessionServerConfig.getAccessLimitRate()); + } + + @Override + public boolean tryAcquire() { + return rateLimiter.tryAcquire(); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/DatumSnapshotTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/DatumSnapshotTaskListener.java new file mode 100644 index 000000000..be81dc7d0 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/DatumSnapshotTaskListener.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.listener; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.scheduler.task.DatumSnapshotTask; +import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.task.batcher.TaskDispatcher; +import com.alipay.sofa.registry.task.batcher.TaskDispatchers; +import com.alipay.sofa.registry.task.batcher.TaskProcessor; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListener; + +/** + * + * @author kezhu.wukz + * @version $Id: RenewDatumTaskListener.java, v 0.1 2019-06-14 12:02 kezhu.wukz Exp $ + */ +public class DatumSnapshotTaskListener implements TaskListener { + + @Autowired + private DataNodeService dataNodeService; + + private TaskDispatcher singleTaskDispatcher; + + @Autowired + private TaskProcessor dataNodeSingleTaskProcessor; + + @PostConstruct + public void init() { + singleTaskDispatcher = TaskDispatchers.createSingleTaskDispatcher( + TaskDispatchers.getDispatcherName(TaskType.DATUM_SNAPSHOT_TASK.getName()), 100000, 32, + 1000, 1000, dataNodeSingleTaskProcessor); + } + + @Override + public boolean support(TaskEvent event) { + return TaskType.DATUM_SNAPSHOT_TASK.equals(event.getTaskType()); + } + + @Override + public void handleEvent(TaskEvent event) { + SessionTask datumSnapshotTask = new DatumSnapshotTask(dataNodeService); + + datumSnapshotTask.setTaskEvent(event); + + singleTaskDispatcher.dispatch(datumSnapshotTask.getTaskId(), datumSnapshotTask, + datumSnapshotTask.getExpiryTime()); + } + +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ProvideDataChangeFetchTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ProvideDataChangeFetchTaskListener.java index fe4b73208..aeb82529b 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ProvideDataChangeFetchTaskListener.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ProvideDataChangeFetchTaskListener.java @@ -18,6 +18,7 @@ import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistManager; import com.alipay.sofa.registry.server.session.node.service.MetaNodeService; import com.alipay.sofa.registry.server.session.registry.Registry; import com.alipay.sofa.registry.server.session.scheduler.task.ProvideDataChangeFetchTask; @@ -67,6 +68,9 @@ public class ProvideDataChangeFetchTaskListener implements TaskListener { @Autowired private Registry sessionRegistry; + @Autowired + private BlacklistManager blacklistManager; + private TaskDispatcher singleTaskDispatcher; private TaskProcessor dataNodeSingleTaskProcessor; @@ -93,7 +97,7 @@ public void handleEvent(TaskEvent event) { SessionTask provideDataChangeFetchTask = new ProvideDataChangeFetchTask( sessionServerConfig, taskListenerManager, metaNodeService, sessionWatchers, - boltExchange, sessionInterests, sessionRegistry); + boltExchange, sessionInterests, sessionRegistry, blacklistManager); provideDataChangeFetchTask.setTaskEvent(event); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/PublishDataTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/PublishDataTaskListener.java new file mode 100644 index 000000000..e2d0f7ef8 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/PublishDataTaskListener.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.listener; + +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.scheduler.ExecutorManager; +import com.alipay.sofa.registry.server.session.scheduler.task.PublishDataTask; +import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.task.batcher.TaskProcessor; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListener; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * @author kezhu.wukz + * @version $Id: PublishDataTaskListener.java, v 0.1 2019-06-17 12:02 kezhu.wukz Exp $ + */ +public class PublishDataTaskListener implements TaskListener { + + @Autowired + private DataNodeService dataNodeService; + + @Autowired + private TaskProcessor dataNodeSingleTaskProcessor; + + @Autowired + private ExecutorManager executorManager; + + @Override + public boolean support(TaskEvent event) { + return TaskType.PUBLISH_DATA_TASK.equals(event.getTaskType()); + } + + @Override + public void handleEvent(TaskEvent event) { + + SessionTask publishDataTask = new PublishDataTask(dataNodeService); + + publishDataTask.setTaskEvent(event); + + executorManager.getPublishDataExecutor().execute(()-> dataNodeSingleTaskProcessor.process(publishDataTask)); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ReceivedDataMultiPushTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ReceivedDataMultiPushTaskListener.java index fa8e67694..93a706bc5 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ReceivedDataMultiPushTaskListener.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/ReceivedDataMultiPushTaskListener.java @@ -16,6 +16,10 @@ */ package com.alipay.sofa.registry.server.session.listener; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.remoting.exchange.Exchange; @@ -25,6 +29,7 @@ import com.alipay.sofa.registry.server.session.scheduler.task.PushTaskClosure; import com.alipay.sofa.registry.server.session.scheduler.task.ReceivedDataMultiPushTask; import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.strategy.ReceivedDataMultiPushTaskStrategy; import com.alipay.sofa.registry.server.session.strategy.TaskMergeProcessorStrategy; import com.alipay.sofa.registry.task.TaskClosure; @@ -35,9 +40,6 @@ import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.concurrent.TimeUnit; /** * @@ -64,6 +66,9 @@ public class ReceivedDataMultiPushTaskListener implements TaskListener, PushTask @Autowired private ReceivedDataMultiPushTaskStrategy receivedDataMultiPushTaskStrategy; + @Autowired + private Interests sessionInterests; + private TaskMergeProcessorStrategy receiveDataTaskMergeProcessorStrategy; private TaskProcessor clientNodeSingleTaskProcessor; @@ -80,7 +85,9 @@ public ReceivedDataMultiPushTaskListener(TaskProcessor clientNodeSingleTaskProce asyncHashedWheelTimer = new AsyncHashedWheelTimer(threadFactoryBuilder.setNameFormat( "Registry-ReceivedDataPushTask-WheelTimer").build(), sessionServerConfig.getUserDataPushRetryWheelTicksDuration(), TimeUnit.MILLISECONDS, - sessionServerConfig.getUserDataPushRetryWheelTicksSize(), threadFactoryBuilder + sessionServerConfig.getUserDataPushRetryWheelTicksSize(), + sessionServerConfig.getUserDataPushRetryExecutorThreadSize(), + sessionServerConfig.getUserDataPushRetryExecutorQueueSize(), threadFactoryBuilder .setNameFormat("Registry-ReceivedDataPushTask-WheelExecutor-%d").build(), new TaskFailedCallback() { @Override @@ -117,7 +124,7 @@ public void handleEvent(TaskEvent event) { public void executePushAsync(TaskEvent event) { SessionTask receivedDataMultiPushTask = new ReceivedDataMultiPushTask(sessionServerConfig, clientNodeService, - executorManager, boltExchange, receivedDataMultiPushTaskStrategy,asyncHashedWheelTimer); + executorManager, boltExchange, receivedDataMultiPushTaskStrategy,asyncHashedWheelTimer,sessionInterests); receivedDataMultiPushTask.setTaskEvent(event); executorManager.getPushTaskExecutor() diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/RenewDatumTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/RenewDatumTaskListener.java new file mode 100644 index 000000000..a5f497090 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/RenewDatumTaskListener.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.listener; + +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.registry.SessionRegistry; +import com.alipay.sofa.registry.server.session.scheduler.task.RenewDatumTask; +import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.task.batcher.TaskDispatcher; +import com.alipay.sofa.registry.task.batcher.TaskDispatchers; +import com.alipay.sofa.registry.task.batcher.TaskProcessor; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListener; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.PostConstruct; + +/** + * + * @author kezhu.wukz + * @version $Id: RenewDatumTaskListener.java, v 0.1 2019-06-17 12:02 kezhu.wukz Exp $ + */ +public class RenewDatumTaskListener implements TaskListener { + + @Autowired + private DataNodeService dataNodeService; + + @Autowired + private SessionServerConfig sessionServerConfig; + + private TaskDispatcher singleTaskDispatcher; + + @Autowired + private TaskProcessor dataNodeSingleTaskProcessor; + + @Autowired + private SessionRegistry sessionRegistry; + + @PostConstruct + public void init() { + singleTaskDispatcher = TaskDispatchers.createSingleTaskDispatcher( + TaskDispatchers.getDispatcherName(TaskType.RENEW_DATUM_TASK.getName()), 100000, 32, + 1000, 1000, dataNodeSingleTaskProcessor); + } + + @Override + public boolean support(TaskEvent event) { + return TaskType.RENEW_DATUM_TASK.equals(event.getTaskType()); + } + + @Override + public void handleEvent(TaskEvent event) { + SessionTask renewDatumTask = new RenewDatumTask(sessionServerConfig, dataNodeService, + sessionRegistry); + + renewDatumTask.setTaskEvent(event); + + singleTaskDispatcher.dispatch(renewDatumTask.getTaskId(), renewDatumTask, + renewDatumTask.getExpiryTime()); + } + +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/SubscriberPushEmptyTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/SubscriberPushEmptyTaskListener.java new file mode 100644 index 000000000..955af4062 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/SubscriberPushEmptyTaskListener.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.listener; + +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.server.session.scheduler.task.SubscriberPushEmptyTask; +import com.alipay.sofa.registry.task.batcher.TaskDispatcher; +import com.alipay.sofa.registry.task.batcher.TaskDispatchers; +import com.alipay.sofa.registry.task.batcher.TaskProcessor; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListener; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * @author shangyu.wh + * @version $Id: SubscriberRegisterFetchTaskListener.java, v 0.1 2017-12-07 19:53 shangyu.wh Exp $ + */ +public class SubscriberPushEmptyTaskListener implements TaskListener { + + @Autowired + private SessionServerConfig sessionServerConfig; + + /** + * trigger task com.alipay.sofa.registry.server.meta.listener process + */ + @Autowired + private TaskListenerManager taskListenerManager; + + private TaskDispatcher singleTaskDispatcher; + + @Autowired + private TaskProcessor dataNodeSingleTaskProcessor; + + public TaskDispatcher getSingleTaskDispatcher() { + if (singleTaskDispatcher == null) { + singleTaskDispatcher = TaskDispatchers.createDefaultSingleTaskDispatcher( + TaskType.SUBSCRIBER_PUSH_EMPTY_TASK.getName(), dataNodeSingleTaskProcessor); + } + return singleTaskDispatcher; + } + + @Override + public boolean support(TaskEvent event) { + return TaskType.SUBSCRIBER_PUSH_EMPTY_TASK.equals(event.getTaskType()); + } + + @Override + public void handleEvent(TaskEvent event) { + + SessionTask subscriberPushEmptyTask = new SubscriberPushEmptyTask(sessionServerConfig, + taskListenerManager); + + subscriberPushEmptyTask.setTaskEvent(event); + + getSingleTaskDispatcher().dispatch(subscriberPushEmptyTask.getTaskId(), + subscriberPushEmptyTask, subscriberPushEmptyTask.getExpiryTime()); + } + +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/UnPublishDataTaskListener.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/UnPublishDataTaskListener.java new file mode 100644 index 000000000..566910f07 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/listener/UnPublishDataTaskListener.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.listener; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; +import com.alipay.sofa.registry.server.session.scheduler.task.UnPublishDataTask; +import com.alipay.sofa.registry.server.session.store.DataStore; +import com.alipay.sofa.registry.server.session.store.Interests; +import com.alipay.sofa.registry.server.session.store.Watchers; +import com.alipay.sofa.registry.task.batcher.TaskDispatcher; +import com.alipay.sofa.registry.task.batcher.TaskDispatchers; +import com.alipay.sofa.registry.task.batcher.TaskProcessor; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListener; + +/** + * + * @author kezhu.wukz + * @version $Id: UnPublishDataTaskListener.java, v 0.1 2019-06-17 12:02 kezhu.wukz Exp $ + */ +public class UnPublishDataTaskListener implements TaskListener { + + /** + * store subscribers + */ + @Autowired + private Interests sessionInterests; + + /** + * store publishers + */ + @Autowired + private DataStore sessionDataStore; + + @Autowired + private Watchers sessionWatchers; + + /** + * transfer data to DataNode + */ + @Autowired + private DataNodeService dataNodeService; + + @Autowired + private SessionServerConfig sessionServerConfig; + + private TaskDispatcher singleTaskDispatcher; + + @Autowired + private TaskProcessor dataNodeSingleTaskProcessor; + + @PostConstruct + public void init() { + singleTaskDispatcher = TaskDispatchers.createSingleTaskDispatcher( + TaskDispatchers.getDispatcherName(TaskType.UN_PUBLISH_DATA_TASK.getName()), 100000, 32, + 1000, 1000, dataNodeSingleTaskProcessor); + } + + @Override + public boolean support(TaskEvent event) { + return TaskType.UN_PUBLISH_DATA_TASK.equals(event.getTaskType()); + } + + @Override + public void handleEvent(TaskEvent event) { + SessionTask unPublishDataTask = new UnPublishDataTask(dataNodeService); + + unPublishDataTask.setTaskEvent(event); + + singleTaskDispatcher.dispatch(unPublishDataTask.getTaskId(), unPublishDataTask, + unPublishDataTask.getExpiryTime()); + } + +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/AbstractNodeManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/AbstractNodeManager.java index 274aa4dc4..ea956a588 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/AbstractNodeManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/AbstractNodeManager.java @@ -16,6 +16,15 @@ */ package com.alipay.sofa.registry.server.session.node; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.metaserver.GetNodesRequest; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; @@ -28,14 +37,6 @@ import com.alipay.sofa.registry.remoting.exchange.message.Response; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.util.VersionsMapUtils; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @@ -148,9 +149,9 @@ public URL getRequestUrl() { } } catch (RequestException e) { - LOGGER.error("NodeManager get all dataCenter nodes error! " + e.getRequestMessage(), e); + LOGGER.error("NodeManager get all dataCenter nodes error! " + e.getMessage(), e); throw new RuntimeException("NodeManager get all dataCenter nodes error! " - + e.getRequestMessage(), e); + + e.getMessage(), e); } return nodeChangeResult; diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/DataNodeManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/DataNodeManager.java index 894346efa..d62baaff7 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/DataNodeManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/DataNodeManager.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.server.session.node; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.DataNode; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; @@ -23,7 +25,6 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -44,7 +45,6 @@ public class DataNodeManager extends AbstractNodeManager { public DataNode getNode(String dataInfoId) { DataNode dataNode = consistentHash.getNodeFor(dataInfoId); if (dataNode == null) { - LOGGER.error("calculate data node error!,dataInfoId={}", dataInfoId); throw new RuntimeException("DataNodeManager calculate data node error!,dataInfoId=" + dataInfoId); } @@ -70,7 +70,7 @@ public NodeType getNodeType() { } @Override - public void reNewNode() { + public void renewNode() { } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/MetaNodeManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/MetaNodeManager.java index 2a2095096..56117598a 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/MetaNodeManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/MetaNodeManager.java @@ -16,11 +16,11 @@ */ package com.alipay.sofa.registry.server.session.node; +import java.util.Collection; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.MetaNode; -import java.util.Collection; - /** * * @author shangyu.wh @@ -44,6 +44,6 @@ public Collection getDataCenters() { } @Override - public void reNewNode() { + public void renewNode() { } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/NodeManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/NodeManager.java index 59b47879a..c3c0ebc74 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/NodeManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/NodeManager.java @@ -16,13 +16,13 @@ */ package com.alipay.sofa.registry.server.session.node; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; - /** * * @author shangyu.wh @@ -40,7 +40,7 @@ public interface NodeManager { Collection getDataCenters(); - void reNewNode(); + void renewNode(); NodeChangeResult getAllDataCenterNodes(); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/SessionNodeManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/SessionNodeManager.java index 4c50cfa2e..b20f0f66c 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/SessionNodeManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/SessionNodeManager.java @@ -16,9 +16,13 @@ */ package com.alipay.sofa.registry.server.session.node; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.metaserver.NodeChangeResult; -import com.alipay.sofa.registry.common.model.metaserver.ReNewNodesRequest; +import com.alipay.sofa.registry.common.model.metaserver.RenewNodesRequest; import com.alipay.sofa.registry.common.model.metaserver.SessionNode; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; @@ -27,10 +31,6 @@ import com.alipay.sofa.registry.remoting.exchange.RequestException; import com.alipay.sofa.registry.remoting.exchange.message.Request; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - /** * * @author shangyu.wh @@ -71,18 +71,18 @@ public List getZoneServerList(String zonename) { } @Override - public void reNewNode() { + public void renewNode() { try { - Request reNewNodesRequestRequest = new Request() { + Request renewNodesRequestRequest = new Request() { @Override - public ReNewNodesRequest getRequestBody() { + public RenewNodesRequest getRequestBody() { URL clientUrl = new URL(NetUtil.getLocalAddress().getHostAddress(), 0); SessionNode sessionNode = new SessionNode(clientUrl, sessionServerConfig.getSessionServerRegion()); - return new ReNewNodesRequest(sessionNode); + return new RenewNodesRequest(sessionNode); } @Override @@ -92,11 +92,9 @@ public URL getRequestUrl() { } }; - metaNodeExchanger.request(reNewNodesRequestRequest); + metaNodeExchanger.request(renewNodesRequestRequest); } catch (RequestException e) { - LOGGER.error("SessionNodeManager reNew node error! " + e.getRequestMessage(), e); - throw new RuntimeException("SessionNodeManager reNew node error! " - + e.getRequestMessage(), e); + throw new RuntimeException("SessionNodeManager renew node error! " + e.getMessage(), e); } } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/processor/DataNodeSingleTaskProcessor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/processor/DataNodeSingleTaskProcessor.java index 74d6c9c43..f3e376b90 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/processor/DataNodeSingleTaskProcessor.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/processor/DataNodeSingleTaskProcessor.java @@ -16,14 +16,15 @@ */ package com.alipay.sofa.registry.server.session.node.processor; +import java.util.List; + import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.scheduler.task.RenewDatumTask; import com.alipay.sofa.registry.server.session.scheduler.task.SessionTask; import com.alipay.sofa.registry.task.Retryable; import com.alipay.sofa.registry.task.batcher.TaskProcessor; -import java.util.List; - /** * * @author shangyu.wh @@ -37,9 +38,15 @@ public class DataNodeSingleTaskProcessor implements TaskProcessor { @Override public ProcessingResult process(SessionTask task) { try { - LOGGER.info("execute " + task); + if (!(task instanceof RenewDatumTask)) { + LOGGER.info("execute " + task); + } + task.execute(); - LOGGER.info("end " + task); + + if (!(task instanceof RenewDatumTask)) { + LOGGER.info("end " + task); + } return ProcessingResult.Success; } catch (Throwable throwable) { LOGGER.error("Data node SingleTask Process error! Task:" + task, throwable); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/ClientNodeServiceImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/ClientNodeServiceImpl.java index 7ab6333cf..788c6b844 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/ClientNodeServiceImpl.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/ClientNodeServiceImpl.java @@ -16,12 +16,13 @@ */ package com.alipay.sofa.registry.server.session.node.service; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.remoting.CallbackHandler; import com.alipay.sofa.registry.remoting.exchange.NodeExchanger; import com.alipay.sofa.registry.remoting.exchange.RequestException; import com.alipay.sofa.registry.remoting.exchange.message.Request; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -57,8 +58,7 @@ public CallbackHandler getCallBackHandler() { clientNodeExchanger.request(request); } catch (RequestException e) { - throw new RuntimeException("Push data to client node error !" + e.getRequestMessage(), - e); + throw new RuntimeException("Push data to client node error !" + e.getMessage(), e); } } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeService.java index df1180ba8..544c88010 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeService.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeService.java @@ -16,15 +16,17 @@ */ package com.alipay.sofa.registry.server.session.node.service; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.SessionServerRegisterRequest; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.common.model.store.URL; -import java.util.Collection; -import java.util.List; -import java.util.Map; - /** * * @author shangyu.wh @@ -97,4 +99,14 @@ public interface DataNodeService { void registerSessionProcessId(SessionServerRegisterRequest sessionServerRegisterRequest, URL dataUrl); + /** + * check publisher digest same as session current store,and renew the lastUpdateTime of this connectId + */ + Boolean renewDatum(RenewDatumRequest renewDatumRequest); + + /** + * Correct the publishers information of this connectId on dataServer + */ + void sendDatumSnapshot(DatumSnapshotRequest datumSnapshotRequest); + } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeServiceImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeServiceImpl.java index 4337f2432..afd2bf2ff 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeServiceImpl.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/DataNodeServiceImpl.java @@ -16,9 +16,22 @@ */ package com.alipay.sofa.registry.server.session.node.service; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; import com.alipay.sofa.registry.common.model.GenericResponse; import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; import com.alipay.sofa.registry.common.model.dataserver.ClientOffRequest; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.dataserver.GetDataRequest; @@ -40,14 +53,6 @@ import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; /** * @@ -69,13 +74,16 @@ public class DataNodeServiceImpl implements DataNodeService { private AsyncHashedWheelTimer asyncHashedWheelTimer; - public DataNodeServiceImpl() { + @PostConstruct + public void init() { ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); threadFactoryBuilder.setDaemon(true); asyncHashedWheelTimer = new AsyncHashedWheelTimer(threadFactoryBuilder.setNameFormat( - "Registry-DataNodeServiceImpl-WheelTimer").build(), 100, TimeUnit.MILLISECONDS, 1024, - threadFactoryBuilder.setNameFormat("Registry-DataNodeServiceImpl-WheelExecutor-%d") - .build(), new TaskFailedCallback() { + "Registry-DataNodeServiceImpl-Retry-WheelTimer").build(), 100, TimeUnit.MILLISECONDS, + 1024, sessionServerConfig.getDataNodeRetryExecutorThreadSize(), + sessionServerConfig.getDataNodeRetryExecutorQueueSize(), threadFactoryBuilder + .setNameFormat("Registry-DataNodeServiceImpl-Retry-WheelExecutor-%d").build(), + new TaskFailedCallback() { @Override public void executionRejected(Throwable e) { LOGGER.error("executionRejected: " + e.getMessage(), e); @@ -90,98 +98,78 @@ public void executionFailed(Throwable e) { @Override public void register(final Publisher publisher) { - + String bizName = "PublishData"; + Request request = buildPublishDataRequest(publisher); try { + sendRequest(bizName, request); + } catch (RequestException e) { + doRetryAsync(bizName, request, e, sessionServerConfig.getPublishDataTaskRetryTimes(), + sessionServerConfig.getPublishDataTaskRetryFirstDelay(), + sessionServerConfig.getPublishDataTaskRetryIncrementDelay()); + } + } - Request publisherRequest = new Request() { - - private URL url; - - @Override - public PublishDataRequest getRequestBody() { - PublishDataRequest publishDataRequest = new PublishDataRequest(); - publishDataRequest.setPublisher(publisher); - publishDataRequest.setSessionServerProcessId(SessionProcessIdGenerator - .getSessionProcessId()); - return publishDataRequest; - } - - @Override - public URL getRequestUrl() { - if (url == null) { - url = getUrl(publisher.getDataInfoId()); - } - return url; - } - }; + private Request buildPublishDataRequest(Publisher publisher) { + return new Request() { + private AtomicInteger retryTimes = new AtomicInteger(); + + @Override + public PublishDataRequest getRequestBody() { + PublishDataRequest publishDataRequest = new PublishDataRequest(); + publishDataRequest.setPublisher(publisher); + publishDataRequest.setSessionServerProcessId(SessionProcessIdGenerator + .getSessionProcessId()); + return publishDataRequest; + } - Response response = dataNodeExchanger.request(publisherRequest); + @Override + public URL getRequestUrl() { + return getUrl(publisher.getDataInfoId()); + } - Object result = response.getResult(); - if (result instanceof CommonResponse) { - CommonResponse commonResponse = (CommonResponse) result; - if (!commonResponse.isSuccess()) { - LOGGER.error( - "PublishDataRequest get server response failed!target url:{},message:{}", - publisherRequest.getRequestUrl(), commonResponse.getMessage()); - throw new RuntimeException( - "PublishDataRequest get server response failed! msg:" - + commonResponse.getMessage()); - } + @Override + public AtomicInteger getRetryTimes() { + return retryTimes; } - } catch (RequestException e) { - LOGGER.error("DataNodeService register new publisher error! " + e.getRequestMessage(), - e); - throw new RuntimeException("DataNodeService register new publisher error! " - + e.getRequestMessage(), e); - } + }; } @Override public void unregister(final Publisher publisher) { + String bizName = "UnPublishData"; + Request request = buildUnPublishDataRequest(publisher); try { - Request unPublishRequest = new Request() { - - private URL url; - - @Override - public UnPublishDataRequest getRequestBody() { - UnPublishDataRequest unPublishDataRequest = new UnPublishDataRequest(); - unPublishDataRequest.setDataInfoId(publisher.getDataInfoId()); - unPublishDataRequest.setRegisterId(publisher.getRegisterId()); - unPublishDataRequest.setRegisterTimestamp(publisher.getRegisterTimestamp()); - return unPublishDataRequest; - } + sendRequest(bizName, request); + } catch (RequestException e) { + doRetryAsync(bizName, request, e, sessionServerConfig.getUnPublishDataTaskRetryTimes(), + sessionServerConfig.getUnPublishDataTaskRetryFirstDelay(), + sessionServerConfig.getUnPublishDataTaskRetryIncrementDelay()); + } + } - @Override - public URL getRequestUrl() { - if (url == null) { - url = getUrl(publisher.getDataInfoId()); - } - return url; - } - }; + private Request buildUnPublishDataRequest(Publisher publisher) { + return new Request() { - Response response = dataNodeExchanger.request(unPublishRequest); + private AtomicInteger retryTimes = new AtomicInteger(); - Object result = response.getResult(); - if (result instanceof CommonResponse) { - CommonResponse commonResponse = (CommonResponse) result; - if (!commonResponse.isSuccess()) { - LOGGER.error( - "UnPublishRequest get server response failed!target url:{},message:{}", - unPublishRequest.getRequestUrl(), commonResponse.getMessage()); - throw new RuntimeException("UnPublishRequest get server response failed! msg:" - + commonResponse.getMessage()); - } + @Override + public UnPublishDataRequest getRequestBody() { + UnPublishDataRequest unPublishDataRequest = new UnPublishDataRequest( + publisher.getDataInfoId(), publisher.getRegisterId(), + publisher.getRegisterTimestamp()); + return unPublishDataRequest; } - } catch (RequestException e) { - LOGGER.error("Unregister publisher to data node error! " + e.getRequestMessage(), e); - throw new RuntimeException("Unregister publisher to data node error! " - + e.getRequestMessage(), e); - } + @Override + public URL getRequestUrl() { + return getUrl(publisher.getDataInfoId()); + } + @Override + public AtomicInteger getRetryTimes() { + return retryTimes; + } + }; } @Override @@ -190,121 +178,55 @@ public void clientOff(List connectIds) { return; } //get all local dataCenter data node + String bizName = "ClientOff"; Collection nodes = dataNodeManager.getDataCenterNodes(); if (nodes != null && nodes.size() > 0) { - for (Node node : nodes) { - Request clientOffRequestRequest = new Request() { - - private AtomicInteger retryTimes = new AtomicInteger(); - - @Override - public ClientOffRequest getRequestBody() { - ClientOffRequest clientOffRequest = new ClientOffRequest(); - clientOffRequest.setHosts(connectIds); - clientOffRequest.setGmtOccur(System.currentTimeMillis()); - return clientOffRequest; - } - - @Override - public URL getRequestUrl() { - return new URL(node.getNodeUrl().getIpAddress(), - sessionServerConfig.getDataServerPort()); - } - - @Override - public AtomicInteger getRetryTimes() { - return retryTimes; - } - }; + Request request = buildClientOffRequest(connectIds, node); try { + sendRequest(bizName, request); + } catch (RequestException e) { + doRetryAsync(bizName, request, e, + sessionServerConfig.getCancelDataTaskRetryTimes(), + sessionServerConfig.getCancelDataTaskRetryFirstDelay(), + sessionServerConfig.getCancelDataTaskRetryIncrementDelay()); - Response response = dataNodeExchanger.request(clientOffRequestRequest); - Object result = response.getResult(); - if (result instanceof CommonResponse) { - CommonResponse commonResponse = (CommonResponse) result; - if (!commonResponse.isSuccess()) { - LOGGER - .error( - "ClientOff RequestRequest get response failed!target url:{},message:{}", - node.getNodeUrl(), commonResponse.getMessage()); - throw new RuntimeException( - "ClientOff RequestRequest get response failed! msg:" - + commonResponse.getMessage()); - } - } else { - LOGGER - .error( - "ClientOff Request has not get response or response type illegal!url:{}", - node.getNodeUrl()); - throw new RuntimeException( - "ClientOff Request has not get response or response type illegal!"); - } - } catch (Exception e) { - LOGGER.error("Client Off request error! ", e); - clientOffRetry(clientOffRequestRequest); } - } } } - private void clientOffRetry(Request clientOffRequestRequest) { + private Request buildClientOffRequest(List connectIds, Node node) { + return new Request() { - URL url = clientOffRequestRequest.getRequestUrl(); + private AtomicInteger retryTimes = new AtomicInteger(); - int retryTimes = clientOffRequestRequest.getRetryTimes().incrementAndGet(); + @Override + public ClientOffRequest getRequestBody() { + ClientOffRequest clientOffRequest = new ClientOffRequest(); + clientOffRequest.setHosts(connectIds); + clientOffRequest.setGmtOccur(System.currentTimeMillis()); + return clientOffRequest; + } - if (retryTimes <= sessionServerConfig.getCancelDataTaskRetryTimes()) { - asyncHashedWheelTimer.newTimeout(timeout -> { - try { - Response response = dataNodeExchanger.request(clientOffRequestRequest); - Object result = response.getResult(); - if (result instanceof CommonResponse) { - CommonResponse commonResponse = (CommonResponse) result; - if (!commonResponse.isSuccess()) { - LOGGER.error( - "ClientOff retry RequestRequest get response failed!retryTimes={},target url:{},message:{}", - retryTimes, - url, commonResponse.getMessage()); - throw new RuntimeException( - "ClientOff retry RequestRequest get response failed! msg:" + - commonResponse.getMessage()); - } - } else { - LOGGER.error( - "ClientOff retry Request has not get response or response type illegal!retryTimes={},url:{}", - retryTimes, url); - throw new RuntimeException( - "ClientOff retry Request has not get response or response type illegal!"); - } - } catch (Exception e) { - clientOffRetry(clientOffRequestRequest); - } - }, getBlockTime(retryTimes), TimeUnit.MILLISECONDS); - } else { - LOGGER.error("ClientOff retryTimes have exceeded! stop retry! retryTimes={}, url={}, request={}", - retryTimes, url, clientOffRequestRequest.getRequestBody()); - } - } + @Override + public URL getRequestUrl() { + return new URL(node.getNodeUrl().getIpAddress(), + sessionServerConfig.getDataServerPort()); + } - private long getBlockTime(int retry) { - long initialSleepTime = TimeUnit.MILLISECONDS.toMillis(sessionServerConfig - .getCancelDataTaskRetryFirstDelay()); - long increment = TimeUnit.MILLISECONDS.toMillis(sessionServerConfig - .getCancelDataTaskRetryIncrementDelay()); - long result = initialSleepTime + (increment * (retry - 1)); - return result >= 0L ? result : 0L; + @Override + public AtomicInteger getRetryTimes() { + return retryTimes; + } + }; } @Override public void registerSessionProcessId(final SessionServerRegisterRequest sessionServerRegisterRequest, final URL dataUrl) { - try { - Request request = new Request() { - @Override public SessionServerRegisterRequest getRequestBody() { return sessionServerRegisterRequest; @@ -315,22 +237,18 @@ public URL getRequestUrl() { return dataUrl; } }; - dataNodeExchanger.request(request); } catch (RequestException e) { - LOGGER.error("DataNodeService register processId error! " + e.getRequestMessage(), e); throw new RuntimeException("DataNodeService register processId error! " - + e.getRequestMessage(), e); + + e.getMessage(), e); } } @Override public Map> fetchDataVersion(URL dataNodeUrl, Collection dataInfoIdList) { - Map> map = new HashMap<>(); try { - Request getDataVersionRequestRequest = new Request() { @Override public GetDataVersionRequest getRequestBody() { @@ -346,33 +264,22 @@ public URL getRequestUrl() { }; Response response = dataNodeExchanger.request(getDataVersionRequestRequest); - Object result = response.getResult(); - if (result instanceof GenericResponse) { - GenericResponse genericResponse = (GenericResponse) result; - if (genericResponse.isSuccess()) { - map = (Map>) genericResponse.getData(); - if (map.isEmpty()) { - LOGGER - .warn( - "GetDataVersionRequestRequest get response contains no data!target data Node url:{} about dataInfoIds size:{}", - dataNodeUrl.getAddressString(), dataInfoIdList.size()); - } - } else { - LOGGER.error("fetchDataVersion has not get fail response!msg:{}", - genericResponse.getMessage()); - throw new RuntimeException("fetchDataVersion has not get fail response! msg:" - + genericResponse.getMessage()); + GenericResponse genericResponse = (GenericResponse) result; + if (genericResponse.isSuccess()) { + map = (Map>) genericResponse.getData(); + if (map.isEmpty()) { + LOGGER + .warn( + "GetDataVersionRequestRequest get response contains no data!target data Node url:{} about dataInfoIds size:{}", + dataNodeUrl.getAddressString(), dataInfoIdList.size()); } } else { - LOGGER - .error("GetDataVersionRequestRequest has not get response or response type illegal!"); + throw new RuntimeException("fetchDataVersion has not get fail response! msg:" + + genericResponse.getMessage()); } - } catch (RequestException e) { - LOGGER.error("Fetch data Version request error! " + e.getRequestMessage(), e); - throw new RuntimeException( - "Fetch data Version request error! " + e.getRequestMessage(), e); + throw new RuntimeException("Fetch data Version request error! " + e.getMessage(), e); } return map; @@ -398,12 +305,12 @@ private Map getDatumMap(String dataInfoId) { return getDatumMap(dataInfoId, null); } - @Override public Map getDatumMap(String dataInfoId, String dataCenterId) { + @Override + public Map getDatumMap(String dataInfoId, String dataCenterId) { Map map; try { - GetDataRequest getDataRequest = new GetDataRequest(); //dataCenter null means all dataCenters @@ -428,42 +335,141 @@ public URL getRequestUrl() { Response response = dataNodeExchanger.request(getDataRequestStringRequest); Object result = response.getResult(); - if (result instanceof GenericResponse) { - GenericResponse genericResponse = (GenericResponse) result; - if (genericResponse.isSuccess()) { - map = (Map) genericResponse.getData(); - if (map == null || map.isEmpty()) { - LOGGER.warn("GetDataRequest get response contains no datum!"); - } else { - map.forEach((dataCenter, datum) -> Datum.processDatum(datum)); - } + GenericResponse genericResponse = (GenericResponse) result; + if (genericResponse.isSuccess()) { + map = (Map) genericResponse.getData(); + if (map == null || map.isEmpty()) { + LOGGER.warn("GetDataRequest get response contains no datum!dataInfoId={}", dataCenterId); } else { - LOGGER.error("GetDataRequest has not get fail response!msg:{}", genericResponse.getMessage()); - throw new RuntimeException("GetDataRequest has not get fail response! msg:" + - genericResponse.getMessage()); + map.forEach((dataCenter, datum) -> Datum.processDatum(datum)); } } else { - LOGGER.error("GetDataRequest has not get response or response type illegal!"); - throw new RuntimeException("GetDataRequest has not get response or response type illegal!"); + throw new RuntimeException( + String.format("GetDataRequest has got fail response!dataInfoId:%s msg:%s", dataInfoId, + genericResponse.getMessage())); } } catch (RequestException e) { - LOGGER.error("Get data request to data node error! " + e.getRequestMessage(), e); throw new RuntimeException( - "Get data request to data node error! " + e.getRequestMessage(), e); + String.format("Get data request to data node error!dataInfoId:%s msg:%s ", dataInfoId, + e.getMessage()), e); } return map; } - private URL getUrl(String dataInfoId) { + @Override + public Boolean renewDatum(RenewDatumRequest renewDatumRequest) { + Request request = buildRenewDatumRequest(renewDatumRequest); + try { + GenericResponse genericResponse = (GenericResponse) sendRequest("RenewDatum", request); + return (Boolean) genericResponse.getData(); + } catch (RequestException e) { + throw new RuntimeException(e.getMessage(), e); + } + } - Node dataNode = dataNodeManager.getNode(dataInfoId); - if (dataNode != null) { - //meta push data node has not port - String dataIp = dataNode.getNodeUrl().getIpAddress(); - return new URL(dataIp, sessionServerConfig.getDataServerPort()); + private Request buildRenewDatumRequest(RenewDatumRequest renewDatumRequest) { + return new Request() { + private AtomicInteger retryTimes = new AtomicInteger(); + + @Override + public RenewDatumRequest getRequestBody() { + return renewDatumRequest; + } + + @Override + public URL getRequestUrl() { + return new URL(renewDatumRequest.getDataServerIP(), + sessionServerConfig.getDataServerPort()); + } + + @Override + public AtomicInteger getRetryTimes() { + return retryTimes; + } + }; + } + + @Override + public void sendDatumSnapshot(DatumSnapshotRequest datumSnapshotRequest) { + String bizName = "DatumSnapshot"; + Request request = buildDatumSnapshotRequest(datumSnapshotRequest); + try { + sendRequest(bizName, request); + } catch (RequestException e) { + doRetryAsync(bizName, request, e, sessionServerConfig.getDatumSnapshotTaskRetryTimes(), + sessionServerConfig.getDatumSnapshotTaskRetryFirstDelay(), + sessionServerConfig.getDatumSnapshotTaskRetryIncrementDelay()); } - return null; + + } + + private Request buildDatumSnapshotRequest(DatumSnapshotRequest datumSnapshotRequest) { + return new Request() { + private AtomicInteger retryTimes = new AtomicInteger(); + + @Override + public DatumSnapshotRequest getRequestBody() { + return datumSnapshotRequest; + } + + @Override + public URL getRequestUrl() { + return new URL(datumSnapshotRequest.getDataServerIp(), + sessionServerConfig.getDataServerPort()); + } + + @Override + public AtomicInteger getRetryTimes() { + return retryTimes; + } + }; + } + + private CommonResponse sendRequest(String bizName, Request request) throws RequestException { + Response response = dataNodeExchanger.request(request); + Object result = response.getResult(); + CommonResponse commonResponse = (CommonResponse) result; + if (!commonResponse.isSuccess()) { + throw new RuntimeException(String.format( + "[%s] response not success, failed! target url: %s, request: %s, message: %s", + bizName, request.getRequestUrl(), request.getRequestBody(), + commonResponse.getMessage())); + } + return commonResponse; + } + + private void doRetryAsync(String bizName, Request request, Exception e, int maxRetryTimes, long firstDelay, + long incrementDelay) { + int retryTimes = request.getRetryTimes().incrementAndGet(); + if (retryTimes <= maxRetryTimes) { + LOGGER.warn("{} failed, will retry again, retryTimes: {}, msg: {}", bizName, retryTimes, e.getMessage()); + asyncHashedWheelTimer.newTimeout(timeout -> { + try { + sendRequest(bizName, request); + } catch (RequestException ex) { + doRetryAsync(bizName, request, ex, maxRetryTimes, firstDelay, incrementDelay); + } + }, getDelayTime(retryTimes, firstDelay, incrementDelay), TimeUnit.MILLISECONDS); + } else { + LOGGER.error(String.format( + "%s failed, retryTimes have exceeded! stop retry! retryTimes: %s, url: %s, request: %s, msg: %s", + bizName, (retryTimes - 1), request.getRequestUrl(), request.getRequestBody(), e.getMessage()), e); + } + } + + private long getDelayTime(int retry, long firstDelay, long incrementDelay) { + long initialSleepTime = TimeUnit.MILLISECONDS.toMillis(firstDelay); + long increment = TimeUnit.MILLISECONDS.toMillis(incrementDelay); + long result = initialSleepTime + (increment * (retry - 1)); + return result >= 0L ? result : 0L; + } + + private URL getUrl(String dataInfoId) { + Node dataNode = dataNodeManager.getNode(dataInfoId); + //meta push data node has not port + String dataIp = dataNode.getNodeUrl().getIpAddress(); + return new URL(dataIp, sessionServerConfig.getDataServerPort()); } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/MetaNodeServiceImpl.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/MetaNodeServiceImpl.java index 85eef1f9a..eaceb1e09 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/MetaNodeServiceImpl.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/node/service/MetaNodeServiceImpl.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.server.session.node.service; +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.metaserver.FetchProvideDataRequest; import com.alipay.sofa.registry.common.model.metaserver.ProvideData; import com.alipay.sofa.registry.common.model.store.URL; @@ -28,7 +30,6 @@ import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.RaftClientManager; import com.alipay.sofa.registry.server.session.node.SessionNodeManager; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -78,8 +79,8 @@ public URL getRequestUrl() { throw new RuntimeException("MetaNodeService fetch null provider data!"); } } catch (RequestException e) { - LOGGER.error("fetch provider data error! " + e.getRequestMessage(), e); - throw new RuntimeException("fetch provider data error! " + e.getRequestMessage(), e); + LOGGER.error("fetch provider data error! " + e.getMessage(), e); + throw new RuntimeException("fetch provider data error! " + e.getMessage(), e); } } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/Registry.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/Registry.java index 6d4920f14..a0c7c6675 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/Registry.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/Registry.java @@ -16,10 +16,10 @@ */ package com.alipay.sofa.registry.server.session.registry; -import com.alipay.sofa.registry.common.model.store.StoreData; - import java.util.List; +import com.alipay.sofa.registry.common.model.store.StoreData; + /** * * @author shangyu.wh @@ -43,6 +43,15 @@ public interface Registry { */ void cancel(List connectIds); + /** + * remove publisher or subscriber data by client ip address and port(ip:port) + * this function always use in rest api Console manage ,the run mode is standard + * remove subscriber data will push empty datum to some one who has dataInfoId begin with pushEmptyDataDataIdPrefixes config + * + * @param connectIds + */ + void remove(List connectIds); + /** * message mode com.alipay.sofa.registry.client.provider for client node to unregister single subscriber or publisher data * @@ -61,4 +70,18 @@ public interface Registry { * for fetchChangData first invoke */ void fetchChangDataProcess(); + + /** + * Regularly send update Datum with same connectID valid time request service + */ + void renewDatum(String connectId); + + void sendDatumSnapshot(String connectId, String dataServerIp); + + /** + * for scheduler clean no connect client + */ + void cleanClientConnect(); + + void setEnableDataRenewSnapshot(boolean enableDataRenewSnapshot); } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/SessionRegistry.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/SessionRegistry.java index fe40e3a48..0ad21988f 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/SessionRegistry.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/registry/SessionRegistry.java @@ -16,8 +16,19 @@ */ package com.alipay.sofa.registry.server.session.registry; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; -import com.alipay.sofa.registry.common.model.store.BaseInfo; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.common.model.store.StoreData; import com.alipay.sofa.registry.common.model.store.Subscriber; @@ -28,24 +39,24 @@ import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.remoting.Server; import com.alipay.sofa.registry.remoting.exchange.Exchange; +import com.alipay.sofa.registry.server.session.acceptor.WriteDataAcceptor; +import com.alipay.sofa.registry.server.session.acceptor.WriteDataRequest; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.filter.DataIdMatchStrategy; import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.renew.RenewService; import com.alipay.sofa.registry.server.session.store.DataStore; import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.store.Watchers; import com.alipay.sofa.registry.server.session.strategy.SessionRegistryStrategy; +import com.alipay.sofa.registry.server.session.wrapper.Wrapper; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInterceptorManager; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInvocation; import com.alipay.sofa.registry.task.listener.TaskEvent; -import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; /** * @@ -54,88 +65,147 @@ */ public class SessionRegistry implements Registry { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionRegistry.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(SessionRegistry.class); + + private static final Logger TASK_LOGGER = LoggerFactory.getLogger( + SessionRegistry.class, "[Task]"); - private static final Logger TASK_LOGGER = LoggerFactory.getLogger(SessionRegistry.class, - "[Task]"); + private static final Logger RENEW_LOGGER = LoggerFactory.getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[SessionRegistry]"); /** * store subscribers */ @Autowired - private Interests sessionInterests; + private Interests sessionInterests; /** * store watchers */ @Autowired - private Watchers sessionWatchers; + private Watchers sessionWatchers; /** * store publishers */ @Autowired - private DataStore sessionDataStore; + private DataStore sessionDataStore; /** * transfer data to DataNode */ @Autowired - private DataNodeService dataNodeService; + private DataNodeService dataNodeService; /** * trigger task com.alipay.sofa.registry.server.meta.listener process */ @Autowired - private TaskListenerManager taskListenerManager; + private TaskListenerManager taskListenerManager; /** * calculate data node url */ @Autowired - private NodeManager dataNodeManager; + private NodeManager dataNodeManager; @Autowired - private SessionServerConfig sessionServerConfig; + private SessionServerConfig sessionServerConfig; @Autowired - private Exchange boltExchange; + private Exchange boltExchange; @Autowired - private SessionRegistryStrategy sessionRegistryStrategy; + private SessionRegistryStrategy sessionRegistryStrategy; - @Override - public void register(StoreData storeData) { - - //check connect already existed - checkConnect(storeData); - - switch (storeData.getDataType()) { - case PUBLISHER: - Publisher publisher = (Publisher) storeData; - - dataNodeService.register(publisher); + @Autowired + private WrapperInterceptorManager wrapperInterceptorManager; - sessionDataStore.add(publisher); + @Autowired + private DataIdMatchStrategy dataIdMatchStrategy; - sessionRegistryStrategy.afterPublisherRegister(publisher); - break; - case SUBSCRIBER: - Subscriber subscriber = (Subscriber) storeData; + @Autowired + private RenewService renewService; - sessionInterests.add(subscriber); + @Autowired + private WriteDataAcceptor writeDataAcceptor; - sessionRegistryStrategy.afterSubscriberRegister(subscriber); - break; - case WATCHER: - Watcher watcher = (Watcher) storeData; + private volatile boolean enableDataRenewSnapshot = true; - sessionWatchers.add(watcher); + @Override + public void register(StoreData storeData) { - sessionRegistryStrategy.afterWatcherRegister(watcher); - break; - default: - break; + WrapperInvocation wrapperInvocation = new WrapperInvocation( + new Wrapper() { + @Override + public Boolean call() { + + switch (storeData.getDataType()) { + case PUBLISHER: + Publisher publisher = (Publisher) storeData; + + sessionDataStore.add(publisher); + + // All write operations to DataServer (pub/unPub/clientoff/renew/snapshot) + // are handed over to WriteDataAcceptor + writeDataAcceptor.accept(new WriteDataRequest() { + @Override + public Object getRequestBody() { + return publisher; + } + + @Override + public WriteDataRequestType getRequestType() { + return WriteDataRequestType.PUBLISHER; + } + + @Override + public String getConnectId() { + return publisher.getSourceAddress().getAddressString(); + } + + @Override + public String getDataServerIP() { + Node dataNode = dataNodeManager.getNode(publisher.getDataInfoId()); + return dataNode.getNodeUrl().getIpAddress(); + } + }); + + sessionRegistryStrategy.afterPublisherRegister(publisher); + break; + case SUBSCRIBER: + Subscriber subscriber = (Subscriber) storeData; + + sessionInterests.add(subscriber); + + sessionRegistryStrategy.afterSubscriberRegister(subscriber); + break; + case WATCHER: + Watcher watcher = (Watcher) storeData; + + sessionWatchers.add(watcher); + + sessionRegistryStrategy.afterWatcherRegister(watcher); + break; + default: + break; + } + return null; + } + + @Override + public Supplier getParameterSupplier() { + return () -> storeData; + } + + }, wrapperInterceptorManager); + + try { + wrapperInvocation.proceed(); + } catch (Exception e) { + throw new RuntimeException("Proceed register error!", e); } } @@ -149,7 +219,30 @@ public void unRegister(StoreData storeData) { sessionDataStore.deleteById(storeData.getId(), publisher.getDataInfoId()); - dataNodeService.unregister(publisher); + // All write operations to DataServer (pub/unPub/clientoff/renew/snapshot) + // are handed over to WriteDataAcceptor + writeDataAcceptor.accept(new WriteDataRequest() { + @Override + public Object getRequestBody() { + return publisher; + } + + @Override + public WriteDataRequestType getRequestType() { + return WriteDataRequestType.UN_PUBLISHER; + } + + @Override + public String getConnectId() { + return publisher.getSourceAddress().getAddressString(); + } + + @Override + public String getDataServerIP() { + Node dataNode = dataNodeManager.getNode(publisher.getDataInfoId()); + return dataNode.getNodeUrl().getIpAddress(); + } + }); sessionRegistryStrategy.afterPublisherUnRegister(publisher); break; @@ -175,9 +268,52 @@ public void unRegister(StoreData storeData) { @Override public void cancel(List connectIds) { - TaskEvent taskEvent = new TaskEvent(connectIds, TaskType.CANCEL_DATA_TASK); - TASK_LOGGER.info("send " + taskEvent.getTaskType() + " taskEvent:{}", taskEvent); - taskListenerManager.sendTaskEvent(taskEvent); + //update local firstly, data node send error depend on renew check + List connectIdsWithPub = new ArrayList<>(); + removeFromSession(connectIds, connectIdsWithPub); + + // clientOff to dataNode async + clientOffToDataNode(connectIdsWithPub); + + } + + private void removeFromSession(List connectIds, List connectIdsWithPub) { + for (String connectId : connectIds) { + if (sessionDataStore.deleteByConnectId(connectId)) { + connectIdsWithPub.add(connectId); + } + sessionInterests.deleteByConnectId(connectId); + sessionWatchers.deleteByConnectId(connectId); + } + } + + private void clientOffToDataNode(List connectIdsWithPub) { + // All write operations to DataServer (pub/unPub/clientoff/renew/snapshot) + // are handed over to WriteDataAcceptor + for (String connectId : connectIdsWithPub) { + writeDataAcceptor.accept(new WriteDataRequest() { + @Override + public Object getRequestBody() { + return connectId; + } + + @Override + public WriteDataRequestType getRequestType() { + return WriteDataRequestType.CLIENT_OFF; + } + + @Override + public String getConnectId() { + return connectId; + } + + @Override + public String getDataServerIP() { + return null; + } + }); + writeDataAcceptor.remove(connectId); + } } @Override @@ -228,10 +364,8 @@ private Map> calculateDataNode(Collection dat if (dataInfoIds != null) { dataInfoIds.forEach(dataInfoId -> { Node dataNode = dataNodeManager.getNode(dataInfoId); - URL url = new URL(dataNode.getNodeUrl().getIpAddress(), - sessionServerConfig.getDataServerPort()); - Collection list = map.computeIfAbsent(url.getAddressString(), - k -> new ArrayList<>()); + URL url = new URL(dataNode.getNodeUrl().getIpAddress(), sessionServerConfig.getDataServerPort()); + Collection list = map.computeIfAbsent(url.getAddressString(), k -> new ArrayList<>()); list.add(dataInfoId); }); } @@ -239,20 +373,136 @@ private Map> calculateDataNode(Collection dat return map; } - private void checkConnect(StoreData storeData) { + public void remove(List connectIds) { + + List connectIdsAll = new ArrayList<>(); + connectIds.forEach(connectId -> { + Map pubMap = getSessionDataStore().queryByConnectId(connectId); + boolean pubExisted = pubMap != null && !pubMap.isEmpty(); - BaseInfo baseInfo = (BaseInfo) storeData; + Map subMap = getSessionInterests().queryByConnectId(connectId); + boolean subExisted = false; + if (subMap != null && !subMap.isEmpty()) { + subExisted = true; + + subMap.forEach((registerId, sub) -> { + if (dataIdMatchStrategy + .match(sub.getDataId(), () -> sessionServerConfig.getBlacklistSubDataIdRegex())) { + fireSubscriberPushEmptyTask(sub); + } + }); + } + + if (pubExisted || subExisted) { + connectIdsAll.add(connectId); + } + }); + if (!connectIds.isEmpty()) { + TaskEvent taskEvent = new TaskEvent(connectIds, TaskEvent.TaskType.CANCEL_DATA_TASK); + TASK_LOGGER.info("send " + taskEvent.getTaskType() + " taskEvent:{}", taskEvent); + getTaskListenerManager().sendTaskEvent(taskEvent); + } + } + + private void fireSubscriberPushEmptyTask(Subscriber subscriber) { + //trigger empty data push + TaskEvent taskEvent = new TaskEvent(subscriber, + TaskEvent.TaskType.SUBSCRIBER_PUSH_EMPTY_TASK); + TASK_LOGGER.info("send " + taskEvent.getTaskType() + " taskEvent:{}", taskEvent); + getTaskListenerManager().sendTaskEvent(taskEvent); + } + + public void cleanClientConnect() { + + SetView intersection = Sets.union(sessionDataStore.getConnectPublishers().keySet(), + sessionInterests.getConnectSubscribers().keySet()); Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort()); - Channel channel = sessionServer.getChannel(baseInfo.getSourceAddress()); + List connectIds = new ArrayList<>(); + for (String connectId : intersection) { + Channel channel = sessionServer.getChannel(URL.valueOf(connectId)); + if (channel == null) { + connectIds.add(connectId); + LOGGER.warn("Client connect has not existed!it must be remove!connectId:{}", + connectId); + } + } + if (!connectIds.isEmpty()) { + cancel(connectIds); + } + } + + @Override + public void renewDatum(String connectId) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("renewDatum: connectId={}", connectId); + } + // check the renew switch + if (!this.enableDataRenewSnapshot) { + return; + } + + List renewDatumRequests = renewService.getRenewDatumRequests(connectId); + if (renewDatumRequests != null) { + for (RenewDatumRequest renewDatumRequest : renewDatumRequests) { + // All write operations to DataServer (pub/unPub/clientoff/renew/snapshot) + // are handed over to WriteDataAcceptor + writeDataAcceptor.accept(new WriteDataRequest() { + @Override + public Object getRequestBody() { + return renewDatumRequest; + } + + @Override + public WriteDataRequestType getRequestType() { + return WriteDataRequestType.RENEW_DATUM; + } + + @Override + public String getConnectId() { + return connectId; + } + + @Override + public String getDataServerIP() { + return renewDatumRequest.getDataServerIP(); + } + }); + } + } + } - if (channel == null) { - throw new RuntimeException(String.format( - "Register address %s has not connected session server!", - baseInfo.getSourceAddress())); + @Override + public void sendDatumSnapshot(String connectId, String dataServerIP) { + if (RENEW_LOGGER.isDebugEnabled()) { + RENEW_LOGGER.debug("sendDatumSnapshot: connectId={}, dataServerIP={}", connectId, + dataServerIP); } + // All write operations to DataServer (pub/unPub/clientoff/renew/snapshot) + // are handed over to WriteDataAcceptor + writeDataAcceptor.accept(new WriteDataRequest() { + @Override + public Object getRequestBody() { + return connectId; + } + + @Override + public WriteDataRequestType getRequestType() { + return WriteDataRequestType.DATUM_SNAPSHOT; + } + + @Override + public String getConnectId() { + return connectId; + } + + @Override + public String getDataServerIP() { + return dataServerIP; + } + }); } /** @@ -260,7 +510,7 @@ private void checkConnect(StoreData storeData) { * * @return property value of sessionInterests */ - public Interests getSessionInterests() { + protected Interests getSessionInterests() { return sessionInterests; } @@ -269,7 +519,7 @@ public Interests getSessionInterests() { * * @return property value of sessionDataStore */ - public DataStore getSessionDataStore() { + protected DataStore getSessionDataStore() { return sessionDataStore; } @@ -278,7 +528,17 @@ public DataStore getSessionDataStore() { * * @return property value of taskListenerManager */ - public TaskListenerManager getTaskListenerManager() { + protected TaskListenerManager getTaskListenerManager() { return taskListenerManager; } + + /** + * Setter method for property enableDataRenewSnapshot . + * + * @param enableDataRenewSnapshot value to be assigned to property enableDataRenewSnapshot + */ + @Override + public void setEnableDataRenewSnapshot(boolean enableDataRenewSnapshot) { + this.enableDataRenewSnapshot = enableDataRenewSnapshot; + } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/DataNodeExchanger.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/DataNodeExchanger.java index fb49eb26f..c3b2e2aef 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/DataNodeExchanger.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/DataNodeExchanger.java @@ -16,7 +16,14 @@ */ package com.alipay.sofa.registry.server.session.remoting; +import java.util.Collection; + +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; @@ -31,10 +38,6 @@ import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.remoting.handler.AbstractClientHandler; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.annotation.Resource; -import java.util.Collection; /** * The type Data node exchanger. @@ -84,20 +87,22 @@ public Response request(Request request) throws RequestException { if (channel == null) { channel = sessionClient.connect(url); } - EXCHANGE_LOGGER.info("DataNode Exchanger request={},url={}", request.getRequestBody(), url); - final Object result = sessionClient.sendSync(channel, request.getRequestBody(), - sessionServerConfig.getDataNodeExchangeTimeOut()); + // print but ignore if from renew module, cause renew request is too much + if (!(request.getRequestBody() instanceof RenewDatumRequest)) { + EXCHANGE_LOGGER.info("DataNode Exchanger request={},url={}", request.getRequestBody(), url); + } + + final Object result = sessionClient + .sendSync(channel, request.getRequestBody(), sessionServerConfig.getDataNodeExchangeTimeOut()); if (result == null) { - LOGGER.error("DataNode Exchanger request data get null result!Request url:" + url); - throw new RequestException("DataNode Exchanger request data get null result!", - request); + throw new RequestException("DataNode Exchanger request data get null result!", request); } response = () -> result; } catch (Exception e) { - LOGGER.error("DataNode Exchanger request data error!request={},url={}", request.getRequestBody(), url, e); - throw new RequestException("DataNode Exchanger request data error!Request url:" + url, - request, e); + LOGGER.error(String.format("Error when request DataNode! Request url=%s, request=%s, msg=%s", url, + request.getRequestBody(), e.getMessage())); + throw new RequestException("DataNode Exchanger request data error! Request url:" + url, request, e); } return response; diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/ClientNodeConnectionHandler.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/ClientNodeConnectionHandler.java index 6c0dab457..8efc82e9e 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/ClientNodeConnectionHandler.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/ClientNodeConnectionHandler.java @@ -16,21 +16,34 @@ */ package com.alipay.sofa.registry.server.session.remoting.handler; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang.math.RandomUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.net.NetUtil; import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.remoting.RemotingException; +import com.alipay.sofa.registry.remoting.Server; +import com.alipay.sofa.registry.remoting.exchange.Exchange; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.registry.Registry; import com.alipay.sofa.registry.server.session.scheduler.ExecutorManager; import com.alipay.sofa.registry.server.session.store.DataStore; import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.store.Watchers; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; +import com.alipay.sofa.registry.timer.RecycleAsyncHashedWheelTimer; +import com.google.common.util.concurrent.ThreadFactoryBuilder; /** * @@ -39,40 +52,80 @@ */ public class ClientNodeConnectionHandler extends AbstractServerHandler { - private static final Logger LOGGER = LoggerFactory.getLogger("SESSION-CONNECT"); + private static final Logger LOGGER = LoggerFactory.getLogger("SESSION-CONNECT"); + private static final Logger RENEW_LOGGER = LoggerFactory.getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[ClientNodeConnectionHandler]"); + + private RecycleAsyncHashedWheelTimer recycleAsyncHashedWheelTimer; + + @Autowired + private Registry sessionRegistry; + + @Autowired + private DataStore sessionDataStore; @Autowired - private Registry sessionRegistry; + private Interests sessionInterests; @Autowired - private DataStore sessionDataStore; + private Watchers sessionWatchers; @Autowired - private Interests sessionInterests; + private ExecutorManager executorManager; @Autowired - private Watchers sessionWatchers; + private SessionServerConfig sessionServerConfig; @Autowired - private ExecutorManager executorManager; + private Exchange boltExchange; + + @PostConstruct + public void init() { + ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); + threadFactoryBuilder.setDaemon(true); + recycleAsyncHashedWheelTimer = new RecycleAsyncHashedWheelTimer(threadFactoryBuilder + .setNameFormat("Registry-RenewDatumTask-WheelTimer").build(), + sessionServerConfig.getRenewDatumWheelTicksDuration(), TimeUnit.MILLISECONDS, + sessionServerConfig.getRenewDatumWheelTicksSize(), + sessionServerConfig.getRenewDatumWheelThreadSize(), + sessionServerConfig.getRenewDatumWheelQueueSize(), threadFactoryBuilder.setNameFormat( + "Registry-RenewDatumTask-WheelExecutor-%d").build(), new TaskFailedCallback() { + @Override + public void executionRejected(Throwable e) { + RENEW_LOGGER.error("executionRejected: " + e.getMessage(), e); + } + + @Override + public void executionFailed(Throwable e) { + RENEW_LOGGER.error("executionFailed: " + e.getMessage(), e); + } + }); + } @Override public HandlerType getType() { return HandlerType.LISENTER; } + @Override + public void connected(Channel channel) throws RemotingException { + super.connected(channel); + fireRenewDatum(channel); + } + @Override public void disconnected(Channel channel) throws RemotingException { super.disconnected(channel); fireCancelClient(channel); } - public void fireCancelClient(Channel channel) { + private void fireCancelClient(Channel channel) { //avoid block connect ConnectionEventExecutor thread pool - executorManager.getDisconnectClientExecutor().execute(()->{ + executorManager.getConnectClientExecutor().execute(() -> { String connectId = NetUtil.toAddressString(channel.getRemoteAddress()); - if(checkCache(connectId)) { + if (checkCache(connectId)) { List connectIds = new ArrayList<>(); connectIds.add(connectId); sessionRegistry.cancel(connectIds); @@ -103,4 +156,29 @@ private boolean checkWatcher(String connectId) { Map subMap = sessionWatchers.queryByConnectId(connectId); return subMap != null && !subMap.isEmpty(); } + + private void fireRenewDatum(Channel channel) { + executorManager.getConnectClientExecutor().execute(() -> { + String connectId = NetUtil.toAddressString(channel.getRemoteAddress()); + RENEW_LOGGER.info("Renew task is started: {}", connectId); + recycleAsyncHashedWheelTimer.newTimeout(timerOut -> sessionRegistry.renewDatum(connectId), randomDelay(), + sessionServerConfig.getRenewDatumWheelTaskDelaySec(), TimeUnit.SECONDS, () -> { + Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort()); + Channel channelClient = sessionServer.getChannel(URL.valueOf(connectId)); + boolean shouldContinue = channelClient != null && channel.isConnected(); + if (!shouldContinue) { + RENEW_LOGGER.info("Renew task is stop: {}", connectId); + } + return shouldContinue; + }); + }); + } + + private long randomDelay() { + return sessionServerConfig.getRenewDatumWheelTaskRandomFirstDelaySec() + / 2 + + RandomUtils.nextInt(sessionServerConfig + .getRenewDatumWheelTaskRandomFirstDelaySec() / 2); + } + } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/NotifyProvideDataChangeHandler.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/NotifyProvideDataChangeHandler.java index eb59882c1..57ca25d32 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/NotifyProvideDataChangeHandler.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/remoting/handler/NotifyProvideDataChangeHandler.java @@ -68,7 +68,10 @@ public Object reply(Channel channel, Object message) { NotifyProvideDataChange notifyProvideDataChange = (NotifyProvideDataChange) message; if (!ValueConstants.STOP_PUSH_DATA_SWITCH_DATA_ID.equals(notifyProvideDataChange - .getDataInfoId())) { + .getDataInfoId()) + && !ValueConstants.BLACK_LIST_DATA_ID.equals(notifyProvideDataChange.getDataInfoId()) + && !ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT.equals(notifyProvideDataChange + .getDataInfoId())) { boolean result = sessionWatchers.checkWatcherVersions( notifyProvideDataChange.getDataInfoId(), notifyProvideDataChange.getVersion()); if (!result) { diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/DefaultRenewService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/DefaultRenewService.java new file mode 100644 index 000000000..c630212e9 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/DefaultRenewService.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.renew; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.common.model.Node; +import com.alipay.sofa.registry.common.model.PublisherDigestUtil; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.server.session.node.NodeManager; +import com.alipay.sofa.registry.server.session.store.DataStore; + +/** + * + * @author kezhu.wukz + * @version $Id: DefaultRenewService.java, v 0.1 2019-06-27 11:09 kezhu.wukz Exp $ + */ +public class DefaultRenewService implements RenewService { + + /*** store publishers */ + @Autowired + private DataStore sessionDataStore; + + /*** calculate data node url */ + @Autowired + private NodeManager dataNodeManager; + + @Override + public List getRenewDatumRequests(String connectId) { + List datumSnapshotRequests = getDatumSnapshotRequest(connectId); + if (datumSnapshotRequests != null && !datumSnapshotRequests.isEmpty()) { + return datumSnapshotRequests.stream() + .map(datumSnapshotRequest -> new RenewDatumRequest(datumSnapshotRequest.getConnectId(), + datumSnapshotRequest.getDataServerIp(), String.valueOf( + PublisherDigestUtil.getDigestValueSum(datumSnapshotRequest.getPublishers())))) + .collect(Collectors.toList()); + } + return null; + } + + @Override + public List getDatumSnapshotRequest(String connectId) { + Map pubMap = sessionDataStore.queryByConnectId(connectId); + if (pubMap != null && !pubMap.isEmpty()) { + Map> dataServerIpToPubs = new ConcurrentHashMap<>(); + List list = new ArrayList<>(); + pubMap.values().forEach(publisher -> { + Node dataNode = dataNodeManager.getNode(publisher.getDataInfoId()); + List publishers = dataServerIpToPubs + .computeIfAbsent(dataNode.getNodeUrl().getIpAddress(), k -> new ArrayList<>()); + publishers.add(publisher); + }); + for (Map.Entry> entry : dataServerIpToPubs.entrySet()) { + List publishers = entry.getValue(); + if (!publishers.isEmpty()) { + DatumSnapshotRequest datumSnapshotRequest = new DatumSnapshotRequest(connectId, entry.getKey(), + publishers); + list.add(datumSnapshotRequest); + } + } + return list; + } + return null; + } + + @Override + public DatumSnapshotRequest getDatumSnapshotRequest(String connectId, String dataServerIP) { + List publishers = new ArrayList<>(); + Map pubMap = sessionDataStore.queryByConnectId(connectId); + if (pubMap != null && !pubMap.isEmpty()) { + pubMap.values().forEach(publisher -> { + Node dataNode = dataNodeManager.getNode(publisher.getDataInfoId()); + if (dataServerIP.equalsIgnoreCase(dataNode.getNodeUrl().getIpAddress())) { + publishers.add(publisher); + } + }); + } + if (!publishers.isEmpty()) { + return new DatumSnapshotRequest(connectId, dataServerIP, publishers); + } + return null; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/RenewService.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/RenewService.java new file mode 100644 index 000000000..ad760951f --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/renew/RenewService.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.renew; + +import java.util.List; + +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.common.model.RenewDatumRequest; + +/** + * + * @author kezhu.wukz + * @version $Id: RenewService.java, v 0.1 2019-06-27 11:06 kezhu.wukz Exp $ + */ +public interface RenewService { + + /** + * Get RenewDatumRequests based on connectId + * + * @param connectId + * @return + */ + List getRenewDatumRequests(String connectId); + + /** + * Get DatumSnapshotRequests based on connectId + * + * @param connectId + * @return + */ + List getDatumSnapshotRequest(String connectId); + + DatumSnapshotRequest getDatumSnapshotRequest(String connectId, String dataServerIP); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/HealthResource.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/HealthResource.java index 37afbd6c2..648acd736 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/HealthResource.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/HealthResource.java @@ -16,15 +16,23 @@ */ package com.alipay.sofa.registry.server.session.resource; -import com.alipay.sofa.registry.common.model.CommonResponse; -import com.alipay.sofa.registry.server.session.bootstrap.SessionServerBootstrap; -import com.alipay.sofa.registry.server.session.node.RaftClientManager; -import org.springframework.beans.factory.annotation.Autowired; - +import javax.annotation.PostConstruct; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.alipay.sofa.registry.common.model.CommonResponse; +import com.alipay.sofa.registry.metrics.ReporterUtils; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerBootstrap; +import com.alipay.sofa.registry.server.session.node.RaftClientManager; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.MetricRegistry; /** * @@ -40,11 +48,28 @@ public class HealthResource { @Autowired private SessionServerBootstrap sessionServerBootstrap; + @PostConstruct + public void init() { + MetricRegistry metrics = new MetricRegistry(); + metrics.register("healthCheck", (Gauge) () -> getHealthCheckResult()); + ReporterUtils.startSlf4jReporter(60, metrics); + } + @GET @Path("check") @Produces(MediaType.APPLICATION_JSON) - public CommonResponse checkHealth() { + public Response checkHealth() { + ResponseBuilder builder = Response.status(Response.Status.OK); + CommonResponse response = getHealthCheckResult(); + builder.entity(response); + if (!response.isSuccess()) { + builder.status(Status.INTERNAL_SERVER_ERROR); + } + + return builder.build(); + } + private CommonResponse getHealthCheckResult() { CommonResponse response; StringBuilder sb = new StringBuilder("SessionServerBoot "); @@ -78,7 +103,6 @@ public CommonResponse checkHealth() { } else { response = CommonResponse.buildFailedResponse(sb.toString()); } - return response; } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/SessionDigestResource.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/SessionDigestResource.java index 3bb5e1110..c8c9d071b 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/SessionDigestResource.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/resource/SessionDigestResource.java @@ -16,12 +16,32 @@ */ package com.alipay.sofa.registry.server.session.resource; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.store.Publisher; import com.alipay.sofa.registry.common.model.store.StoreData; import com.alipay.sofa.registry.common.model.store.Subscriber; import com.alipay.sofa.registry.common.model.store.Watcher; +import com.alipay.sofa.registry.metrics.ReporterUtils; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.node.NodeManagerFactory; @@ -29,22 +49,8 @@ import com.alipay.sofa.registry.server.session.store.DataStore; import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.store.Watchers; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.CollectionUtils; - -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.MetricRegistry; /** * @@ -87,6 +93,13 @@ public class SessionDigestResource { private final static String META = "META"; + @PostConstruct + public void init() { + MetricRegistry metrics = new MetricRegistry(); + metrics.register("pushSwitch", (Gauge) () -> getPushSwitch()); + ReporterUtils.startSlf4jReporter(60, metrics); + } + @GET @Path("{type}/data/query") @Produces(MediaType.APPLICATION_JSON) diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/ExecutorManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/ExecutorManager.java index cd11a6ae6..13ab127a1 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/ExecutorManager.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/ExecutorManager.java @@ -16,13 +16,18 @@ */ package com.alipay.sofa.registry.server.session.scheduler; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.metrics.TaskMetrics; import com.alipay.sofa.registry.remoting.exchange.NodeExchanger; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.registry.Registry; import com.alipay.sofa.registry.task.scheduler.TimedSupervisorTask; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer.TaskFailedCallback; import com.alipay.sofa.registry.util.NamedThreadFactory; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashMap; @@ -43,6 +48,9 @@ */ public class ExecutorManager { + private static final Logger LOGGER = LoggerFactory + .getLogger(ExecutorManager.class); + private final ScheduledExecutorService scheduler; private final ThreadPoolExecutor fetchDataExecutor; @@ -53,11 +61,13 @@ public class ExecutorManager { private final ThreadPoolExecutor connectDataExecutor; private final ExecutorService checkPushExecutor; - private final ExecutorService pushTaskClosureExecutor; private final ThreadPoolExecutor accessDataExecutor; private final ThreadPoolExecutor dataChangeRequestExecutor; private final ThreadPoolExecutor pushTaskExecutor; - private final ThreadPoolExecutor disconnectClientExecutor; + private final ThreadPoolExecutor connectClientExecutor; + private final ThreadPoolExecutor publishDataExecutor; + + private final AsyncHashedWheelTimer pushTaskCheckAsyncHashedWheelTimer; private SessionServerConfig sessionServerConfig; @@ -91,7 +101,9 @@ public class ExecutorManager { private static final String PUSH_TASK_CLOSURE_CHECK_EXECUTOR = "PushTaskClosureCheckExecutor"; - private static final String DISCONNECT_CLIENT_EXECUTOR = "DisconnectClientExecutor"; + private static final String CONNECT_CLIENT_EXECUTOR = "ConnectClientExecutor"; + + private static final String PUBLISH_DATA_EXECUTOR = "PublishDataExecutor"; public ExecutorManager(SessionServerConfig sessionServerConfig) { @@ -103,7 +115,7 @@ public ExecutorManager(SessionServerConfig sessionServerConfig) { new SynchronousQueue<>(), new NamedThreadFactory("SessionScheduler-fetchData")); renNewDataExecutor = new ThreadPoolExecutor(1, 2/*CONFIG*/, 0, TimeUnit.SECONDS, - new SynchronousQueue<>(), new NamedThreadFactory("SessionScheduler-reNewData")); + new SynchronousQueue<>(), new NamedThreadFactory("SessionScheduler-renewData")); getSessionNodeExecutor = new ThreadPoolExecutor(1, 2/*CONFIG*/, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), new NamedThreadFactory("SessionScheduler-getSessionNode")); @@ -152,20 +164,38 @@ public ExecutorManager(SessionServerConfig sessionServerConfig) { new LinkedBlockingQueue(100000), new NamedThreadFactory("UserDataElementPushCheck-executor", true))); - pushTaskClosureExecutor = reportExecutors - .computeIfAbsent(PUSH_TASK_CLOSURE_CHECK_EXECUTOR, k -> new SessionThreadPoolExecutor( - PUSH_TASK_CLOSURE_CHECK_EXECUTOR, 80, 400, 60L, - TimeUnit.SECONDS, - new LinkedBlockingQueue(10000), - new NamedThreadFactory("PushTaskClosureCheck", true))); - - disconnectClientExecutor = reportExecutors.computeIfAbsent(DISCONNECT_CLIENT_EXECUTOR,k->new SessionThreadPoolExecutor( - DISCONNECT_CLIENT_EXECUTOR, sessionServerConfig.getDisconnectClientExecutorMinPoolSize(), - sessionServerConfig.getDisconnectClientExecutorMaxPoolSize(), 60L, + connectClientExecutor = reportExecutors.computeIfAbsent(CONNECT_CLIENT_EXECUTOR,k->new SessionThreadPoolExecutor( + CONNECT_CLIENT_EXECUTOR, sessionServerConfig.getConnectClientExecutorMinPoolSize(), + sessionServerConfig.getConnectClientExecutorMaxPoolSize(), 60L, TimeUnit.SECONDS, - new LinkedBlockingQueue(sessionServerConfig.getDisconnectClientExecutorQueueSize()), + new LinkedBlockingQueue(sessionServerConfig.getConnectClientExecutorQueueSize()), new NamedThreadFactory("DisconnectClientExecutor", true))); + pushTaskCheckAsyncHashedWheelTimer = new AsyncHashedWheelTimer(new NamedThreadFactory("PushTaskConfirmCheck-executor", true), + sessionServerConfig.getPushTaskConfirmCheckWheelTicksDuration(), TimeUnit.MILLISECONDS, + sessionServerConfig.getPushTaskConfirmCheckWheelTicksSize(), + sessionServerConfig.getPushTaskConfirmCheckExecutorThreadSize(), + sessionServerConfig.getPushTaskConfirmCheckExecutorQueueSize(), new ThreadFactoryBuilder() + .setNameFormat("PushTaskConfirmCheck-executor-%d").build(), + new TaskFailedCallback() { + @Override + public void executionRejected(Throwable e) { + LOGGER.error("executionRejected: " + e.getMessage(), e); + } + + @Override + public void executionFailed(Throwable e) { + LOGGER.error("executionFailed: " + e.getMessage(), e); + } + }); + publishDataExecutor = reportExecutors + .computeIfAbsent(PUBLISH_DATA_EXECUTOR, k -> new SessionThreadPoolExecutor(PUBLISH_DATA_EXECUTOR, + sessionServerConfig.getPublishDataExecutorMinPoolSize(), + sessionServerConfig.getPublishDataExecutorMaxPoolSize(), + sessionServerConfig.getPublishDataExecutorKeepAliveTime(), + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(sessionServerConfig.getPublishDataExecutorQueueSize()), + new NamedThreadFactory("PublishData-executor", true))); } public void startScheduler() { @@ -177,10 +207,10 @@ public void startScheduler() { sessionServerConfig.getSchedulerFetchDataFirstDelay(), TimeUnit.SECONDS); scheduler.schedule( - new TimedSupervisorTask("ReNewData", scheduler, renNewDataExecutor, + new TimedSupervisorTask("RenewData", scheduler, renNewDataExecutor, sessionServerConfig.getSchedulerHeartbeatTimeout(), TimeUnit.SECONDS, sessionServerConfig.getSchedulerHeartbeatExpBackOffBound(), - () -> sessionNodeManager.reNewNode()), + () -> sessionNodeManager.renewNode()), sessionServerConfig.getSchedulerHeartbeatFirstDelay(), TimeUnit.SECONDS); scheduler.schedule( @@ -253,12 +283,12 @@ public void stopScheduler() { dataChangeRequestExecutor.shutdown(); } - if (pushTaskClosureExecutor != null && !pushTaskClosureExecutor.isShutdown()) { - pushTaskClosureExecutor.shutdown(); + if (connectClientExecutor != null && !connectClientExecutor.isShutdown()) { + connectClientExecutor.shutdown(); } - if (disconnectClientExecutor != null && !disconnectClientExecutor.isShutdown()) { - disconnectClientExecutor.shutdown(); + if (publishDataExecutor != null && !publishDataExecutor.isShutdown()) { + publishDataExecutor.shutdown(); } } @@ -282,12 +312,15 @@ public ThreadPoolExecutor getDataChangeRequestExecutor() { return dataChangeRequestExecutor; } - public ExecutorService getPushTaskClosureExecutor() { - return pushTaskClosureExecutor; + public ThreadPoolExecutor getConnectClientExecutor() { + return connectClientExecutor; } - public ThreadPoolExecutor getDisconnectClientExecutor() { - return disconnectClientExecutor; + public AsyncHashedWheelTimer getPushTaskCheckAsyncHashedWheelTimer() { + return pushTaskCheckAsyncHashedWheelTimer; } + public ThreadPoolExecutor getPublishDataExecutor() { + return publishDataExecutor; + } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/CancelDataTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/CancelDataTask.java index 17ef2a827..f07a089e2 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/CancelDataTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/CancelDataTask.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.registry.server.session.scheduler.task; +import java.util.List; + import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.service.DataNodeService; import com.alipay.sofa.registry.server.session.store.DataStore; @@ -23,9 +25,6 @@ import com.alipay.sofa.registry.server.session.store.Watchers; import com.alipay.sofa.registry.task.listener.TaskEvent; -import java.util.ArrayList; -import java.util.List; - /** * * @author shangyu.wh @@ -61,23 +60,7 @@ public CancelDataTask(Interests sessionInterests, DataStore sessionDataStore, @Override public void execute() { - if (connectIds.isEmpty()) { - throw new IllegalArgumentException("Input clientOff connectIds error!"); - } - - //remove local first,data node send error depend on other task check - List connectIdsPub = new ArrayList<>(); - for (String connectId : connectIds) { - - if (sessionDataStore.deleteByConnectId(connectId)) { - connectIdsPub.add(connectId); - } - sessionInterests.deleteByConnectId(connectId); - - sessionWatchers.deleteByConnectId(connectId); - } - - dataNodeService.clientOff(connectIdsPub); + dataNodeService.clientOff(connectIds); } @Override @@ -89,9 +72,11 @@ public void setTaskEvent(TaskEvent taskEvent) { } Object obj = taskEvent.getEventObj(); - if (obj instanceof List) { this.connectIds = (List) obj; + if (connectIds.isEmpty()) { + throw new IllegalArgumentException("Input clientOff connectIds error!"); + } } else { throw new IllegalArgumentException("Input task event object error!"); } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchCloudTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchCloudTask.java index 0a31df7ce..29c00dca3 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchCloudTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchCloudTask.java @@ -16,6 +16,15 @@ */ package com.alipay.sofa.registry.server.session.scheduler.task; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + import com.alipay.sofa.registry.common.model.Node.NodeType; import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.store.BaseInfo.ClientVersion; @@ -26,6 +35,7 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.cache.CacheAccessException; import com.alipay.sofa.registry.server.session.cache.CacheService; import com.alipay.sofa.registry.server.session.cache.DatumKey; import com.alipay.sofa.registry.server.session.cache.Key; @@ -42,15 +52,6 @@ import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - /** * * @author shangyu.wh @@ -151,7 +152,8 @@ public void execute() { } public PushTaskClosure getTaskClosure(Map datumMap) { - PushTaskClosure pushTaskClosure = new PushTaskClosure(executorManager.getPushTaskClosureExecutor()); + PushTaskClosure pushTaskClosure = new PushTaskClosure(executorManager.getPushTaskCheckAsyncHashedWheelTimer(), + sessionServerConfig, fetchDataInfoId); pushTaskClosure.setTaskClosure((status, task) -> { if (status == ProcessingResult.Success) { if (sessionServerConfig.isStopPushSwitch()) { @@ -168,8 +170,7 @@ public PushTaskClosure getTaskClosure(Map datumMap) } else { LOGGER.info( "Push all tasks success,but dataCenter:{} dataInfoId:{} version:{} need not update!", - dataCenter, - dataInfoId, version); + dataCenter, dataInfoId, version); } }); } else { @@ -204,7 +205,12 @@ private Map getDatumsCache() { new DatumKey(fetchDataInfoId, dataCenter))). collect(Collectors.toList()); - Map values = sessionCacheService.getValues(keys); + Map values = null; + try { + values = sessionCacheService.getValues(keys); + } catch (CacheAccessException e) { + LOGGER.error(String.format("error when access cache: %s", e.getMessage()), e); + } if (values != null) { values.forEach((key, value) -> { diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchTask.java index 8a95b8548..626088eb5 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DataChangeFetchTask.java @@ -16,6 +16,15 @@ */ package com.alipay.sofa.registry.server.session.scheduler.task; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Predicate; + import com.alipay.sofa.registry.common.model.dataserver.Datum; import com.alipay.sofa.registry.common.model.sessionserver.DataChangeRequest; import com.alipay.sofa.registry.common.model.store.BaseInfo.ClientVersion; @@ -26,6 +35,7 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.cache.CacheAccessException; import com.alipay.sofa.registry.server.session.cache.CacheService; import com.alipay.sofa.registry.server.session.cache.DatumKey; import com.alipay.sofa.registry.server.session.cache.Key; @@ -39,15 +49,7 @@ import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Predicate; +import com.alipay.sofa.registry.util.DatumVersionUtil; /** * @@ -116,12 +118,6 @@ public void execute() { Collection subscribersSend = subscribersVersionCheck(subscriberMap .values()); if (subscribersSend.isEmpty()) { - LOGGER - .warn( - "Subscribers to send empty,which dataInfoId:{} on dataCenter:{},scope:{},address:{},size:{}", - dataChangeRequest.getDataInfoId(), - dataChangeRequest.getDataCenter(), scopeEnum, - entry.getKey(), subscriberMap.size()); continue; } @@ -194,7 +190,8 @@ private Collection subscribersVersionCheck(Collection su public PushTaskClosure getTaskClosure() { //this for all this dataInfoId push result get and call back to change version - PushTaskClosure pushTaskClosure = new PushTaskClosure(executorManager.getPushTaskClosureExecutor()); + PushTaskClosure pushTaskClosure = new PushTaskClosure(executorManager.getPushTaskCheckAsyncHashedWheelTimer(), + sessionServerConfig, dataChangeRequest.getDataInfoId()); pushTaskClosure.setTaskClosure((status, task) -> { String dataCenter = dataChangeRequest.getDataCenter(); String dataInfoId = dataChangeRequest.getDataInfoId(); @@ -212,8 +209,7 @@ public PushTaskClosure getTaskClosure() { dataInfoId, version); } else { LOGGER.info("Push all tasks success,but dataCenter:{} dataInfoId:{} version:{} need not update!", - dataCenter, - dataInfoId, version); + dataCenter, dataInfoId, version); } } else { LOGGER.warn( @@ -232,9 +228,8 @@ private void evictReSubscribers(Collection subscribersPush) { } private void fireReceivedDataMultiPushTask(Datum datum, List subscriberRegisterIdList, - Collection subscribers, - ScopeEnum scopeEnum, Subscriber subscriber, - PushTaskClosure pushTaskClosure) { + Collection subscribers, ScopeEnum scopeEnum, + Subscriber subscriber, PushTaskClosure pushTaskClosure) { String dataId = datum.getDataId(); Predicate zonePredicate = (zone) -> { if (!sessionServerConfig.getSessionServerRegion().equals(zone)) { @@ -244,14 +239,15 @@ private void fireReceivedDataMultiPushTask(Datum datum, List subscriberR } else if (ScopeEnum.dataCenter == scopeEnum) { // disable zone config - return sessionServerConfig.isInvalidForeverZone(zone) - && !sessionServerConfig.isInvalidIgnored(dataId); + return sessionServerConfig.isInvalidForeverZone(zone) && !sessionServerConfig + .isInvalidIgnored(dataId); } } return false; }; - ReceivedData receivedData = ReceivedDataConverter.getReceivedDataMulti(datum, scopeEnum, - subscriberRegisterIdList, sessionServerConfig.getSessionServerRegion(), zonePredicate); + ReceivedData receivedData = ReceivedDataConverter + .getReceivedDataMulti(datum, scopeEnum, subscriberRegisterIdList, + sessionServerConfig.getSessionServerRegion(), zonePredicate); //trigger push to client node Map parameter = new HashMap<>(); @@ -259,8 +255,8 @@ private void fireReceivedDataMultiPushTask(Datum datum, List subscriberR TaskEvent taskEvent = new TaskEvent(parameter, TaskType.RECEIVED_DATA_MULTI_PUSH_TASK); taskEvent.setTaskClosure(pushTaskClosure); taskEvent.setAttribute(Constant.PUSH_CLIENT_SUBSCRIBERS, subscribers); - taskLogger.info("send {} taskURL:{},taskScope:{},,taskId={}", taskEvent.getTaskType(), subscriber.getSourceAddress(), - scopeEnum,taskEvent.getTaskId()); + taskLogger.info("send {} taskURL:{},taskScope:{},,taskId={}", taskEvent.getTaskType(), + subscriber.getSourceAddress(), scopeEnum, taskEvent.getTaskId()); taskListenerManager.sendTaskEvent(taskEvent); } @@ -272,7 +268,14 @@ private Datum getDatumCache() { DatumKey datumKey = new DatumKey(dataChangeRequest.getDataInfoId(), dataChangeRequest.getDataCenter()); Key key = new Key(KeyType.OBJ, datumKey.getClass().getName(), datumKey); - Value value = sessionCacheService.getValue(key); + + Value value = null; + try { + value = sessionCacheService.getValue(key); + } catch (CacheAccessException e) { + LOGGER.error(String.format("error when access cache: %s", e.getMessage()), e); + } + return value == null ? null : value.getPayload(); } @@ -282,7 +285,7 @@ private void fireUserDataElementPushTask(InetSocketAddress address, Datum datum, TaskEvent taskEvent = new TaskEvent(TaskType.USER_DATA_ELEMENT_PUSH_TASK); taskEvent.setTaskClosure(pushTaskClosure); - taskEvent.setSendTimeStamp(datum.getVersion()); + taskEvent.setSendTimeStamp(DatumVersionUtil.getRealTimestamp(datum.getVersion())); taskEvent.setAttribute(Constant.PUSH_CLIENT_SUBSCRIBERS, subscribers); taskEvent.setAttribute(Constant.PUSH_CLIENT_DATUM, datum); taskEvent.setAttribute(Constant.PUSH_CLIENT_URL, new URL(address)); @@ -302,7 +305,7 @@ private void fireUserDataElementMultiPushTask(InetSocketAddress address, Datum d TaskEvent taskEvent = new TaskEvent(TaskType.USER_DATA_ELEMENT_MULTI_PUSH_TASK); taskEvent.setTaskClosure(pushTaskClosure); - taskEvent.setSendTimeStamp(datum.getVersion()); + taskEvent.setSendTimeStamp(DatumVersionUtil.getRealTimestamp(datum.getVersion())); taskEvent.setAttribute(Constant.PUSH_CLIENT_SUBSCRIBERS, subscribers); taskEvent.setAttribute(Constant.PUSH_CLIENT_DATUM, datum); taskEvent.setAttribute(Constant.PUSH_CLIENT_URL, new URL(address)); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DatumSnapshotTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DatumSnapshotTask.java new file mode 100644 index 000000000..ae7d88f6e --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/DatumSnapshotTask.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.scheduler.task; + +import com.alipay.sofa.registry.common.model.DatumSnapshotRequest; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.task.listener.TaskEvent; + +/** + * + * @author kezhu.wukz + * @version $Id: DatumSnapshotTask.java, v 0.1 2019-06-14 12:15 kezhu.wukz Exp $ + */ +public class DatumSnapshotTask extends AbstractSessionTask { + /** + * transfer data to DataNode + */ + private final DataNodeService dataNodeService; + + private DatumSnapshotRequest datumSnapshotRequest; + + public DatumSnapshotTask(DataNodeService dataNodeService) { + this.dataNodeService = dataNodeService; + } + + @Override + public void execute() { + dataNodeService.sendDatumSnapshot(datumSnapshotRequest); + } + + @Override + public void setTaskEvent(TaskEvent taskEvent) { + //taskId create from event + if (taskEvent.getTaskId() != null) { + setTaskId(taskEvent.getTaskId()); + } + + Object obj = taskEvent.getEventObj(); + if (obj instanceof DatumSnapshotRequest) { + this.datumSnapshotRequest = (DatumSnapshotRequest) obj; + } else { + throw new IllegalArgumentException("Input task event object error!"); + } + } + + @Override + public String toString() { + return String.format("DATUM_SNAPSHOT_TASK{ taskId=%s, datumSnapshotRequest=%s }", + getTaskId(), datumSnapshotRequest); + } + + @Override + public boolean checkRetryTimes() { + //dataNodeService.sendDatumSnapshot will be retry all the failed + return false; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ProvideDataChangeFetchTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ProvideDataChangeFetchTask.java index 7d6c69ca9..3f398d1aa 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ProvideDataChangeFetchTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ProvideDataChangeFetchTask.java @@ -16,6 +16,18 @@ */ package com.alipay.sofa.registry.server.session.scheduler.task; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.springframework.util.CollectionUtils; + import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.metaserver.DataOperator; import com.alipay.sofa.registry.common.model.metaserver.NotifyProvideDataChange; @@ -33,6 +45,8 @@ import com.alipay.sofa.registry.remoting.exchange.Exchange; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.converter.ReceivedDataConverter; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistConstants; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistManager; import com.alipay.sofa.registry.server.session.node.service.MetaNodeService; import com.alipay.sofa.registry.server.session.registry.Registry; import com.alipay.sofa.registry.server.session.store.Interests; @@ -41,15 +55,6 @@ import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import org.springframework.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; /** * @@ -82,13 +87,15 @@ public class ProvideDataChangeFetchTask extends AbstractSessionTask { private final Registry sessionRegistry; + private final BlacklistManager blacklistManager; + private NotifyProvideDataChange notifyProvideDataChange; public ProvideDataChangeFetchTask(SessionServerConfig sessionServerConfig, TaskListenerManager taskListenerManager, MetaNodeService metaNodeService, Watchers sessionWatchers, Exchange boltExchange, Interests sessionInterests, - Registry sessionRegistry) { + Registry sessionRegistry, BlacklistManager blacklistManager) { this.sessionServerConfig = sessionServerConfig; this.taskListenerManager = taskListenerManager; this.metaNodeService = metaNodeService; @@ -96,6 +103,7 @@ public ProvideDataChangeFetchTask(SessionServerConfig sessionServerConfig, this.boltExchange = boltExchange; this.sessionInterests = sessionInterests; this.sessionRegistry = sessionRegistry; + this.blacklistManager = blacklistManager; } @Override @@ -123,6 +131,7 @@ public void execute() { provideData = metaNodeService.fetchData(dataInfoId); if (ValueConstants.STOP_PUSH_DATA_SWITCH_DATA_ID.equals(dataInfoId)) { + //push stop switch if (provideData != null) { if (provideData.getProvideData() == null || provideData.getProvideData().getObject() == null) { LOGGER.info("Fetch session stop push switch no data existed,config not change!"); @@ -153,7 +162,35 @@ public void execute() { LOGGER.info("Fetch session stop push switch data null,config not change!"); } return; + } else if (ValueConstants.BLACK_LIST_DATA_ID.equals(dataInfoId)) { + //black list data + if (provideData.getProvideData() == null || provideData.getProvideData().getObject() == null) { + LOGGER.info("Fetch session blacklist no data existed,current config not change!"); + return; + } + String data = (String) provideData.getProvideData().getObject(); + if (data != null) { + Map>> blacklistConfigMap = blacklistManager + .convertBlacklistConfig(data); + clientOffBlackIp(blacklistConfigMap); + LOGGER.info("Fetch session blacklist data switch {} success!", data); + } else { + LOGGER.info("Fetch session blacklist data null,current config not change!"); + } + return; + } else if (ValueConstants.ENABLE_DATA_RENEW_SNAPSHOT.equals(dataInfoId)) { + //stop renew switch + if (provideData == null || provideData.getProvideData() == null + || provideData.getProvideData().getObject() == null) { + LOGGER.info("Fetch enableDataRenewSnapshot but no data existed, current config not change!"); + return; + } + boolean enableDataRenewSnapshot = Boolean.parseBoolean((String) provideData.getProvideData().getObject()); + LOGGER.info("Fetch enableDataRenewSnapshot {} success!", enableDataRenewSnapshot); + this.sessionRegistry.setEnableDataRenewSnapshot(enableDataRenewSnapshot); + return; } + if (provideData == null) { LOGGER.warn("Notify provider data Change request {} fetch no provider data!", notifyProvideDataChange); return; @@ -177,11 +214,12 @@ public void execute() { if (!registerIds.isEmpty()) { ReceivedConfigData receivedConfigData; if (notifyProvideDataChange.getDataOperator() == DataOperator.REMOVE) { - receivedConfigData = ReceivedDataConverter.getReceivedConfigData(null, dataInfo, - notifyProvideDataChange.getVersion()); + receivedConfigData = ReceivedDataConverter + .getReceivedConfigData(null, dataInfo, notifyProvideDataChange.getVersion()); } else { - receivedConfigData = ReceivedDataConverter.getReceivedConfigData( - provideData.getProvideData(), dataInfo, provideData.getVersion()); + receivedConfigData = ReceivedDataConverter + .getReceivedConfigData(provideData.getProvideData(), dataInfo, + provideData.getVersion()); } receivedConfigData.setConfiguratorRegistIds(registerIds); firePushTask(receivedConfigData, new URL(channel.getRemoteAddress())); @@ -200,7 +238,7 @@ private void fireReSubscriber() { //begin push fire data fetch task first,avoid reSubscriber push duplicate sessionRegistry.fetchChangDataProcess(); } catch (Throwable e) { - LOGGER.error("Open push switch first fetch task execute error",e); + LOGGER.error("Open push switch first fetch task execute error", e); } try { @@ -247,6 +285,53 @@ private void firePushTask(ReceivedConfigData receivedConfigData, URL clientUrl) taskListenerManager.sendTaskEvent(taskEvent); } + private void clientOffBlackIp(Map>> blacklistConfigMap) { + + if (blacklistConfigMap != null) { + Set ipSet = new HashSet(); + + for (Map.Entry>> configEntry : blacklistConfigMap + .entrySet()) { + if (BlacklistConstants.FORBIDDEN_PUB.equals(configEntry.getKey()) + || BlacklistConstants.FORBIDDEN_SUB_BY_PREFIX.equals(configEntry.getKey())) { + Map> typeMap = configEntry.getValue(); + if (typeMap != null) { + for (Map.Entry> typeEntry : typeMap.entrySet()) { + if (BlacklistConstants.IP_FULL.equals(typeEntry.getKey())) { + if (typeEntry.getValue() != null) { + ipSet.addAll(typeEntry.getValue()); + } + } + } + } + } + + } + + sessionRegistry.remove(getIpConnects(ipSet)); + } + } + + public List getIpConnects(Set _ipList) { + + Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort()); + + List connections = new ArrayList<>(); + + if (sessionServer != null) { + Collection channels = sessionServer.getChannels(); + for (Channel channel : channels) { + String key = NetUtil.toAddressString(channel.getRemoteAddress()); + String ip = key.substring(0, key.indexOf(":")); + if (_ipList.contains(ip)) { + connections.add(key); + } + } + } + + return connections; + } + private Map getCache(String connectId) { Map map = sessionWatchers.queryByConnectId(connectId); return map == null ? new ConcurrentHashMap<>() : map; diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PublishDataTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PublishDataTask.java new file mode 100644 index 000000000..b5fa227a3 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PublishDataTask.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.scheduler.task; + +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.task.listener.TaskEvent; + +/** + * + * @author kezhu.wukz + * @version $Id: PublishDataTask.java, v 0.1 2019-06-14 12:15 kezhu.wukz Exp $ + */ +public class PublishDataTask extends AbstractSessionTask { + + private final DataNodeService dataNodeService; + + private Publisher publisher; + + public PublishDataTask(DataNodeService dataNodeService) { + this.dataNodeService = dataNodeService; + } + + @Override + public void execute() { + dataNodeService.register(publisher); + } + + @Override + public void setTaskEvent(TaskEvent taskEvent) { + //taskId create from event + if (taskEvent.getTaskId() != null) { + setTaskId(taskEvent.getTaskId()); + } + + Object obj = taskEvent.getEventObj(); + if (obj instanceof Publisher) { + this.publisher = (Publisher) obj; + } else { + throw new IllegalArgumentException("Input task event object error!"); + } + } + + @Override + public String toString() { + return String + .format("PUBLISH_DATA_TASK{ taskId=%s, publisher=%s }", getTaskId(), publisher); + } + + @Override + public boolean checkRetryTimes() { + //dataNodeService.register will be retry all the failed + return false; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PushTaskClosure.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PushTaskClosure.java index 68a7a4b45..a2683dcda 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PushTaskClosure.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/PushTaskClosure.java @@ -18,16 +18,15 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.task.Task; import com.alipay.sofa.registry.task.TaskClosure; import com.alipay.sofa.registry.task.batcher.TaskProcessor.ProcessingResult; import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.timer.AsyncHashedWheelTimer; import java.util.Set; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** @@ -37,31 +36,37 @@ */ public class PushTaskClosure implements TaskClosure { - private final static Logger LOGGER = LoggerFactory - .getLogger(PushTaskClosure.class); + private final static Logger LOGGER = LoggerFactory + .getLogger(PushTaskClosure.class); - private Set tasks = ConcurrentHashMap - .newKeySet(); + private Set tasks = ConcurrentHashMap + .newKeySet(); - private ConcurrentHashMap taskResultMap = new ConcurrentHashMap<>(); + private ConcurrentHashMap taskResultMap = new ConcurrentHashMap<>(); private TaskClosure taskClosure; - private final BlockingQueue completionQueue = new LinkedBlockingQueue<>(); + private final AsyncHashedWheelTimer pushTaskCheckAsyncHashedWheelTimer; - private final ExecutorService pushTaskClosureExecutor; + private final SessionServerConfig sessionServerConfig; - public PushTaskClosure(ExecutorService pushTaskClosureExecutor) { - this.pushTaskClosureExecutor = pushTaskClosureExecutor; + private final String dataInfoId; + + public PushTaskClosure(AsyncHashedWheelTimer pushTaskCheckAsyncHashedWheelTimer, + SessionServerConfig sessionServerConfig, String dataInfoId) { + this.pushTaskCheckAsyncHashedWheelTimer = pushTaskCheckAsyncHashedWheelTimer; + this.sessionServerConfig = sessionServerConfig; + this.dataInfoId = dataInfoId; } @Override public void run(ProcessingResult processingResult, Task task) { if (task != null) { - ProcessingResult existed = taskResultMap - .putIfAbsent(task.getTaskId(), processingResult); - if (existed == null) { - completionQueue.add(task.getTaskId()); + ProcessingResult result = taskResultMap.putIfAbsent(task.getTaskId(), processingResult); + if (result == null) { + if (processingResult == ProcessingResult.Success) { + tasks.remove(task.getTaskId()); + } } } } @@ -71,36 +76,24 @@ public void addTask(TaskEvent taskEvent) { } public void start() { - pushTaskClosureExecutor.execute(() -> { - try { - int size = tasks.size(); - LOGGER.info("Push task queue size {},all task size {}", completionQueue.size(), size); - for (int i = 0; i < size; i++) { - String taskId = completionQueue.poll(6000, TimeUnit.MILLISECONDS); - if(taskId != null) { - ProcessingResult result = taskResultMap.get(taskId); - if (result == ProcessingResult.Success) { - tasks.remove(taskId); - } - } - } - } catch (InterruptedException e) { - LOGGER.error("Push task check InterruptedException!", e); - } + int size = tasks.size(); + LOGGER.info("Push task confirm,dataInfoId={},all task size={}", dataInfoId, size); + + pushTaskCheckAsyncHashedWheelTimer.newTimeout(timeout -> { if (tasks.isEmpty()) { - LOGGER.info("Push all tasks success"); + LOGGER.info("Push all tasks success,dataInfoId={}",dataInfoId); if (taskClosure != null) { taskClosure.run(ProcessingResult.Success, null); } - } else { - LOGGER.warn("Push tasks found error tasks {} !", tasks.size()); + LOGGER.warn("Push tasks found error tasks {},dataInfoId={}!", tasks.size(),dataInfoId); if (taskClosure != null) { taskClosure.run(ProcessingResult.PermanentError, null); } } - }); + + },sessionServerConfig.getPushTaskConfirmWaitTimeout(),TimeUnit.MILLISECONDS); } /** diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ReceivedDataMultiPushTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ReceivedDataMultiPushTask.java index 52328b44e..4539fed32 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ReceivedDataMultiPushTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/ReceivedDataMultiPushTask.java @@ -17,6 +17,7 @@ package com.alipay.sofa.registry.server.session.scheduler.task; import com.alipay.sofa.registry.common.model.PushDataRetryRequest; +import com.alipay.sofa.registry.common.model.store.DataInfo; import com.alipay.sofa.registry.common.model.store.Subscriber; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.core.model.DataBox; @@ -30,6 +31,7 @@ import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.node.service.ClientNodeService; import com.alipay.sofa.registry.server.session.scheduler.ExecutorManager; +import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.strategy.ReceivedDataMultiPushTaskStrategy; import com.alipay.sofa.registry.task.Task; import com.alipay.sofa.registry.task.TaskClosure; @@ -63,6 +65,7 @@ public class ReceivedDataMultiPushTask extends AbstractSessionTask implements Ta private Collection subscribers; private ReceivedDataMultiPushTaskStrategy receivedDataMultiPushTaskStrategy; private AsyncHashedWheelTimer asyncHashedWheelTimer; + private Interests sessionInterests; private String dataPush; @@ -71,65 +74,75 @@ public ReceivedDataMultiPushTask(SessionServerConfig sessionServerConfig, ExecutorManager executorManager, Exchange boltExchange, ReceivedDataMultiPushTaskStrategy receivedDataMultiPushTaskStrategy, - AsyncHashedWheelTimer asyncHashedWheelTimer) { + AsyncHashedWheelTimer asyncHashedWheelTimer, + Interests sessionInterests) { this.sessionServerConfig = sessionServerConfig; this.clientNodeService = clientNodeService; this.executorManager = executorManager; this.boltExchange = boltExchange; this.receivedDataMultiPushTaskStrategy = receivedDataMultiPushTaskStrategy; this.asyncHashedWheelTimer = asyncHashedWheelTimer; + this.sessionInterests = sessionInterests; } @Override public void execute() { - - if (sessionServerConfig.isStopPushSwitch()) { - LOGGER - .info( - "Stop Push ReceivedData with switch on! dataId: {},group: {},Instance: {}, url: {}", - receivedData.getDataId(), receivedData.getGroup(), - receivedData.getInstanceId(), url); - return; - } - - Object receivedDataPush = receivedDataMultiPushTaskStrategy.convert2PushData(receivedData, - url); - - CallbackHandler callbackHandler = new CallbackHandler() { - @Override - public void onCallback(Channel channel, Object message) { + Object receivedDataPush = null; + try { + if (sessionServerConfig.isStopPushSwitch()) { LOGGER .info( - "Push ReceivedData success! dataId:{},group:{},Instance:{},version:{},url: {},dataPush:{}", + "Stop Push ReceivedData with switch on! dataId: {},group: {},Instance: {}, url: {}", receivedData.getDataId(), receivedData.getGroup(), - receivedData.getInstanceId(), receivedData.getVersion(), url, dataPush); - - if (taskClosure != null) { - confirmCallBack(true); - } + receivedData.getInstanceId(), url); + return; } - @Override - public void onException(Channel channel, Throwable exception) { - LOGGER - .error( - "Push ReceivedData error! dataId:{},group:{},Instance:{},version:{},url: {},dataPush:{}", - receivedData.getDataId(), receivedData.getGroup(), - receivedData.getInstanceId(), receivedData.getVersion(), url, dataPush, - exception); + receivedDataPush = receivedDataMultiPushTaskStrategy + .convert2PushData(receivedData, url); + + final Object finalReceivedDataPush = receivedDataPush; + CallbackHandler callbackHandler = new CallbackHandler() { + @Override + public void onCallback(Channel channel, Object message) { + + if (taskClosure != null) { + confirmCallBack(true); + } + LOGGER + .info( + "Push ReceivedData success! dataId:{},group:{},Instance:{},version:{},url: {},dataPush:{}", + receivedData.getDataId(), receivedData.getGroup(), + receivedData.getInstanceId(), receivedData.getVersion(), url, dataPush); + } - if (taskClosure != null) { - confirmCallBack(false); - throw new RuntimeException("Push ReceivedData got exception from callback!"); - } else { - retrySendReceiveData(new PushDataRetryRequest(receivedDataPush, url)); + @Override + public void onException(Channel channel, Throwable exception) { + try { + LOGGER + .error( + "Push ReceivedData error! dataId:{},group:{},Instance:{},version:{},url: {},dataPush:{}", + receivedData.getDataId(), receivedData.getGroup(), + receivedData.getInstanceId(), receivedData.getVersion(), url, + dataPush, exception); + + if (taskClosure != null) { + throw new RuntimeException( + "Push ReceivedData got exception from callback!"); + } else { + retrySendReceiveData(new PushDataRetryRequest(finalReceivedDataPush, + url)); + } + } finally { + if (taskClosure != null) { + confirmCallBack(false); + } + } } - } - }; + }; - try { clientNodeService.pushWithCallback(receivedDataPush, url, callbackHandler); - } catch (Exception e) { + } catch (Throwable e) { if (taskClosure != null) { confirmCallBack(false); throw e; @@ -156,36 +169,57 @@ private void retrySendReceiveData(PushDataRetryRequest pushDataRetryRequest) { if (channel != null && channel.isConnected()) { - asyncHashedWheelTimer.newTimeout(timeout -> { + asyncHashedWheelTimer.newTimeout(timeout -> { try { clientNodeService.pushWithCallback(infoPackage, targetUrl, new CallbackHandler() { @Override public void onCallback(Channel channel, Object message) { - LOGGER.info("Retry Push ReceivedData success! dataId:{}, group:{},url:{},taskId:{},dataPush:{},retryTimes:{}", - receivedData.getDataId(), receivedData.getGroup(), targetUrl,getTaskId(),dataPush,retryTimes); + LOGGER.info( + "Retry Push ReceivedData success! dataId:{}, group:{},url:{},taskId:{},dataPush:{},retryTimes:{}", + receivedData.getDataId(), receivedData.getGroup(), targetUrl, getTaskId(), + dataPush, retryTimes); } @Override public void onException(Channel channel, Throwable exception) { - LOGGER.error("Retry Push ReceivedData callback error! url:{}, dataId:{}, group:{},taskId:{},dataPush:{},retryTimes:{}", targetUrl, - receivedData.getDataId(), receivedData.getGroup(),getTaskId(),dataPush,retryTimes); + LOGGER.error( + "Retry Push ReceivedData callback error! url:{}, dataId:{}, group:{},taskId:{},dataPush:{},retryTimes:{}", + targetUrl, receivedData.getDataId(), receivedData.getGroup(), getTaskId(), + dataPush, retryTimes); retrySendReceiveData(pushDataRetryRequest); } }); } catch (Exception e) { - LOGGER.error("Retry Push ReceivedData error! url:{}, dataId:{}, group:{},taskId:{},dataPush:{},retryTimes:{}", targetUrl, - receivedData.getDataId(), receivedData.getGroup(),getTaskId(),dataPush,retryTimes); + LOGGER.error( + "Retry Push ReceivedData error! url:{}, dataId:{}, group:{},taskId:{},dataPush:{},retryTimes:{}", + targetUrl, receivedData.getDataId(), receivedData.getGroup(), getTaskId(), dataPush, + retryTimes); retrySendReceiveData(pushDataRetryRequest); } },getBlockTime(retryTimes),TimeUnit.MILLISECONDS); } else { - LOGGER.error("Retry Push ReceivedData error, connect be null or disconnected,stop retry!dataId:{}, group:{},url:{},taskId:{},dataPush:{},retryTimes:{}", - receivedData.getDataId(), receivedData.getGroup(), targetUrl,getTaskId(),dataPush,retryTimes); + LOGGER.error( + "Retry Push ReceivedData error, connect be null or disconnected,stop retry!dataId:{}, group:{},url:{},taskId:{},dataPush:{},retryTimes:{}", + receivedData.getDataId(), receivedData.getGroup(), targetUrl, getTaskId(), dataPush, + retryTimes); } } else { - LOGGER.error("Retry Push ReceivedData times have exceeded!dataId:{}, group:{},url:{},taskId:{},dataPush:{},retryTimes:{}", - receivedData.getDataId(), receivedData.getGroup(), targetUrl,getTaskId(),dataPush,retryTimes); + //set sessionInterests dataInfoId version zero + DataInfo dataInfo = new DataInfo(receivedData.getInstanceId(), receivedData.getDataId(), + receivedData.getGroup()); + boolean result = sessionInterests.checkAndUpdateInterestVersionZero(receivedData.getSegment(), dataInfo.getDataInfoId()); + if (result) { + LOGGER.warn("Retry Push ReceivedData times have exceeded,set sessionInterests dataInfoId version zero! url:{},taskId:{},dataPush:{},retryTimes:{},dataCenter:{},dataInfoId:{}!", + targetUrl,getTaskId(),dataPush,retryTimes, + receivedData.getSegment(), + dataInfo.getDataInfoId()); + } else { + LOGGER.warn("Retry Push ReceivedData times have exceeded,but set sessionInterests dataInfoId version zero fail!url:{},taskId:{},dataPush:{},retryTimes:{},dataCenter:{},dataInfoId:{}!", + targetUrl,getTaskId(),dataPush,retryTimes, + receivedData.getSegment(), + dataInfo.getDataInfoId()); + } } } } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/RenewDatumTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/RenewDatumTask.java new file mode 100644 index 000000000..04ee1814a --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/RenewDatumTask.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.scheduler.task; + +import com.alipay.sofa.registry.common.model.RenewDatumRequest; +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.server.session.registry.SessionRegistry; +import com.alipay.sofa.registry.task.listener.TaskEvent; + +/** + * + * @author kezhu.wukz + * @version $Id: RenewDatumTask.java, v 0.1 2019-06-14 12:15 kezhu.wukz Exp $ + */ +public class RenewDatumTask extends AbstractSessionTask { + + private static final Logger RENEW_LOGGER = LoggerFactory.getLogger( + ValueConstants.LOGGER_NAME_RENEW, + "[RenewDatumTask]"); + + private final DataNodeService dataNodeService; + + private final SessionServerConfig sessionServerConfig; + + private final SessionRegistry sessionRegistry; + + private RenewDatumRequest renewDatumRequest; + + public RenewDatumTask(SessionServerConfig sessionServerConfig, DataNodeService dataNodeService, + SessionRegistry sessionRegistry) { + this.sessionServerConfig = sessionServerConfig; + this.dataNodeService = dataNodeService; + this.sessionRegistry = sessionRegistry; + } + + @Override + public void execute() { + + try { + Boolean result = dataNodeService.renewDatum(renewDatumRequest); + if (!result) { + RENEW_LOGGER.info( + "Renew datum request to dataNode got digest different! renewDatumRequest={}", + renewDatumRequest); + + // send snapshot datum for the corresponding connId + sessionRegistry.sendDatumSnapshot(renewDatumRequest.getConnectId(), + renewDatumRequest.getDataServerIP()); + + } + } catch (Exception e) { + RENEW_LOGGER.error(String.format( + "Renew datum request to dataNode error! renewDatumRequest=%s, errorMsg=%s", + renewDatumRequest, e.getMessage()), e); + } + } + + @Override + public void setTaskEvent(TaskEvent taskEvent) { + //taskId create from event + if (taskEvent.getTaskId() != null) { + setTaskId(taskEvent.getTaskId()); + } + + Object obj = taskEvent.getEventObj(); + if (obj instanceof RenewDatumRequest) { + this.renewDatumRequest = (RenewDatumRequest) obj; + } else { + throw new IllegalArgumentException("Input task event object error!"); + } + } + + @Override + public String toString() { + return String.format("RENEW_DATUM_TASK{ taskId=%s, renewDatumRequest=%s }", getTaskId(), + renewDatumRequest); + } + + @Override + public boolean checkRetryTimes() { + return checkRetryTimes(sessionServerConfig.getRenewDatumTaskRetryTimes()); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SessionRegisterDataTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SessionRegisterDataTask.java index 925bc27a5..732d3fb64 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SessionRegisterDataTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SessionRegisterDataTask.java @@ -16,6 +16,10 @@ */ package com.alipay.sofa.registry.server.session.scheduler.task; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + import com.alipay.sofa.registry.common.model.dataserver.SessionServerRegisterRequest; import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.log.Logger; @@ -29,10 +33,6 @@ import com.alipay.sofa.registry.server.session.node.service.DataNodeService; import com.alipay.sofa.registry.task.listener.TaskEvent; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - /** * * @author shangyu.wh @@ -84,11 +84,11 @@ public void setTaskEvent(TaskEvent taskEvent) { if (sessionServer != null) { Collection chs = sessionServer.getChannels(); - Set clientHosts = new HashSet<>(); - chs.forEach(channel -> clientHosts.add(NetUtil.toAddressString(channel.getRemoteAddress()))); + Set connectIds = new HashSet<>(); + chs.forEach(channel -> connectIds.add(NetUtil.toAddressString(channel.getRemoteAddress()))); sessionServerRegisterRequest = new SessionServerRegisterRequest( - SessionProcessIdGenerator.getSessionProcessId(), clientHosts); + SessionProcessIdGenerator.getSessionProcessId(), connectIds); } else { LOGGER.error("get null session server,please check server started before register!port {}", sessionServerConfig.getServerPort()); @@ -106,7 +106,7 @@ public void execute() { public String toString() { return "SESSION_REGISTER_DATA_TASK{" + "taskId='" + taskId + '\'' + ", sessionServerRegisterRequest=" + sessionServerRegisterRequest.getProcessId() - + ", clientList=" + sessionServerRegisterRequest.getClientHosts().size() + + ", clientList=" + sessionServerRegisterRequest.getConnectIds().size() + ", dataUrl=" + dataUrl + '}'; } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SubscriberPushEmptyTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SubscriberPushEmptyTask.java new file mode 100644 index 000000000..027b2d7b4 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/SubscriberPushEmptyTask.java @@ -0,0 +1,212 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.scheduler.task; + +import com.alipay.sofa.registry.common.model.constants.ValueConstants; +import com.alipay.sofa.registry.common.model.dataserver.Datum; +import com.alipay.sofa.registry.common.model.store.BaseInfo.ClientVersion; +import com.alipay.sofa.registry.common.model.store.Subscriber; +import com.alipay.sofa.registry.common.model.store.URL; +import com.alipay.sofa.registry.core.model.ReceivedData; +import com.alipay.sofa.registry.core.model.ScopeEnum; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.converter.ReceivedDataConverter; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskEvent.TaskType; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; +import com.alipay.sofa.registry.util.DatumVersionUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * @author shangyu.wh + * @version $Id: SubscriberRegisterFetchTask.java, v 0.1 2017-12-07 16:23 shangyu.wh Exp $ + */ +public class SubscriberPushEmptyTask extends AbstractSessionTask { + + private static final Logger taskLogger = LoggerFactory.getLogger( + SubscriberPushEmptyTask.class, "[Task]"); + + protected final SessionServerConfig sessionServerConfig; + /** + * trigger task com.alipay.sofa.registry.server.meta.listener process + */ + protected final TaskListenerManager taskListenerManager; + protected Subscriber subscriber; + + public SubscriberPushEmptyTask(SessionServerConfig sessionServerConfig, + TaskListenerManager taskListenerManager) { + this.sessionServerConfig = sessionServerConfig; + this.taskListenerManager = taskListenerManager; + } + + @Override + public long getExpiryTime() { + return -1; + } + + @Override + public void setTaskEvent(TaskEvent taskEvent) { + //taskId create from event + if (taskEvent.getTaskId() != null) { + setTaskId(taskEvent.getTaskId()); + } + + Object obj = taskEvent.getEventObj(); + + if (!(obj instanceof Subscriber)) { + throw new IllegalArgumentException("Input task event object error!"); + } + + this.subscriber = (Subscriber) obj; + } + + @Override + public void execute() { + executeTask(); + } + + protected void executeTask() { + + if (subscriber == null) { + throw new IllegalArgumentException("Subscriber can not be null!"); + } + + List subscriberRegisterIdList = Collections.singletonList(subscriber + .getRegisterId()); + + boolean isOldVersion = !ClientVersion.StoreData.equals(subscriber.getClientVersion()); + + switch (subscriber.getScope()) { + case zone: + if (isOldVersion) { + fireUserDataElementPushTask(); + } else { + fireReceivedDataPushTask(subscriberRegisterIdList, ScopeEnum.zone); + } + break; + + case dataCenter: + if (isOldVersion) { + fireUserDataElementMultiPushTask(); + } else { + fireReceivedDataPushTask(subscriberRegisterIdList, ScopeEnum.dataCenter); + } + break; + + case global: + + fireReceivedDataPushTask(subscriberRegisterIdList, ScopeEnum.global); + + break; + default: + break; + } + + } + + protected void fireReceivedDataPushTask(List subscriberRegisterIdList, + ScopeEnum scopeEnum) { + ReceivedData receivedData = ReceivedDataConverter.getReceivedDataMulti( + subscriber.getDataId(), subscriber.getGroup(), subscriber.getInstanceId(), + ValueConstants.DEFAULT_DATA_CENTER, scopeEnum, subscriberRegisterIdList, + subscriber.getCell()); + //no datum set version current timestamp + receivedData.setVersion(DatumVersionUtil.nextId()); + firePush(receivedData); + } + + protected void firePush(ReceivedData receivedData) { + //trigger push to client node + Map parameter = new HashMap<>(); + parameter.put(receivedData, subscriber.getSourceAddress()); + TaskEvent taskEvent = new TaskEvent(parameter, TaskType.RECEIVED_DATA_MULTI_PUSH_TASK); + taskLogger.info("send {} taskURL:{},taskScope", taskEvent.getTaskType(), + subscriber.getSourceAddress(), receivedData.getScope()); + taskListenerManager.sendTaskEvent(taskEvent); + } + + protected void fireUserDataElementPushTask() { + + //no datum + Datum datum = new Datum(); + datum.setDataId(subscriber.getDataId()); + datum.setInstanceId(subscriber.getInstanceId()); + datum.setGroup(subscriber.getGroup()); + //no datum set version current timestamp + datum.setVersion(DatumVersionUtil.nextId()); + datum.setPubMap(new HashMap<>()); + datum.setDataCenter(ValueConstants.DEFAULT_DATA_CENTER); + + Collection subscribers = new ArrayList<>(); + subscribers.add(subscriber); + + TaskEvent taskEvent = new TaskEvent(subscriber, TaskType.USER_DATA_ELEMENT_PUSH_TASK); + + taskEvent.setAttribute(Constant.PUSH_CLIENT_SUBSCRIBERS, subscribers); + taskEvent.setAttribute(Constant.PUSH_CLIENT_DATUM, datum); + taskEvent.setAttribute(Constant.PUSH_CLIENT_URL, subscriber.getSourceAddress()); + + taskLogger.info("send {} taskURL:{}", taskEvent.getTaskType(), + subscriber.getSourceAddress()); + taskListenerManager.sendTaskEvent(taskEvent); + } + + protected void fireUserDataElementMultiPushTask() { + + //no datum + Datum datum = new Datum(); + datum.setDataId(subscriber.getDataId()); + datum.setInstanceId(subscriber.getInstanceId()); + datum.setGroup(subscriber.getGroup()); + //no datum set version as mini as + datum.setVersion(DatumVersionUtil.nextId()); + datum.setPubMap(new HashMap<>()); + datum.setDataCenter(ValueConstants.DEFAULT_DATA_CENTER); + + Collection subscribers = new ArrayList<>(); + subscribers.add(subscriber); + + TaskEvent taskEvent = new TaskEvent(subscriber, TaskType.USER_DATA_ELEMENT_MULTI_PUSH_TASK); + taskEvent.setAttribute(Constant.PUSH_CLIENT_SUBSCRIBERS, subscribers); + taskEvent.setAttribute(Constant.PUSH_CLIENT_DATUM, datum); + taskEvent.setAttribute(Constant.PUSH_CLIENT_URL, subscriber.getSourceAddress()); + + taskLogger.info("send {} taskURL:{}", taskEvent.getTaskType(), + subscriber.getSourceAddress()); + taskListenerManager.sendTaskEvent(taskEvent); + } + + @Override + public boolean checkRetryTimes() { + return checkRetryTimes(sessionServerConfig.getSubscriberRegisterFetchRetryTimes()); + } + + @Override + public String toString() { + return "SubscriberPushEmptyTask{" + "taskId='" + getTaskId() + '\'' + ", subscriber=" + + subscriber + ", expiryTime='" + getExpiryTime() + '\'' + '}'; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/UnPublishDataTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/UnPublishDataTask.java new file mode 100644 index 000000000..46fa86298 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/task/UnPublishDataTask.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.scheduler.task; + +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.server.session.node.service.DataNodeService; +import com.alipay.sofa.registry.task.listener.TaskEvent; + +/** + * + * @author kezhu.wukz + * @version $Id: UnPublishDataTask.java, v 0.1 2019-06-14 12:15 kezhu.wukz Exp $ + */ +public class UnPublishDataTask extends AbstractSessionTask { + + private final DataNodeService dataNodeService; + + private Publisher unPublisher; + + public UnPublishDataTask(DataNodeService dataNodeService) { + this.dataNodeService = dataNodeService; + } + + @Override + public void execute() { + dataNodeService.unregister(unPublisher); + } + + @Override + public void setTaskEvent(TaskEvent taskEvent) { + //taskId create from event + if (taskEvent.getTaskId() != null) { + setTaskId(taskEvent.getTaskId()); + } + + Object obj = taskEvent.getEventObj(); + if (obj instanceof Publisher) { + this.unPublisher = (Publisher) obj; + } else { + throw new IllegalArgumentException("Input task event object error!"); + } + } + + @Override + public String toString() { + return String.format("UN_PUBLISH_DATA_TASK{ taskId=%s, unPublisher=%s }", getTaskId(), + unPublisher); + } + + @Override + public boolean checkRetryTimes() { + //dataNodeService.unregister will be retry all the failed + return false; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/timertask/SyncClientsHeartbeatTask.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/timertask/SyncClientsHeartbeatTask.java index 7f2d58464..1b8d77973 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/timertask/SyncClientsHeartbeatTask.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/scheduler/timertask/SyncClientsHeartbeatTask.java @@ -16,9 +16,20 @@ */ package com.alipay.sofa.registry.server.session.scheduler.timertask; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; + import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.metrics.TaskMetrics; +import com.alipay.sofa.registry.remoting.Server; +import com.alipay.sofa.registry.remoting.exchange.Exchange; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; import com.alipay.sofa.registry.server.session.listener.ReceivedDataMultiPushTaskListener; import com.alipay.sofa.registry.server.session.scheduler.ExecutorManager; import com.alipay.sofa.registry.server.session.store.DataStore; @@ -30,13 +41,6 @@ import com.alipay.sofa.registry.task.listener.TaskListener; import com.codahale.metrics.Gauge; import com.codahale.metrics.MetricRegistry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ThreadPoolExecutor; /** * The type Sync clients heartbeat task. @@ -57,6 +61,12 @@ public class SyncClientsHeartbeatTask { public static final String SYMBOLIC1 = " ├─ "; public static final String SYMBOLIC2 = " └─ "; + @Autowired + private Exchange boltExchange; + + @Autowired + private SessionServerConfig sessionServerConfig; + /** * store subscribers */ @@ -87,8 +97,15 @@ public void syncCounte() { long countPub = sessionDataStore.count(); long countSubW = sessionWatchers.count(); - CONSOLE_COUNT_LOGGER.info("Subscriber count: {}, Publisher count: {}, Watcher count: {},", - countSub, countPub, countSubW); + int channelCount = 0; + Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort()); + if (sessionServer != null) { + channelCount = sessionServer.getChannelCount(); + } + + CONSOLE_COUNT_LOGGER.info( + "Subscriber count: {}, Publisher count: {}, Watcher count: {}, Connection count: {}", + countSub, countPub, countSubW, channelCount); } @Scheduled(initialDelayString = "${session.server.printTask.fixedDelay}", fixedDelayString = "${session.server.printTask.fixedDelay}") diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/DataStore.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/DataStore.java index c33dea1ce..455057c3c 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/DataStore.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/DataStore.java @@ -19,6 +19,7 @@ import com.alipay.sofa.registry.common.model.store.Publisher; import java.util.Collection; +import java.util.Map; /** * @@ -49,4 +50,10 @@ public interface DataStore extends DataManager { */ Collection getStoreDataInfoIds(); + /** + * get all publishers group by connectId + * @return + */ + Map> getConnectPublishers(); + } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/Interests.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/Interests.java index e3c0b65c1..5f08bfb34 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/Interests.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/Interests.java @@ -62,6 +62,14 @@ public interface Interests extends DataManager { */ boolean checkAndUpdateInterestVersions(String dataCenter, String dataInfoId, Long version); + /** + * set subscribers interest dataInfoId version zero + * @param dataCenter + * @param dataInfoId + * @return + */ + boolean checkAndUpdateInterestVersionZero(String dataCenter, String dataInfoId); + /** * get all subscriber dataInfoIds * @@ -85,4 +93,10 @@ Map> querySubscriberIndex(String data * @return */ Subscriber queryById(String registerId, String dataInfoId); + + /** + * get all subscribers group by connectId + * @return + */ + Map> getConnectSubscribers(); } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionDataStore.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionDataStore.java index ffe24cf8b..6bd16b497 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionDataStore.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionDataStore.java @@ -46,11 +46,11 @@ public class SessionDataStore implements DataStore { */ private Map> registry = new ConcurrentHashMap<>(); + /*** index */ private Map> connectIndex = new ConcurrentHashMap<>(); @Override public void add(Publisher publisher) { - write.lock(); try { Map publishers = registry.get(publisher.getDataInfoId()); @@ -103,7 +103,7 @@ public void add(Publisher publisher) { } publishers.put(publisher.getRegisterId(), publisher); - addIndex(publisher); + addToConnectIndex(publisher); } finally { write.unlock(); @@ -132,7 +132,7 @@ public boolean deleteById(String registerId, String dataInfoId) { return false; } else { - removeIndex(publisherTodelete); + removeFromConnectIndex(publisherTodelete); return true; } } @@ -148,7 +148,6 @@ public Map queryByConnectId(String connectId) { @Override public boolean deleteByConnectId(String connectId) { - write.lock(); try { for (Map map : registry.values()) { @@ -157,10 +156,10 @@ public boolean deleteByConnectId(String connectId) { if (publisher != null && connectId.equals(publisher.getSourceAddress().getAddressString())) { it.remove(); - invalidateIndex(publisher); } } } + connectIndex.remove(connectId); return true; } catch (Exception e) { LOGGER.error("Delete publisher by connectId {} error!", connectId, e); @@ -209,12 +208,7 @@ public long count() { return count.get(); } - private void addIndex(Publisher publisher) { - - addConnectIndex(publisher); - } - - private void addConnectIndex(Publisher publisher) { + private void addToConnectIndex(Publisher publisher) { String connectId = publisher.getSourceAddress().getAddressString(); Map publisherMap = connectIndex.get(connectId); @@ -229,11 +223,7 @@ private void addConnectIndex(Publisher publisher) { publisherMap.put(publisher.getRegisterId(), publisher); } - private void removeIndex(Publisher publisher) { - removeConnectIndex(publisher); - } - - private void removeConnectIndex(Publisher publisher) { + private void removeFromConnectIndex(Publisher publisher) { String connectId = publisher.getSourceAddress().getAddressString(); Map publisherMap = connectIndex.get(connectId); if (publisherMap != null) { @@ -252,4 +242,8 @@ private void invalidateConnectIndex(String connectId) { connectIndex.remove(connectId); } + @Override + public Map> getConnectPublishers() { + return connectIndex; + } } \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionInterests.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionInterests.java index a1b0719be..fd5cb9595 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionInterests.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/store/SessionInterests.java @@ -250,13 +250,20 @@ public boolean checkAndUpdateInterestVersions(String dataCenter, String dataInfo dataInfoVersions = newDataInfoVersions; } } - + //set zero + if (version.longValue() == 0l) { + return dataInfoVersions.put(dataInfoId, version) != null; + } return VersionsMapUtils.checkAndUpdateVersions(dataInfoVersions, dataInfoId, version); } finally { read.unlock(); } } + public boolean checkAndUpdateInterestVersionZero(String dataCenter, String dataInfoId) { + return checkAndUpdateInterestVersions(dataCenter, dataInfoId, 0l); + } + @Override public Collection getInterestDataInfoIds() { return interests.keySet(); @@ -428,6 +435,11 @@ public void clearReSubscribers() { stopPushInterests.clear(); } + @Override + public Map> getConnectSubscribers() { + return connectIndex; + } + public SessionServerConfig getSessionServerConfig() { return sessionServerConfig; } diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSessionRegistryStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSessionRegistryStrategy.java index 630058f56..c68889f3e 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSessionRegistryStrategy.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSessionRegistryStrategy.java @@ -40,14 +40,11 @@ * @since 2019/2/15 */ public class DefaultSessionRegistryStrategy implements SessionRegistryStrategy { - private static final Logger LOGGER = LoggerFactory - .getLogger(DefaultSessionRegistryStrategy.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(DefaultSessionRegistryStrategy.class); - private static final Logger CONSOLE_LOGGER = LoggerFactory.getLogger("SESSION-CONSOLE", - "[Task]"); - - private static final Logger taskLogger = LoggerFactory.getLogger( - DefaultSessionRegistryStrategy.class, "[Task]"); + private static final Logger taskLogger = LoggerFactory.getLogger( + DefaultSessionRegistryStrategy.class, "[Task]"); /** * store subscribers @@ -110,10 +107,7 @@ private void fireDataChangeCloudTask(String dataInfoId) { @Override public void afterPublisherRegister(Publisher publisher) { - TaskEvent syncPublisherTask = new TaskEvent(publisher, - TaskEvent.TaskType.SYNC_PUBLISHER_TASK); - CONSOLE_LOGGER.info("send " + syncPublisherTask.getTaskType() + " taskEvent:{}", publisher); - taskListenerManager.sendTaskEvent(syncPublisherTask); + } @Override diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSubscriberMultiFetchTaskStrategy.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSubscriberMultiFetchTaskStrategy.java index a33637d65..629c38518 100644 --- a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSubscriberMultiFetchTaskStrategy.java +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/strategy/impl/DefaultSubscriberMultiFetchTaskStrategy.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.server.session.strategy.impl; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; + import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.constants.ValueConstants; import com.alipay.sofa.registry.common.model.dataserver.Datum; @@ -27,6 +37,7 @@ import com.alipay.sofa.registry.log.Logger; import com.alipay.sofa.registry.log.LoggerFactory; import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import com.alipay.sofa.registry.server.session.cache.CacheAccessException; import com.alipay.sofa.registry.server.session.cache.CacheService; import com.alipay.sofa.registry.server.session.cache.DatumKey; import com.alipay.sofa.registry.server.session.cache.Key; @@ -35,19 +46,12 @@ import com.alipay.sofa.registry.server.session.node.NodeManager; import com.alipay.sofa.registry.server.session.node.NodeManagerFactory; import com.alipay.sofa.registry.server.session.scheduler.task.Constant; +import com.alipay.sofa.registry.server.session.store.Interests; import com.alipay.sofa.registry.server.session.strategy.SubscriberMultiFetchTaskStrategy; import com.alipay.sofa.registry.server.session.utils.DatumUtils; import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskListenerManager; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - /** * @author xuanbei * @since 2019/2/15 @@ -60,6 +64,9 @@ public class DefaultSubscriberMultiFetchTaskStrategy implements SubscriberMultiF private static final Logger LOGGER = LoggerFactory .getLogger(DefaultSubscriberMultiFetchTaskStrategy.class); + @Autowired + private Interests sessionInterests; + @Override public void doSubscriberMultiFetchTask(SessionServerConfig sessionServerConfig, TaskListenerManager taskListenerManager, @@ -69,39 +76,29 @@ public void doSubscriberMultiFetchTask(SessionServerConfig sessionServerConfig, Map datumMap = getDatumsCache(fetchDataInfoId, sessionCacheService); - if (datumMap != null) { - - for (ScopeEnum scopeEnum : ScopeEnum.values()) { - Map> map = getPushSubscribers(scopeEnum, - subscribers); - - if (map != null && !map.isEmpty()) { - for (Map.Entry> entry : map - .entrySet()) { - Map subscriberMap = entry.getValue(); - if (subscriberMap != null && !subscriberMap.isEmpty()) { - Subscriber subscriber = subscriberMap.values().iterator().next(); - boolean isOldVersion = !BaseInfo.ClientVersion.StoreData - .equals(subscriber.getClientVersion()); - - if (isOldVersion) { - fireUserDataPushTaskCloud(entry.getKey(), datumMap, - subscriberMap.values(), subscriber, taskListenerManager); - } else { - fireReceivedDataPushTaskCloud(datumMap, - new ArrayList(subscriberMap.keySet()), subscriber, - taskListenerManager); - } + for (ScopeEnum scopeEnum : ScopeEnum.values()) { + Map> map = getPushSubscribers(scopeEnum, + subscribers); + + if (map != null && !map.isEmpty()) { + for (Map.Entry> entry : map.entrySet()) { + Map subscriberMap = entry.getValue(); + if (subscriberMap != null && !subscriberMap.isEmpty()) { + Subscriber subscriber = subscriberMap.values().iterator().next(); + boolean isOldVersion = !BaseInfo.ClientVersion.StoreData.equals(subscriber + .getClientVersion()); + + if (isOldVersion) { + fireUserDataPushTaskCloud(entry.getKey(), datumMap, + subscriberMap.values(), subscriber, taskListenerManager); + } else { + fireReceivedDataPushTaskCloud(datumMap, + new ArrayList(subscriberMap.keySet()), subscriber, + taskListenerManager); } } } } - - } else { - //TODO EMPTY push empty - LOGGER.error( - "SubscriberMultiFetchTask cloud Get publisher data error,which dataInfoId:{}", - fetchDataInfoId); } } @@ -116,7 +113,18 @@ private Map getDatumsCache(String fetchDataInfoId, CacheService s new DatumKey(fetchDataInfoId, dataCenter))). collect(Collectors.toList()); - Map values = sessionCacheService.getValues(keys); + Map values = null; + try { + values = sessionCacheService.getValues(keys); + } catch (CacheAccessException e) { + // The version is set to 0, so that when session checks the datum versions regularly, it will actively re-query the data. + for (String dataCenter : dataCenters) { + boolean result = sessionInterests.checkAndUpdateInterestVersionZero(dataCenter, fetchDataInfoId); + LOGGER.error(String.format( + "error when access cache, so checkAndUpdateInterestVersionZero(return %s): %s", result, + e.getMessage()), e); + } + } if (values != null) { values.forEach((key, value) -> { @@ -140,8 +148,7 @@ private Map> getPushSubscribers(Scope subscribers.forEach((subscriber) -> { if (subscriber.getScope().equals(scopeEnum)) { - InetSocketAddress address = new InetSocketAddress( - subscriber.getSourceAddress().getIpAddress(), + InetSocketAddress address = new InetSocketAddress(subscriber.getSourceAddress().getIpAddress(), subscriber.getSourceAddress().getPort()); Map map = payload.computeIfAbsent(address, k -> new HashMap<>()); map.put(subscriber.getRegisterId(), subscriber); diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/AccessLimitWrapperInterceptor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/AccessLimitWrapperInterceptor.java new file mode 100644 index 000000000..4c6c136a4 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/AccessLimitWrapperInterceptor.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import com.alipay.sofa.registry.common.model.store.BaseInfo; +import com.alipay.sofa.registry.common.model.store.StoreData; +import com.alipay.sofa.registry.server.session.limit.AccessLimitService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * @author shangyu.wh + * @version 1.0: AccessLimitWrapperInterceptor.java, v 0.1 2019-08-26 20:29 shangyu.wh Exp $ + */ +public class AccessLimitWrapperInterceptor implements WrapperInterceptor { + + @Autowired + private AccessLimitService accessLimitService; + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) + throws Exception { + + BaseInfo baseInfo = (BaseInfo) invocation.getParameterSupplier().get(); + + if (!accessLimitService.tryAcquire()) { + throw new RuntimeException(String.format( + "Register access limit for session server!dataInfoId=%s,connectId=%s", + baseInfo.getDataInfoId(), baseInfo.getSourceAddress())); + } + + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 0; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/BlacklistWrapperInterceptor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/BlacklistWrapperInterceptor.java new file mode 100644 index 000000000..20e076fd2 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/BlacklistWrapperInterceptor.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import com.alipay.sofa.registry.common.model.store.BaseInfo; +import com.alipay.sofa.registry.common.model.store.StoreData; +import com.alipay.sofa.registry.common.model.store.StoreData.DataType; +import com.alipay.sofa.registry.common.model.store.Subscriber; +import com.alipay.sofa.registry.log.Logger; +import com.alipay.sofa.registry.log.LoggerFactory; +import com.alipay.sofa.registry.server.session.filter.ProcessFilter; +import com.alipay.sofa.registry.server.session.registry.SessionRegistry; +import com.alipay.sofa.registry.task.listener.TaskEvent; +import com.alipay.sofa.registry.task.listener.TaskListenerManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * blacklist filter + * + * @author shangyu.wh + * @version 1.0: BlacklistWrapperInterceptor.java, v 0.1 2019-06-18 22:26 shangyu.wh Exp $ + */ +public class BlacklistWrapperInterceptor implements WrapperInterceptor { + + private static final Logger TASK_LOGGER = LoggerFactory.getLogger(SessionRegistry.class, + "[Task]"); + + @Autowired + private TaskListenerManager taskListenerManager; + + /** + * blacklist filter + */ + @Autowired + private ProcessFilter processFilter; + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) + throws Exception { + + BaseInfo storeData = (BaseInfo) invocation.getParameterSupplier().get(); + + if (processFilter.match(storeData)) { + if (DataType.PUBLISHER == storeData.getDataType()) { + // match blacklist stop pub. + return true; + } + + if (DataType.SUBSCRIBER == storeData.getDataType()) { + fireSubscriberPushEmptyTask((Subscriber) storeData); + return true; + } + } + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 200; + } + + private void fireSubscriberPushEmptyTask(Subscriber subscriber) { + //trigger empty data push + TaskEvent taskEvent = new TaskEvent(subscriber, + TaskEvent.TaskType.SUBSCRIBER_PUSH_EMPTY_TASK); + TASK_LOGGER.info("send " + taskEvent.getTaskType() + " taskEvent:{}", taskEvent); + taskListenerManager.sendTaskEvent(taskEvent); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/ClientCheckWrapperInterceptor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/ClientCheckWrapperInterceptor.java new file mode 100644 index 000000000..d3d80ec8c --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/ClientCheckWrapperInterceptor.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import com.alipay.sofa.registry.common.model.store.BaseInfo; +import com.alipay.sofa.registry.common.model.store.StoreData; +import com.alipay.sofa.registry.remoting.Channel; +import com.alipay.sofa.registry.remoting.Server; +import com.alipay.sofa.registry.remoting.exchange.Exchange; +import com.alipay.sofa.registry.server.session.bootstrap.SessionServerConfig; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * check connect already existed + * + * @author shangyu.wh + * @version 1.0: ClientCheckWrapperInterceptor.java, v 0.1 2019-06-18 13:53 shangyu.wh Exp $ + */ +public class ClientCheckWrapperInterceptor implements WrapperInterceptor { + + @Autowired + private SessionServerConfig sessionServerConfig; + + @Autowired + private Exchange boltExchange; + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) + throws Exception { + + BaseInfo baseInfo = (BaseInfo) invocation.getParameterSupplier().get(); + + Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort()); + + Channel channel = sessionServer.getChannel(baseInfo.getSourceAddress()); + + if (channel == null) { + throw new RuntimeException(String.format( + "Register address %s has not connected session server!", + baseInfo.getSourceAddress())); + } + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 100; + } +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/Wrapper.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/Wrapper.java new file mode 100644 index 000000000..19090af52 --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/Wrapper.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import java.util.function.Supplier; + +/** + * + * @author shangyu.wh + * @version 1.0: Wrapper.java, v 0.1 2019-06-18 19:33 shangyu.wh Exp $ + */ +public interface Wrapper { + + R call(); + + Supplier getParameterSupplier(); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptor.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptor.java new file mode 100644 index 000000000..f23478ffe --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptor.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +/** + * + * @author shangyu.wh + * @version 1.0: WrapperInterceptor.java, v 0.1 2019-06-18 11:45 shangyu.wh Exp $ + */ +public interface WrapperInterceptor { + + /** + * invoke inside function + * + * @param invocation + * @return + * @throws Exception + */ + R invokeCodeWrapper(WrapperInvocation invocation) throws Exception; + + /** + * Interceptor order + * @return + */ + int getOrder(); +} \ No newline at end of file diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptorManager.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptorManager.java new file mode 100644 index 000000000..009f6876f --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInterceptorManager.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * + * @author shangyu.wh + * @version 1.0: WrapperInterceptorManager.java, v 0.1 2019-06-18 14:51 shangyu.wh Exp $ + */ +public class WrapperInterceptorManager { + + private List interceptorChain = new CopyOnWriteArrayList<>(); + + public int addInterceptor(WrapperInterceptor item){ + // The index of the search key, if it is contained in the list; otherwise, (-(insertion point) - 1) + final int index = Collections.binarySearch(interceptorChain, item, + (o1, o2) -> { + if (o1 == null && o2 == null) { + return 0; + } else if (o1 == null) { + return 1; + } else if (o2 == null) { + return -1; + } + + if (o1.getOrder() < o2.getOrder()) { + return -1; + } else if (o1.getOrder() > o2.getOrder()) { + return 1; + } + return 0; + }); + final int insertAt; + if (index < 0) { + insertAt = -(index + 1); + } else { + insertAt = index + 1; + } + + interceptorChain.add(insertAt, item); + return insertAt; + } + + /** + * Getter method for property interceptorChain. + * + * @return property value of interceptorChain + */ + public List getInterceptorChain() { + return interceptorChain; + } +} diff --git a/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInvocation.java b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInvocation.java new file mode 100644 index 000000000..7a736944f --- /dev/null +++ b/server/server/session/src/main/java/com/alipay/sofa/registry/server/session/wrapper/WrapperInvocation.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session.wrapper; + +import java.util.Iterator; +import java.util.List; +import java.util.function.Supplier; + +/** + * + * @author shangyu.wh + * @version 1.0: WrapperInvocation.java, v 0.1 2019-06-18 11:43 shangyu.wh Exp $ + */ +public class WrapperInvocation { + + private final Wrapper target; + + private List interceptorChain; + + private Iterator iterator; + + public WrapperInvocation(Wrapper target, + WrapperInterceptorManager wrapperInterceptorManager) { + this.interceptorChain = wrapperInterceptorManager.getInterceptorChain(); + this.iterator = this.interceptorChain.iterator(); + this.target = target; + } + + public R proceed() throws Exception { + if (iterator.hasNext()) { + WrapperInterceptor interceptor = iterator.next(); + return interceptor.invokeCodeWrapper(this); + } + return target.call(); + } + + /** + * Getter method for property ParameterSupplier. + * + * @return property value of ParameterSupplier + */ + public Supplier getParameterSupplier() { + return target.getParameterSupplier(); + } +} \ No newline at end of file diff --git a/server/server/session/src/main/resources/application.properties b/server/server/session/src/main/resources/application.properties index 9df254384..f5062be72 100644 --- a/server/server/session/src/main/resources/application.properties +++ b/server/server/session/src/main/resources/application.properties @@ -1,7 +1,7 @@ spring.main.banner-mode=LOG -#nodes.metaNode=: -#nodes.localDataCenter= -#nodes.localRegion= +nodes.metaNode=DefaultDataCenter:localhost +nodes.localDataCenter=DefaultDataCenter +nodes.localRegion=DEFAULT_ZONE #session.server.logging.level=INFO #session.server.logging.home=/home/admin/logs/registry/session @@ -27,4 +27,6 @@ session.server.schedulerFetchDataFirstDelay=3 session.server.schedulerFetchDataExpBackOffBound=10 #session.server.invalidForeverZones=; #session.server.invalidIgnoreDataidRegex= -#session.server.pushEmptyDataDataIdPrefixes= \ No newline at end of file +#session.server.pushEmptyDataDataIdPrefixes= +session.server.renewDatumWheelTaskDelaySec=180 +session.server.renewDatumWheelTaskRandomFirstDelaySec=60 \ No newline at end of file diff --git a/server/server/session/src/main/resources/logback-spring.xml b/server/server/session/src/main/resources/logback-spring.xml index 96f141a5b..568a803ca 100644 --- a/server/server/session/src/main/resources/logback-spring.xml +++ b/server/server/session/src/main/resources/logback-spring.xml @@ -71,6 +71,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${SESSION_LOG_HOME}/registry-renew.log + + ${SESSION_LOG_HOME}/registry-renew.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -241,6 +261,26 @@ + + true + + ${LOG_LEVEL} + + + ERROR + DENY + + ${SESSION_LOG_HOME}/registry-metrics.log + + ${SESSION_LOG_HOME}/registry-metrics.log.%d{yyyy-MM-dd} + 30 + + + [%d{ISO8601}][%p][%t][%c{0}] - %m%n + ${LOG_ENCODE} + + + @@ -253,6 +293,11 @@ + + + + + @@ -297,6 +342,11 @@ + + + + + diff --git a/server/server/session/src/main/resources/security/blacklist.txt b/server/server/session/src/main/resources/security/blacklist.txt new file mode 100644 index 000000000..e3413f8d4 --- /dev/null +++ b/server/server/session/src/main/resources/security/blacklist.txt @@ -0,0 +1,78 @@ +org.codehaus.groovy.runtime.MethodClosure +clojure.core$constantly +clojure.main$eval_opt +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactory +com.alibaba.citrus.springext.support.parser.AbstractNamedProxyBeanDefinitionParser$ProxyTargetFactoryImpl +com.alibaba.citrus.springext.util.SpringExtUtil.AbstractProxy +com.alipay.custrelation.service.model.redress.Pair +com.caucho.hessian.test.TestCons +com.mchange.v2.c3p0.JndiRefForwardingDataSource +com.mchange.v2.c3p0.WrapperConnectionPoolDataSource +com.rometools.rome.feed.impl.EqualsBean +com.rometools.rome.feed.impl.ToStringBean +com.sun.jndi.rmi.registry.BindingEnumeration +com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl +com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl +com.sun.rowset.JdbcRowSetImpl +com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data +java.rmi.server.UnicastRemoteObject +java.security.SignedObject +java.util.ServiceLoader$LazyIterator +javax.imageio.ImageIO$ContainsFilter +javax.imageio.spi.ServiceRegistry +javax.management.BadAttributeValueExpException +javax.naming.InitialContext +javax.naming.spi.ObjectFactory +javax.script.ScriptEngineManager +javax.sound.sampled.AudioFormat$Encoding +org.apache.carbondata.core.scan.expression.ExpressionResult +org.apache.commons.dbcp +org.apache.commons.dbcp2 +org.apache.commons.beanutils +org.apache.ibatis.executor.loader.AbstractSerialStateHolder +org.apache.ibatis.executor.loader.CglibSerialStateHolder +org.apache.ibatis.executor.loader.JavassistSerialStateHolder +org.apache.ibatis.executor.loader.cglib.CglibProxyFactory +org.apache.ibatis.executor.loader.javassist.JavassistSerialStateHolder +org.apache.tomcat.dbcp.dbcp.datasources.SharedPoolDataSource +org.apache.wicket.util.upload.DiskFileItem +org.apache.xalan.xsltc.trax.TemplatesImpl +org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding +org.apache.xpath.XPathContext +org.eclipse.jetty.util.log.LoggerLog +org.geotools.filter.ConstantExpression +org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder +org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor +org.springframework.beans.factory.BeanFactory +org.springframework.beans.factory.config.PropertyPathFactoryBean +org.springframework.beans.factory.support.DefaultListableBeanFactory +org.springframework.jndi.support.SimpleJndiBeanFactory +org.springframework.orm.jpa.AbstractEntityManagerFactoryBean +org.springframework.transaction.jta.JtaTransactionManager +org.yaml.snakeyaml.tokens.DirectiveToken +sun.rmi.server.UnicastRef +javax.management.ImmutableDescriptor +org.springframework.jndi.JndiObjectTargetSource +ch.qos.logback.core.db.JNDIConnectionSource +java.beans.Expression +javassist.bytecode +javassist.tools.web.Viewer +javassist.util.proxy.SerializedProxy +org.apache.ibatis.javassist.bytecode +org.apache.ibatis.javassist.tools.web.Viewer +org.apache.ibatis.javassist.util.proxy.SerializedProxy +org.springframework.beans.factory.config.MethodInvokingFactoryBean +com.alibaba.druid +com.sun.corba +com.sun.org.apache.bcel +com.sun.org.apache.xml +com.sun.org.apache.xpath +org.apache.zookeeper.Shell +org.apache.tomcat.dbcp.dbcp.BasicDataSource +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +org.jboss.resteasy.plugins +org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler +org.apache.velocity.runtime.resource.Resource +org.springframework.expression.spel.ast.Indexer$PropertyIndexingValueRef +org.mortbay.log.Slf4jLog +org.springframework.expression.spel.ast.MethodReference$MethodValueRef \ No newline at end of file diff --git a/server/server/session/src/test/java/com/alipay/sofa/registry/server/session/WrapperInvocationTest.java b/server/server/session/src/test/java/com/alipay/sofa/registry/server/session/WrapperInvocationTest.java new file mode 100644 index 000000000..8d97e703f --- /dev/null +++ b/server/server/session/src/test/java/com/alipay/sofa/registry/server/session/WrapperInvocationTest.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.server.session; + +import com.alipay.sofa.registry.server.session.wrapper.Wrapper; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInterceptor; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInterceptorManager; +import com.alipay.sofa.registry.server.session.wrapper.WrapperInvocation; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; + +import static junit.framework.Assert.*; + +/** + * + * @author shangyu.wh + * @version 1.0: WrapperInvocationTest.java, v 0.1 2019-06-18 17:41 shangyu.wh Exp $ + */ +public class WrapperInvocationTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testWrapperInterceptorException() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("test exception!"); + testAll("EXP"); + } + + @Test + public void testWrapperInterceptorProceed() throws Exception { + assertEquals(testAll("Proceed"), 1); + } + + @Test + public void testWrapperInterceptorAllRun() throws Exception { + assertEquals(testAll("AllRun"), 2); + } + + private int testAll(String input) throws Exception { + + AtomicInteger ret = new AtomicInteger(0); + + WrapperInterceptorManager wrapperInterceptorManager = new WrapperInterceptorManager(); + + wrapperInterceptorManager.addInterceptor(new WrapperInterceptor(){ + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) throws Exception { + System.out.println("0"); + if("EXP".equals(invocation.getParameterSupplier().get())){ + throw new IllegalAccessException("test exception!"); + } + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 0; + } + }); + + wrapperInterceptorManager.addInterceptor(new WrapperInterceptor(){ + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) throws Exception { + System.out.println("1"); + if("Proceed".equals(invocation.getParameterSupplier().get())){ + ret.set(1); + return true; + } + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 1; + } + }); + + wrapperInterceptorManager.addInterceptor(new WrapperInterceptor(){ + + @Override + public Boolean invokeCodeWrapper(WrapperInvocation invocation) throws Exception { + System.out.println("2"); + if("test".equals(invocation.getParameterSupplier().get())){ + return true; + } + return invocation.proceed(); + } + + @Override + public int getOrder() { + return 2; + } + }); + + + + WrapperInvocation wrapperInvocation = new WrapperInvocation(new Wrapper() { + @Override + public Boolean call() { + if("AllRun".equals(getParameterSupplier().get())) { + System.out.println("success"); + ret.set(2); + return true; + } + return null; + } + + @Override + public Supplier getParameterSupplier() { + return ()->input; + } + + }, wrapperInterceptorManager); + + wrapperInvocation.proceed(); + + return ret.get(); + } +} \ No newline at end of file diff --git a/server/store/api/pom.xml b/server/store/api/pom.xml index 4dbc9f331..b2f226779 100644 --- a/server/store/api/pom.xml +++ b/server/store/api/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-store - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server/store/jraft/pom.xml b/server/store/jraft/pom.xml index d9726ec78..c2c5022bf 100644 --- a/server/store/jraft/pom.xml +++ b/server/store/jraft/pom.xml @@ -6,7 +6,7 @@ com.alipay.sofa registry-store - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml diff --git a/server/store/pom.xml b/server/store/pom.xml index 680f0b7ab..a9e371a24 100644 --- a/server/store/pom.xml +++ b/server/store/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-server-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/test/pom.xml b/test/pom.xml index 4cfd9e221..11c4eca5d 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -5,7 +5,7 @@ com.alipay.sofa registry-parent - 5.2.1 + 5.3.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/test/src/main/resources/application.properties b/test/src/main/resources/application.properties index 20ce078a6..ea2cbe7fe 100644 --- a/test/src/main/resources/application.properties +++ b/test/src/main/resources/application.properties @@ -18,6 +18,9 @@ session.server.schedulerHeartbeatExpBackOffBound=10 session.server.schedulerFetchDataTimeout=3 session.server.schedulerFetchDataFirstDelay=3 session.server.schedulerFetchDataExpBackOffBound=10 +session.server.renewAndSnapshotSilentPeriodSec=10 +session.server.renewDatumWheelTaskDelaySec=10 +session.server.renewDatumWheelTaskRandomFirstDelaySec=10 ## data node configuration data.server.logging.level=INFO @@ -31,6 +34,7 @@ data.server.rpcTimeout=3000 data.server.metaServerPort=9611 data.server.storeNodes=3 data.server.numberOfReplicas=1000 +data.server.datumTimeToLiveSec=20 ## meta node configuration meta.server.logging.level=INFO diff --git a/test/src/main/resources/logback-spring.xml b/test/src/main/resources/logback-spring.xml index adbee9009..a1f43c7db 100644 --- a/test/src/main/resources/logback-spring.xml +++ b/test/src/main/resources/logback-spring.xml @@ -4,14 +4,14 @@ - + [%d{ISO8601}][%p][%t][%c{0}] - %m%n - WARN + INFO diff --git a/test/src/test/java/com/alipay/sofa/registry/test/BaseIntegrationTest.java b/test/src/test/java/com/alipay/sofa/registry/test/BaseIntegrationTest.java index 5ddcb99f8..83c238b6c 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/BaseIntegrationTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/BaseIntegrationTest.java @@ -16,6 +16,31 @@ */ package com.alipay.sofa.registry.test; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; + +import org.junit.Before; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + import com.alipay.remoting.Connection; import com.alipay.sofa.registry.client.api.RegistryClientConfig; import com.alipay.sofa.registry.client.api.SubscriberDataObserver; @@ -35,28 +60,6 @@ import com.alipay.sofa.registry.remoting.jersey.JerseyClient; import com.alipay.sofa.registry.server.data.cache.DatumCache; import com.alipay.sofa.registry.server.test.TestRegistryMain; -import org.junit.Before; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ConfigurableApplicationContext; - -import javax.ws.rs.client.Entity; -import javax.ws.rs.core.MediaType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.junit.Assert.assertTrue; /** * @author xuanbei 18/12/1 @@ -183,12 +186,13 @@ protected static void clientOff() throws Exception { } protected static void clearData() throws Exception { - DatumCache.getAll().clear(); + DatumCache datumCache = (DatumCache) dataApplicationContext.getBean("datumCache"); + datumCache.getAll().clear(); List connectIds = new ArrayList<>(Arrays.asList( NetUtil.genHost(LOCAL_ADDRESS, getSourcePort(registryClient1)), NetUtil.genHost(LOCAL_ADDRESS, getSourcePort(registryClient2)))); for (String connectId : connectIds) { - Map publisherMap = DatumCache.getByHost(connectId); + Map publisherMap = datumCache.getByConnectId(connectId); if (publisherMap != null) { publisherMap.clear(); } diff --git a/test/src/test/java/com/alipay/sofa/registry/test/pubsub/PubSubTest.java b/test/src/test/java/com/alipay/sofa/registry/test/pubsub/PubSubTest.java index bb7c60a42..ab7495f50 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/pubsub/PubSubTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/pubsub/PubSubTest.java @@ -45,7 +45,7 @@ public void publisherTest() throws InterruptedException { PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); SubscriberRegistration subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); @@ -53,7 +53,7 @@ public void publisherTest() throws InterruptedException { registryClient1.register(subReg); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); assertEquals(1, userData.getZoneData().size()); @@ -80,11 +80,11 @@ public void subscriberTest() throws InterruptedException { new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.dataCenter); registryClient1.register(subReg); - Thread.sleep(500L); + Thread.sleep(2000L); PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); @@ -112,7 +112,7 @@ public void multiClientTest() throws InterruptedException { PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); SubscriberRegistration subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); @@ -120,7 +120,7 @@ public void multiClientTest() throws InterruptedException { registryClient2.register(subReg); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); assertEquals(1, userData.getZoneData().size()); @@ -139,11 +139,11 @@ public void multiClientTest() throws InterruptedException { subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.global); registryClient1.register(subReg); - Thread.sleep(500L); + Thread.sleep(2000L); registration = new PublisherRegistration(dataId); registryClient2.register(registration, value); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); @@ -163,12 +163,12 @@ public void multiClientTest() throws InterruptedException { subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.zone); registryClient1.register(subReg); - Thread.sleep(500L); + Thread.sleep(2000L); registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); registryClient2.register(registration, value); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); diff --git a/test/src/test/java/com/alipay/sofa/registry/test/pubsub/TempPublisherTest.java b/test/src/test/java/com/alipay/sofa/registry/test/pubsub/TempPublisherTest.java index 96d1f9bd1..45401d224 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/pubsub/TempPublisherTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/pubsub/TempPublisherTest.java @@ -16,6 +16,18 @@ */ package com.alipay.sofa.registry.test.pubsub; +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + import com.alipay.sofa.registry.client.api.model.RegistryType; import com.alipay.sofa.registry.client.api.registration.PublisherRegistration; import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration; @@ -26,17 +38,6 @@ import com.alipay.sofa.registry.core.model.ScopeEnum; import com.alipay.sofa.registry.server.session.node.service.DataNodeService; import com.alipay.sofa.registry.test.BaseIntegrationTest; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; -import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; -import static org.junit.Assert.assertEquals; /** * @author xuanbei @@ -45,7 +46,7 @@ @RunWith(SpringRunner.class) public class TempPublisherTest extends BaseIntegrationTest { @Test - public void doTest() throws Exception { + public synchronized void doTest() throws Exception { String dataId = "test-dataId-" + System.currentTimeMillis(); String value = "test publish temp data"; @@ -54,7 +55,7 @@ public void doTest() throws Exception { new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.zone); registryClient1.register(subReg); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(0, userData.getZoneData().size()); @@ -77,7 +78,7 @@ public void doTest() throws Exception { sessionApplicationContext.getBean(DataNodeService.class).register(tempPublisher); // data size is 1 - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(1, userData.getZoneData().size()); userData = null; @@ -87,14 +88,14 @@ public void doTest() throws Exception { subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.zone); registryClient1.register(subReg); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(dataId, this.dataId); assertEquals(0, userData.getZoneData().size()); registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); } @Test - public void doTestPubAndTempPubSameTime() throws Exception { + public synchronized void doTestPubAndTempPubSameTime() throws Exception { String dataId = "test-same-time-pub&tempPub-" + System.currentTimeMillis(); String value = "test same time publish"; @@ -102,13 +103,13 @@ public void doTestPubAndTempPubSameTime() throws Exception { new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.zone); registryClient1.register(subReg); - Thread.sleep(1000L); + Thread.sleep(2000L); // publish data PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, "test publish"); - Thread.sleep(1000L); + Thread.sleep(2000L); // publish temp data Publisher tempPublisher = new Publisher(); @@ -128,7 +129,7 @@ public void doTestPubAndTempPubSameTime() throws Exception { tempPublisher.setDataList(dataBoxData); sessionApplicationContext.getBean(DataNodeService.class).register(tempPublisher); - Thread.sleep(1000L); + Thread.sleep(2000L); assertEquals(1, userData.getZoneData().size()); assertEquals(2, userData.getZoneData().get(LOCAL_REGION).size()); diff --git a/test/src/test/java/com/alipay/sofa/registry/test/renew/RenewTest.java b/test/src/test/java/com/alipay/sofa/registry/test/renew/RenewTest.java new file mode 100644 index 000000000..c531420c4 --- /dev/null +++ b/test/src/test/java/com/alipay/sofa/registry/test/renew/RenewTest.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.test.renew; + +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.core.MediaType; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + +import com.alipay.sofa.registry.client.api.model.RegistryType; +import com.alipay.sofa.registry.client.api.registration.PublisherRegistration; +import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration; +import com.alipay.sofa.registry.common.model.store.DataInfo; +import com.alipay.sofa.registry.core.model.Result; +import com.alipay.sofa.registry.core.model.ScopeEnum; +import com.alipay.sofa.registry.server.data.cache.DatumCache; +import com.alipay.sofa.registry.test.BaseIntegrationTest; + +/** + * @author kezhu.wukz + */ +@RunWith(SpringRunner.class) +public class RenewTest extends BaseIntegrationTest { + + /** + * clean datum -> renew + */ + @Test + public void testRenewAfterClean() throws InterruptedException { + String dataId = "test-dataId-" + System.currentTimeMillis(); + String value = "test publish"; + + // pub/sub + { + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + + registryClient1.register(subReg); + } + + Thread.sleep(5000L); + + // check sub + { + assertEquals(dataId, this.dataId); + assertEquals(LOCAL_REGION, userData.getLocalZone()); + assertEquals(1, userData.getZoneData().size()); + assertEquals(1, userData.getZoneData().values().size()); + assertEquals(true, userData.getZoneData().containsKey(LOCAL_REGION)); + assertEquals(1, userData.getZoneData().get(LOCAL_REGION).size()); + assertEquals(value, userData.getZoneData().get(LOCAL_REGION).get(0)); + } + + //clean datum and unsub + { + //pub again to ignore renew for 10sec + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + //un sub, because will new sub below + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); + // sleep to sure pub is done + Thread.sleep(2000L); + // clean all datum + DatumCache datumCache = (DatumCache) dataApplicationContext.getBean("datumCache"); + datumCache.cleanDatum(LOCAL_DATACENTER, + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)); + } + + // new sub, and got empty datum + { + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + registryClient1.register(subReg); + } + Thread.sleep(3000L); + assertEquals(0, userData.getZoneData().size()); + + //renew in 20sec + Thread.sleep(20000L); + assertEquals(1, userData.getZoneData().size()); + + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.PUBLISHER); + } + + /** + * close renew -> clean datum + */ + @Test + public void testNoRenewAfterClean() throws InterruptedException { + // close renew + Assert.assertTrue(metaChannel.getWebTarget().path("renewSwitch/disable") + .request(MediaType.APPLICATION_JSON).get(Result.class).isSuccess()); + Thread.sleep(2000L); + + String dataId = "test-dataId-" + System.currentTimeMillis(); + String value = "test publish"; + + // pub/sub + { + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + + registryClient1.register(subReg); + } + + Thread.sleep(5000L); + + // check sub + { + assertEquals(dataId, this.dataId); + assertEquals(LOCAL_REGION, userData.getLocalZone()); + assertEquals(1, userData.getZoneData().size()); + assertEquals(1, userData.getZoneData().values().size()); + assertEquals(true, userData.getZoneData().containsKey(LOCAL_REGION)); + assertEquals(1, userData.getZoneData().get(LOCAL_REGION).size()); + assertEquals(value, userData.getZoneData().get(LOCAL_REGION).get(0)); + } + + //clean datum and unsub + { + //pub again to ignore renew for 10sec + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + //un sub, because will new sub below + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); + // sleep to sure pub is done + Thread.sleep(2000L); + // clean all datum + DatumCache datumCache = (DatumCache) dataApplicationContext.getBean("datumCache"); + datumCache.cleanDatum(LOCAL_DATACENTER, + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)); + } + + // new sub, and got empty datum + { + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + registryClient1.register(subReg); + } + Thread.sleep(3000L); + assertEquals(0, userData.getZoneData().size()); + + //renew is disable, so it's also 0 in 20sec + Thread.sleep(20000L); + assertEquals(0, userData.getZoneData().size()); + + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); + registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.PUBLISHER); + + // open renew + Assert.assertTrue(metaChannel.getWebTarget().path("renewSwitch/enable") + .request(MediaType.APPLICATION_JSON).get(Result.class).isSuccess()); + Thread.sleep(2000L); + } + +} \ No newline at end of file diff --git a/test/src/test/java/com/alipay/sofa/registry/test/resource/data/DataDigestResourceTest.java b/test/src/test/java/com/alipay/sofa/registry/test/resource/data/DataDigestResourceTest.java index 5bacd905e..fef3d6864 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/resource/data/DataDigestResourceTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/resource/data/DataDigestResourceTest.java @@ -54,17 +54,17 @@ public static void beforeClass() throws Exception { clientOff(); dataId = "test-dataId-" + System.currentTimeMillis(); value = "DataDigestResourceTest"; - Thread.sleep(1000L); + Thread.sleep(2000L); PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(1000L); + Thread.sleep(2000L); SubscriberRegistration subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.dataCenter); registryClient1.register(subReg); - Thread.sleep(500L); + Thread.sleep(2000L); } @AfterClass diff --git a/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/BlacklistTest.java b/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/BlacklistTest.java new file mode 100644 index 000000000..fff295990 --- /dev/null +++ b/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/BlacklistTest.java @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.registry.test.resource.meta; + +import com.alipay.sofa.registry.client.api.model.RegistryType; +import com.alipay.sofa.registry.client.api.registration.PublisherRegistration; +import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration; +import com.alipay.sofa.registry.common.model.store.DataInfo; +import com.alipay.sofa.registry.common.model.store.Publisher; +import com.alipay.sofa.registry.common.model.store.Subscriber; +import com.alipay.sofa.registry.core.model.Result; +import com.alipay.sofa.registry.core.model.ScopeEnum; +import com.alipay.sofa.registry.net.NetUtil; +import com.alipay.sofa.registry.server.session.filter.blacklist.BlacklistConstants; +import com.alipay.sofa.registry.test.BaseIntegrationTest; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Maps; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author shangyu.wh + * @since 2019/1/14 + */ +@RunWith(SpringRunner.class) +public class BlacklistTest extends BaseIntegrationTest { + @Test + public void testBlacklistUpdate() throws Exception { + + Map>> map = new HashMap<>(); + Set set1 = new HashSet<>(); + Set set2 = new HashSet<>(); + set1.add("193.165.0.1"); + set1.add("193.165.0.2"); + set2.add("193.165.0.3"); + set2.add("193.165.0.4"); + + Map> map1 = Maps.newHashMap(); + map1.put(BlacklistConstants.IP_FULL, set1); + + Map> map2 = Maps.newHashMap(); + map2.put(BlacklistConstants.IP_FULL, set2); + + map.put(BlacklistConstants.FORBIDDEN_PUB, map1); + map.put(BlacklistConstants.FORBIDDEN_SUB_BY_PREFIX, map2); + + ObjectMapper mapper = new ObjectMapper(); + + Result response = metaChannel + .getWebTarget() + .path("blacklist/update") + .request() + .post(Entity.entity(mapper.writeValueAsString(map), MediaType.APPLICATION_JSON), + Result.class); + + assertTrue(response.isSuccess()); + + } + + @Test + public void testBlacklistUpdatePub() throws Exception { + + Map>> map = new HashMap<>(); + Set set1 = new HashSet<>(); + Set set2 = new HashSet<>(); + String local = NetUtil.getLocalAddress().getHostAddress(); + set1.add(local); + set2.add(local); + + Map> map1 = Maps.newHashMap(); + map1.put(BlacklistConstants.IP_FULL, set1); + + Map> map2 = Maps.newHashMap(); + map2.put(BlacklistConstants.IP_FULL, set2); + + map.put(BlacklistConstants.FORBIDDEN_PUB, map1); + + ObjectMapper mapper = new ObjectMapper(); + + Result response = metaChannel + .getWebTarget() + .path("blacklist/update") + .request() + .post(Entity.entity(mapper.writeValueAsString(map), MediaType.APPLICATION_JSON), + Result.class); + + assertTrue(response.isSuccess()); + + BaseIntegrationTest.dataId = null; + + //wait for new list meta dispatch to session + Thread.sleep(2000L); + + String dataId = "test-dataId-blacklist"; + String value = "test blacklist"; + + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + Thread.sleep(2000L); + + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + + registryClient1.register(subReg); + + Thread.sleep(2000L); + assertEquals(dataId, this.dataId); + assertEquals(LOCAL_REGION, userData.getLocalZone()); + + Map> publisherMap = sessionChannel + .getWebTarget() + .path("digest/pub/data/query") + .queryParam("dataInfoId", + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)) + .request(APPLICATION_JSON).get(new GenericType>>() { + }); + assertEquals(0, publisherMap.size()); + + Map> subscriberMap = sessionChannel + .getWebTarget() + .path("digest/sub/data/query") + .queryParam("dataInfoId", + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)) + .request(APPLICATION_JSON).get(new GenericType>>() { + }); + assertEquals(1, subscriberMap.size()); + assertEquals(1, subscriberMap.get("SUB").size()); + assertEquals(dataId, subscriberMap.get("SUB").get(0).getDataId()); + + } + + @Test + public void testBlacklistUpdateSub() throws Exception { + + Map>> map = new HashMap<>(); + Set set1 = new HashSet<>(); + Set set2 = new HashSet<>(); + String local = NetUtil.getLocalAddress().getHostAddress(); + set1.add(local); + set2.add(local); + + Map> map1 = Maps.newHashMap(); + map1.put(BlacklistConstants.IP_FULL, set1); + + Map> map2 = Maps.newHashMap(); + map2.put(BlacklistConstants.IP_FULL, set2); + + map.put(BlacklistConstants.FORBIDDEN_SUB_BY_PREFIX, map2); + + ObjectMapper mapper = new ObjectMapper(); + + Result response = metaChannel + .getWebTarget() + .path("blacklist/update") + .request() + .post(Entity.entity(mapper.writeValueAsString(map), MediaType.APPLICATION_JSON), + Result.class); + + assertTrue(response.isSuccess()); + + BaseIntegrationTest.dataId = null; + //wait for new list meta dispatch to session + Thread.sleep(2000L); + + String dataId = "test-dataId-blacklist2"; + String value = "test blacklist2"; + + PublisherRegistration registration = new PublisherRegistration(dataId); + registryClient1.register(registration, value); + Thread.sleep(2000L); + + SubscriberRegistration subReg = new SubscriberRegistration(dataId, + new MySubscriberDataObserver()); + subReg.setScopeEnum(ScopeEnum.dataCenter); + + registryClient1.register(subReg); + + Thread.sleep(2000L); + assertEquals(dataId, this.dataId); + assertEquals(LOCAL_REGION, userData.getLocalZone()); + + Map> publisherMap = sessionChannel + .getWebTarget() + .path("digest/pub/data/query") + .queryParam("dataInfoId", + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)) + .request(APPLICATION_JSON).get(new GenericType>>() { + }); + assertEquals(1, publisherMap.size()); + assertEquals(1, publisherMap.get("PUB").size()); + assertEquals(dataId, publisherMap.get("PUB").get(0).getDataId()); + assertEquals(value, bytes2Object(publisherMap.get("PUB").get(0).getDataList().get(0) + .getBytes())); + + Map> subscriberMap = sessionChannel + .getWebTarget() + .path("digest/sub/data/query") + .queryParam("dataInfoId", + DataInfo.toDataInfoId(dataId, DEFAULT_INSTANCE_ID, DEFAULT_GROUP)) + .request(APPLICATION_JSON).get(new GenericType>>() { + }); + assertEquals(0, subscriberMap.size()); + + } + + @AfterClass + public static void afterClass() { + registryClient1.unregister("test-dataId-blacklist", DEFAULT_GROUP, RegistryType.SUBSCRIBER); + registryClient1.unregister("test-dataId-blacklist", DEFAULT_GROUP, RegistryType.PUBLISHER); + registryClient1 + .unregister("test-dataId-blacklist2", DEFAULT_GROUP, RegistryType.SUBSCRIBER); + registryClient1.unregister("test-dataId-blacklist2", DEFAULT_GROUP, RegistryType.PUBLISHER); + } +} diff --git a/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/StopPushDataSwitchTest.java b/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/StopPushDataSwitchTest.java index 61bff0670..ca7ff690f 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/StopPushDataSwitchTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/resource/meta/StopPushDataSwitchTest.java @@ -16,7 +16,24 @@ */ package com.alipay.sofa.registry.test.resource.meta; +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.CollectionUtils; + import com.alipay.sofa.registry.client.api.model.RegistryType; +import com.alipay.sofa.registry.client.api.model.UserData; import com.alipay.sofa.registry.client.api.registration.PublisherRegistration; import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration; import com.alipay.sofa.registry.common.model.store.Subscriber; @@ -29,18 +46,6 @@ import com.alipay.sofa.registry.task.listener.TaskEvent; import com.alipay.sofa.registry.task.listener.TaskListenerManager; import com.alipay.sofa.registry.test.BaseIntegrationTest; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.CollectionUtils; - -import java.util.Map; - -import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; /** * @author xuanbei @@ -48,40 +53,58 @@ */ @RunWith(SpringRunner.class) public class StopPushDataSwitchTest extends BaseIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(StopPushDataSwitchTest.class); + @Test public void testStopPushDataSwitch() throws Exception { // open stop push switch - assertTrue(metaChannel.getWebTarget().path("stopPushDataSwitch/open") - .request(APPLICATION_JSON).get(Result.class).isSuccess()); - BaseIntegrationTest.dataId = null; + assertTrue( + metaChannel.getWebTarget().path("stopPushDataSwitch/open").request(APPLICATION_JSON).get(Result.class) + .isSuccess()); + Thread.sleep(2000L); + + AtomicReference dataIdResult = new AtomicReference<>(); + AtomicReference userDataResult = new AtomicReference<>(); // register Publisher & Subscriber, Subscriber get no data String dataId = "test-dataId-" + System.currentTimeMillis(); String value = "test stop publish data switch"; + + LOGGER.info("dataidIn:" + dataId); + + SessionServerConfig sessionServerConfig = sessionApplicationContext.getBean(SessionServerConfig.class); + + LOGGER.info("sessionServerConfig.isStopPushSwitch:" + sessionServerConfig.isStopPushSwitch()); + PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); - SubscriberRegistration subReg = new SubscriberRegistration(dataId, - new MySubscriberDataObserver()); + SubscriberRegistration subReg = new SubscriberRegistration(dataId, (dataIdOb, data) -> { + LOGGER.info("sub:" + data); + dataIdResult.set(dataIdOb); + userDataResult.set(data); + }); subReg.setScopeEnum(ScopeEnum.dataCenter); registryClient1.register(subReg); - Thread.sleep(1000L); - assertNull(BaseIntegrationTest.dataId); + Thread.sleep(2000L); + assertNull(dataIdResult.get()); // close stop push switch - assertTrue(metaChannel.getWebTarget().path("stopPushDataSwitch/close") - .request(APPLICATION_JSON).get(Result.class).isSuccess()); - Thread.sleep(1000L); + assertTrue( + metaChannel.getWebTarget().path("stopPushDataSwitch/close").request(APPLICATION_JSON).get(Result.class) + .isSuccess()); + Thread.sleep(2000L); // Subscriber get data, test data - assertEquals(dataId, this.dataId); - assertEquals(LOCAL_REGION, userData.getLocalZone()); - assertEquals(1, userData.getZoneData().size()); - assertEquals(1, userData.getZoneData().values().size()); - assertEquals(true, userData.getZoneData().containsKey(LOCAL_REGION)); - assertEquals(1, userData.getZoneData().get(LOCAL_REGION).size()); - assertEquals(value, userData.getZoneData().get(LOCAL_REGION).get(0)); + assertEquals(dataId, dataIdResult.get()); + assertEquals(LOCAL_REGION, userDataResult.get().getLocalZone()); + assertEquals(1, userDataResult.get().getZoneData().size()); + assertEquals(1, userDataResult.get().getZoneData().values().size()); + assertEquals(true, userDataResult.get().getZoneData().containsKey(LOCAL_REGION)); + assertEquals(1, userDataResult.get().getZoneData().get(LOCAL_REGION).size()); + assertEquals(value, userDataResult.get().getZoneData().get(LOCAL_REGION).get(0)); // unregister Publisher & Subscriber registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); @@ -95,28 +118,41 @@ public void testStopPushDataSwitch() throws Exception { @Test public void testStopPushDataSwitchByCode() throws Exception { // open stop push switch - assertTrue(metaChannel.getWebTarget().path("stopPushDataSwitch/open").request(APPLICATION_JSON) - .get(Result.class) - .isSuccess()); - BaseIntegrationTest.dataId = null; + assertTrue( + metaChannel.getWebTarget().path("stopPushDataSwitch/open").request(APPLICATION_JSON).get(Result.class) + .isSuccess()); + Thread.sleep(2000L); + + AtomicReference dataIdResult = new AtomicReference<>(); + AtomicReference userDataResult = new AtomicReference<>(); // register Publisher & Subscriber, Subscriber get no data String dataId = "test-dataId-hahhahahahha-" + System.currentTimeMillis(); String value = "test stop publish data switch by code"; + + LOGGER.info("dataidIn2:" + dataId); + + SessionServerConfig sessionServerConfig = sessionApplicationContext.getBean(SessionServerConfig.class); + + LOGGER.info("sessionServerConfig.isStopPushSwitch2:" + sessionServerConfig.isStopPushSwitch()); PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); - SubscriberRegistration subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); + SubscriberRegistration subReg = new SubscriberRegistration(dataId, (dataIdOb, data) -> { + LOGGER.info("sub:" + data); + dataIdResult.set(dataIdOb); + userDataResult.set(data); + }); subReg.setScopeEnum(ScopeEnum.dataCenter); registryClient1.register(subReg); - Thread.sleep(1000L); - assertNull(BaseIntegrationTest.dataId); + Thread.sleep(2000L); + assertNull(dataIdResult.get()); // invoke code directly Interests sessionInterests = sessionApplicationContext.getBean(Interests.class); TaskListenerManager taskListenerManager = sessionApplicationContext.getBean(TaskListenerManager.class); - SessionServerConfig sessionServerConfig = sessionApplicationContext.getBean(SessionServerConfig.class); + if (sessionInterests instanceof ReSubscribers) { ReSubscribers reSubscriber = (ReSubscribers) sessionInterests; @@ -138,19 +174,19 @@ public void testStopPushDataSwitchByCode() throws Exception { Thread.sleep(1000); // Subscriber get data, test data - assertEquals(dataId, this.dataId); - assertEquals(LOCAL_REGION, userData.getLocalZone()); - assertEquals(1, userData.getZoneData().size()); - assertEquals(1, userData.getZoneData().values().size()); - assertEquals(true, userData.getZoneData().containsKey(LOCAL_REGION)); - assertEquals(1, userData.getZoneData().get(LOCAL_REGION).size()); - assertEquals(value, userData.getZoneData().get(LOCAL_REGION).get(0)); + assertEquals(dataId, dataIdResult.get()); + assertEquals(LOCAL_REGION, userDataResult.get().getLocalZone()); + assertEquals(1, userDataResult.get().getZoneData().size()); + assertEquals(1, userDataResult.get().getZoneData().values().size()); + assertEquals(true, userDataResult.get().getZoneData().containsKey(LOCAL_REGION)); + assertEquals(1, userDataResult.get().getZoneData().get(LOCAL_REGION).size()); + assertEquals(value, userDataResult.get().getZoneData().get(LOCAL_REGION).get(0)); // unregister Publisher & Subscriber, close stop push switch registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.SUBSCRIBER); registryClient1.unregister(dataId, DEFAULT_GROUP, RegistryType.PUBLISHER); - assertTrue(metaChannel.getWebTarget().path("stopPushDataSwitch/close").request(APPLICATION_JSON) - .get(Result.class) - .isSuccess()); + assertTrue( + metaChannel.getWebTarget().path("stopPushDataSwitch/close").request(APPLICATION_JSON).get(Result.class) + .isSuccess()); } } diff --git a/test/src/test/java/com/alipay/sofa/registry/test/resource/session/ClientsOpenResourceTest.java b/test/src/test/java/com/alipay/sofa/registry/test/resource/session/ClientsOpenResourceTest.java index f456d5b01..c9a74282e 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/resource/session/ClientsOpenResourceTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/resource/session/ClientsOpenResourceTest.java @@ -38,7 +38,7 @@ public void testClientOff() throws Exception { String value = "test client off"; PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(1000L); + Thread.sleep(2000L); String countResult = dataChannel.getWebTarget().path("digest/datum/count") .request(APPLICATION_JSON).get(String.class); diff --git a/test/src/test/java/com/alipay/sofa/registry/test/resource/session/SessionDigestResourceTest.java b/test/src/test/java/com/alipay/sofa/registry/test/resource/session/SessionDigestResourceTest.java index 2c0b7f28c..5ed053960 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/resource/session/SessionDigestResourceTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/resource/session/SessionDigestResourceTest.java @@ -59,13 +59,13 @@ public static void beforeClass() throws Exception { PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); SubscriberRegistration subReg = new SubscriberRegistration(dataId, new MySubscriberDataObserver()); subReg.setScopeEnum(ScopeEnum.dataCenter); registryClient1.register(subReg); - Thread.sleep(500L); + Thread.sleep(2000L); } @AfterClass diff --git a/test/src/test/java/com/alipay/sofa/registry/test/sync/DataSyncTest.java b/test/src/test/java/com/alipay/sofa/registry/test/sync/DataSyncTest.java index 0bccb8810..93ef9a882 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/sync/DataSyncTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/sync/DataSyncTest.java @@ -16,6 +16,16 @@ */ package com.alipay.sofa.registry.test.sync; +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration; import com.alipay.sofa.registry.common.model.CommonResponse; import com.alipay.sofa.registry.common.model.dataserver.NotifyDataSyncRequest; @@ -32,15 +42,6 @@ import com.alipay.sofa.registry.server.data.remoting.dataserver.DataServerConnectionFactory; import com.alipay.sofa.registry.server.data.remoting.dataserver.handler.DataSyncServerConnectionHandler; import com.alipay.sofa.registry.test.BaseIntegrationTest; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringRunner; - -import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; -import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; /** * @author xuanbei @@ -94,7 +95,7 @@ public void doTest() throws Exception { registryClient1.register(subReg); // assert result - Thread.sleep(1000L); + Thread.sleep(5000L); assertEquals(MockSyncDataHandler.dataId, BaseIntegrationTest.dataId); assertEquals(LOCAL_REGION, userData.getLocalZone()); assertEquals(1, userData.getZoneData().size()); diff --git a/test/src/test/java/com/alipay/sofa/registry/test/sync/MockSyncDataHandler.java b/test/src/test/java/com/alipay/sofa/registry/test/sync/MockSyncDataHandler.java index 502fc2e30..732922460 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/sync/MockSyncDataHandler.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/sync/MockSyncDataHandler.java @@ -16,6 +16,18 @@ */ package com.alipay.sofa.registry.test.sync; +import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; +import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; +import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_ADDRESS; +import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_DATACENTER; +import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_REGION; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + import com.alipay.sofa.registry.common.model.GenericResponse; import com.alipay.sofa.registry.common.model.Node; import com.alipay.sofa.registry.common.model.ServerDataBox; @@ -28,20 +40,9 @@ import com.alipay.sofa.registry.common.model.store.URL; import com.alipay.sofa.registry.remoting.Channel; import com.alipay.sofa.registry.server.data.remoting.handler.AbstractServerHandler; +import com.alipay.sofa.registry.util.DatumVersionUtil; import com.alipay.sofa.registry.util.ParaCheckUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import static com.alipay.sofa.registry.client.constants.ValueConstants.DEFAULT_GROUP; -import static com.alipay.sofa.registry.common.model.constants.ValueConstants.DEFAULT_INSTANCE_ID; -import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_ADDRESS; -import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_DATACENTER; -import static com.alipay.sofa.registry.test.BaseIntegrationTest.LOCAL_REGION; - /** * mock SyncDataHandler, it will return fixed Datum. * @@ -51,7 +52,7 @@ public class MockSyncDataHandler extends AbstractServerHandler { public static String dataId = "test-dataId-" + System.currentTimeMillis(); public static String value = "MockSyncDataHandler"; - public static long version = System.currentTimeMillis(); + public static long version = DatumVersionUtil.nextId(); @Override public void checkParam(SyncDataRequest request) throws RuntimeException { diff --git a/test/src/test/java/com/alipay/sofa/registry/test/sync/SyncDataHandlerTest.java b/test/src/test/java/com/alipay/sofa/registry/test/sync/SyncDataHandlerTest.java index 074960dc9..f9fc97667 100644 --- a/test/src/test/java/com/alipay/sofa/registry/test/sync/SyncDataHandlerTest.java +++ b/test/src/test/java/com/alipay/sofa/registry/test/sync/SyncDataHandlerTest.java @@ -51,7 +51,7 @@ public void doTest() throws Exception { String value = "test publish"; PublisherRegistration registration = new PublisherRegistration(dataId); registryClient1.register(registration, value); - Thread.sleep(500L); + Thread.sleep(2000L); // request syncData DataNodeExchanger dataNodeExchanger = dataApplicationContext.getBean("dataNodeExchanger",