|
21 | 21 | import com.alibaba.fluss.cluster.Endpoint; |
22 | 22 | import com.alibaba.fluss.cluster.ServerNode; |
23 | 23 | import com.alibaba.fluss.cluster.ServerType; |
| 24 | +import com.alibaba.fluss.cluster.maintencance.ServerTag; |
24 | 25 | import com.alibaba.fluss.config.ConfigOptions; |
25 | 26 | import com.alibaba.fluss.config.Configuration; |
26 | 27 | import com.alibaba.fluss.exception.FencedLeaderEpochException; |
27 | 28 | import com.alibaba.fluss.exception.FlussRuntimeException; |
28 | 29 | import com.alibaba.fluss.exception.InvalidCoordinatorException; |
29 | 30 | import com.alibaba.fluss.exception.InvalidUpdateVersionException; |
| 31 | +import com.alibaba.fluss.exception.ServerNotExistException; |
| 32 | +import com.alibaba.fluss.exception.ServerTagAlreadyExistException; |
| 33 | +import com.alibaba.fluss.exception.ServerTagNotExistException; |
| 34 | +import com.alibaba.fluss.exception.UnknownServerException; |
30 | 35 | import com.alibaba.fluss.exception.UnknownTableOrBucketException; |
31 | 36 | import com.alibaba.fluss.metadata.PhysicalTablePath; |
32 | 37 | import com.alibaba.fluss.metadata.TableBucket; |
|
35 | 40 | import com.alibaba.fluss.metadata.TablePartition; |
36 | 41 | import com.alibaba.fluss.metadata.TablePath; |
37 | 42 | import com.alibaba.fluss.metrics.MetricNames; |
| 43 | +import com.alibaba.fluss.rpc.messages.AddServerTagResponse; |
38 | 44 | import com.alibaba.fluss.rpc.messages.AdjustIsrResponse; |
39 | 45 | import com.alibaba.fluss.rpc.messages.CommitKvSnapshotResponse; |
40 | 46 | import com.alibaba.fluss.rpc.messages.CommitLakeTableSnapshotResponse; |
41 | 47 | import com.alibaba.fluss.rpc.messages.CommitRemoteLogManifestResponse; |
42 | 48 | import com.alibaba.fluss.rpc.messages.PbCommitLakeTableSnapshotRespForTable; |
| 49 | +import com.alibaba.fluss.rpc.messages.RemoveServerTagResponse; |
43 | 50 | import com.alibaba.fluss.rpc.protocol.ApiError; |
44 | 51 | import com.alibaba.fluss.server.coordinator.event.AccessContextEvent; |
| 52 | +import com.alibaba.fluss.server.coordinator.event.AddServerTagEvent; |
45 | 53 | import com.alibaba.fluss.server.coordinator.event.AdjustIsrReceivedEvent; |
46 | 54 | import com.alibaba.fluss.server.coordinator.event.CommitKvSnapshotEvent; |
47 | 55 | import com.alibaba.fluss.server.coordinator.event.CommitLakeTableSnapshotEvent; |
|
58 | 66 | import com.alibaba.fluss.server.coordinator.event.FencedCoordinatorEvent; |
59 | 67 | import com.alibaba.fluss.server.coordinator.event.NewTabletServerEvent; |
60 | 68 | import com.alibaba.fluss.server.coordinator.event.NotifyLeaderAndIsrResponseReceivedEvent; |
| 69 | +import com.alibaba.fluss.server.coordinator.event.RemoveServerTagEvent; |
61 | 70 | import com.alibaba.fluss.server.coordinator.event.watcher.TableChangeWatcher; |
62 | 71 | import com.alibaba.fluss.server.coordinator.event.watcher.TabletServerChangeWatcher; |
63 | 72 | import com.alibaba.fluss.server.coordinator.statemachine.ReplicaState; |
|
79 | 88 | import com.alibaba.fluss.server.zk.data.LeaderAndIsr; |
80 | 89 | import com.alibaba.fluss.server.zk.data.PartitionAssignment; |
81 | 90 | import com.alibaba.fluss.server.zk.data.RemoteLogManifestHandle; |
| 91 | +import com.alibaba.fluss.server.zk.data.ServerTags; |
82 | 92 | import com.alibaba.fluss.server.zk.data.TableAssignment; |
83 | 93 | import com.alibaba.fluss.server.zk.data.TabletServerRegistration; |
84 | 94 | import com.alibaba.fluss.server.zk.data.ZkData.PartitionIdsZNode; |
@@ -319,6 +329,11 @@ private void initCoordinatorContext() throws Exception { |
319 | 329 | // init tablet server channels |
320 | 330 | coordinatorChannelManager.startup(internalServerNodes); |
321 | 331 |
|
| 332 | + // load server tags. |
| 333 | + zooKeeperClient |
| 334 | + .getServerTags() |
| 335 | + .ifPresent(tags -> coordinatorContext.initSeverTags(tags.getServerTags())); |
| 336 | + |
322 | 337 | // load all tables |
323 | 338 | List<TableInfo> autoPartitionTables = new ArrayList<>(); |
324 | 339 | List<Tuple2<TableInfo, Long>> lakeTables = new ArrayList<>(); |
@@ -493,6 +508,16 @@ public void process(CoordinatorEvent event) { |
493 | 508 | completeFromCallable( |
494 | 509 | commitLakeTableSnapshotEvent.getRespCallback(), |
495 | 510 | () -> tryProcessCommitLakeTableSnapshot(commitLakeTableSnapshotEvent)); |
| 511 | + } else if (event instanceof AddServerTagEvent) { |
| 512 | + AddServerTagEvent addServerTagEvent = (AddServerTagEvent) event; |
| 513 | + completeFromCallable( |
| 514 | + addServerTagEvent.getRespCallback(), |
| 515 | + () -> processAddServerTag(addServerTagEvent)); |
| 516 | + } else if (event instanceof RemoveServerTagEvent) { |
| 517 | + RemoveServerTagEvent removeServerTagEvent = (RemoveServerTagEvent) event; |
| 518 | + completeFromCallable( |
| 519 | + removeServerTagEvent.getRespCallback(), |
| 520 | + () -> processRemoveServerTag(removeServerTagEvent)); |
496 | 521 | } else if (event instanceof AccessContextEvent) { |
497 | 522 | AccessContextEvent<?> accessContextEvent = (AccessContextEvent<?>) event; |
498 | 523 | processAccessContext(accessContextEvent); |
@@ -884,6 +909,90 @@ private void processDeadTabletServer(DeadTabletServerEvent deadTabletServerEvent |
884 | 909 | updateTabletServerMetadataCache(serverInfos, null, null, bucketsWithOfflineLeader); |
885 | 910 | } |
886 | 911 |
|
| 912 | + private AddServerTagResponse processAddServerTag(AddServerTagEvent event) { |
| 913 | + AddServerTagResponse addServerTagResponse = new AddServerTagResponse(); |
| 914 | + List<Integer> serverIds = event.getServerIds(); |
| 915 | + ServerTag serverTag = event.getServerTag(); |
| 916 | + |
| 917 | + // Verify that dose serverTag exist for input serverIds. If any of them exists, throw |
| 918 | + // an error and none of them will be written to coordinatorContext and zk. |
| 919 | + Map<Integer, ServerInfo> liveTabletServers = coordinatorContext.getLiveTabletServers(); |
| 920 | + for (Integer serverId : serverIds) { |
| 921 | + if (!liveTabletServers.containsKey(serverId)) { |
| 922 | + throw new ServerNotExistException( |
| 923 | + String.format( |
| 924 | + "Server %s not exists when trying to add server tag.", serverId)); |
| 925 | + } |
| 926 | + |
| 927 | + if (coordinatorContext.getServerTag(serverId).isPresent()) { |
| 928 | + throw new ServerTagAlreadyExistException( |
| 929 | + String.format( |
| 930 | + "Server tag %s already exists for server %s.", |
| 931 | + serverTag, serverId)); |
| 932 | + } |
| 933 | + } |
| 934 | + |
| 935 | + // First register to zk, and then update coordinatorContext. |
| 936 | + Map<Integer, ServerTag> serverTags = coordinatorContext.getServerTags(); |
| 937 | + for (Integer serverId : serverIds) { |
| 938 | + serverTags.put(serverId, serverTag); |
| 939 | + } |
| 940 | + |
| 941 | + try { |
| 942 | + zooKeeperClient.registerServerTags(new ServerTags(serverTags)); |
| 943 | + } catch (Exception e) { |
| 944 | + LOG.error("Error when register server tags to zookeeper.", e); |
| 945 | + throw new UnknownServerException("Error when register server tags to zookeeper.", e); |
| 946 | + } |
| 947 | + |
| 948 | + // Then update coordinatorContext. |
| 949 | + serverIds.forEach(serverId -> coordinatorContext.putServerTag(serverId, serverTag)); |
| 950 | + |
| 951 | + return addServerTagResponse; |
| 952 | + } |
| 953 | + |
| 954 | + private RemoveServerTagResponse processRemoveServerTag(RemoveServerTagEvent event) { |
| 955 | + RemoveServerTagResponse removeServerTagResponse = new RemoveServerTagResponse(); |
| 956 | + List<Integer> serverIds = event.getServerIds(); |
| 957 | + ServerTag serverTag = event.getServerTag(); |
| 958 | + |
| 959 | + // Verify that dose serverTag not exist for input serverIds. If any of them not exists, |
| 960 | + // throw an error and none of them will be removed form coordinatorContext and zk. |
| 961 | + Map<Integer, ServerInfo> liveTabletServers = coordinatorContext.getLiveTabletServers(); |
| 962 | + for (Integer serverId : serverIds) { |
| 963 | + if (!liveTabletServers.containsKey(serverId)) { |
| 964 | + throw new ServerNotExistException( |
| 965 | + String.format( |
| 966 | + "Server %s not exists when trying to removing server tag.", |
| 967 | + serverId)); |
| 968 | + } |
| 969 | + |
| 970 | + if (!coordinatorContext.getServerTag(serverId).isPresent()) { |
| 971 | + throw new ServerTagNotExistException( |
| 972 | + String.format( |
| 973 | + "Server tag %s not exists for server %s.", serverTag, serverId)); |
| 974 | + } |
| 975 | + } |
| 976 | + |
| 977 | + // First register to zk, and then update coordinatorContext. |
| 978 | + Map<Integer, ServerTag> serverTags = coordinatorContext.getServerTags(); |
| 979 | + for (Integer serverId : serverIds) { |
| 980 | + serverTags.remove(serverId); |
| 981 | + } |
| 982 | + |
| 983 | + try { |
| 984 | + zooKeeperClient.registerServerTags(new ServerTags(serverTags)); |
| 985 | + } catch (Exception e) { |
| 986 | + LOG.error("Error when register server tags to zookeeper.", e); |
| 987 | + throw new UnknownServerException("Error when register server tags to zookeeper.", e); |
| 988 | + } |
| 989 | + |
| 990 | + // Then update coordinatorContext. |
| 991 | + serverIds.forEach(coordinatorContext::removeServerTag); |
| 992 | + |
| 993 | + return removeServerTagResponse; |
| 994 | + } |
| 995 | + |
887 | 996 | private List<AdjustIsrResultForBucket> tryProcessAdjustIsr( |
888 | 997 | Map<TableBucket, LeaderAndIsr> leaderAndIsrList) { |
889 | 998 | // TODO verify leader epoch. |
|
0 commit comments