1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.traffic.rule;
19
20 import com.google.common.base.Preconditions;
21 import lombok.Getter;
22 import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
23 import org.apache.shardingsphere.infra.algorithm.loadbalancer.core.LoadBalanceAlgorithm;
24 import org.apache.shardingsphere.infra.hint.HintValueContext;
25 import org.apache.shardingsphere.infra.rule.scope.GlobalRule;
26 import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
27 import org.apache.shardingsphere.infra.session.query.QueryContext;
28 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
29 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
30 import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration;
31 import org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration;
32 import org.apache.shardingsphere.traffic.api.traffic.hint.HintTrafficAlgorithm;
33 import org.apache.shardingsphere.traffic.api.traffic.hint.HintTrafficValue;
34 import org.apache.shardingsphere.traffic.api.traffic.identifier.SimplifiedTrafficAlgorithm;
35 import org.apache.shardingsphere.traffic.api.traffic.segment.SegmentTrafficAlgorithm;
36 import org.apache.shardingsphere.traffic.api.traffic.segment.SegmentTrafficValue;
37 import org.apache.shardingsphere.traffic.api.traffic.transaction.TransactionTrafficAlgorithm;
38 import org.apache.shardingsphere.traffic.api.traffic.transaction.TransactionTrafficValue;
39 import org.apache.shardingsphere.traffic.spi.TrafficAlgorithm;
40
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashSet;
44 import java.util.LinkedHashMap;
45 import java.util.LinkedHashSet;
46 import java.util.LinkedList;
47 import java.util.Map;
48 import java.util.Optional;
49
50
51
52
53 @Getter
54 public final class TrafficRule implements GlobalRule {
55
56 private final TrafficRuleConfiguration configuration;
57
58 private final Collection<TrafficStrategyRule> strategyRules;
59
60 public TrafficRule(final TrafficRuleConfiguration ruleConfig) {
61 configuration = ruleConfig;
62 Map<String, TrafficAlgorithm> trafficAlgorithms = createTrafficAlgorithms(ruleConfig.getTrafficAlgorithms());
63 Map<String, LoadBalanceAlgorithm> loadBalancers = createLoadBalanceAlgorithms(ruleConfig.getLoadBalancers());
64 strategyRules = createTrafficStrategyRules(ruleConfig.getTrafficStrategies(), trafficAlgorithms, loadBalancers);
65 }
66
67 private Map<String, TrafficAlgorithm> createTrafficAlgorithms(final Map<String, AlgorithmConfiguration> trafficAlgorithms) {
68 Map<String, TrafficAlgorithm> result = new LinkedHashMap<>();
69 for (TrafficStrategyConfiguration each : configuration.getTrafficStrategies()) {
70 if (null == trafficAlgorithms.get(each.getAlgorithmName())) {
71 break;
72 }
73 AlgorithmConfiguration algorithmConfig = trafficAlgorithms.get(each.getAlgorithmName());
74 result.put(each.getName() + "." + each.getAlgorithmName(), TypedSPILoader.getService(TrafficAlgorithm.class, algorithmConfig.getType(), algorithmConfig.getProps()));
75 }
76 return result;
77 }
78
79 private Map<String, LoadBalanceAlgorithm> createLoadBalanceAlgorithms(final Map<String, AlgorithmConfiguration> loadBalancers) {
80 Map<String, LoadBalanceAlgorithm> result = new LinkedHashMap<>();
81 for (TrafficStrategyConfiguration each : configuration.getTrafficStrategies()) {
82 if (null == loadBalancers.get(each.getLoadBalancerName())) {
83 break;
84 }
85 AlgorithmConfiguration algorithmConfig = loadBalancers.get(each.getLoadBalancerName());
86 result.put(each.getName() + "." + each.getLoadBalancerName(), TypedSPILoader.getService(LoadBalanceAlgorithm.class, algorithmConfig.getType(), algorithmConfig.getProps()));
87 }
88 return result;
89 }
90
91 private Collection<TrafficStrategyRule> createTrafficStrategyRules(final Collection<TrafficStrategyConfiguration> trafficStrategies,
92 final Map<String, TrafficAlgorithm> trafficAlgorithms, final Map<String, LoadBalanceAlgorithm> loadBalancers) {
93 Collection<TrafficStrategyRule> noneTransactionStrategyRules = new LinkedList<>();
94 Collection<TrafficStrategyRule> result = new LinkedList<>();
95 for (TrafficStrategyConfiguration each : trafficStrategies) {
96 TrafficAlgorithm trafficAlgorithm = getTrafficAlgorithm(each, trafficAlgorithms);
97 TrafficStrategyRule trafficStrategyRule = createTrafficStrategyRule(each, trafficAlgorithm, loadBalancers);
98 if (isTransactionStrategyRule(trafficAlgorithm)) {
99 result.add(trafficStrategyRule);
100 } else {
101 noneTransactionStrategyRules.add(trafficStrategyRule);
102 }
103 }
104 result.addAll(noneTransactionStrategyRules);
105 return result;
106 }
107
108 private TrafficStrategyRule createTrafficStrategyRule(final TrafficStrategyConfiguration strategyConfig, final TrafficAlgorithm trafficAlgorithm,
109 final Map<String, LoadBalanceAlgorithm> loadBalancers) {
110 TrafficStrategyRule result;
111 if (trafficAlgorithm instanceof SimplifiedTrafficAlgorithm) {
112 result = new TrafficStrategyRule(strategyConfig.getName(), Collections.emptyList(), trafficAlgorithm, null);
113 } else {
114 LoadBalanceAlgorithm loadBalancer = getLoadBalancer(strategyConfig, loadBalancers);
115 result = new TrafficStrategyRule(strategyConfig.getName(), new LinkedHashSet<>(strategyConfig.getLabels()), trafficAlgorithm, loadBalancer);
116 }
117 return result;
118 }
119
120 private boolean isTransactionStrategyRule(final TrafficAlgorithm trafficAlgorithm) {
121 return trafficAlgorithm instanceof TransactionTrafficAlgorithm;
122 }
123
124
125
126
127
128
129
130
131 public Optional<TrafficStrategyRule> findMatchedStrategyRule(final QueryContext queryContext, final boolean inTransaction) {
132 for (TrafficStrategyRule each : strategyRules) {
133 if (match(each.getTrafficAlgorithm(), queryContext, inTransaction)) {
134 return Optional.of(each);
135 }
136 }
137 return Optional.empty();
138 }
139
140 private TrafficAlgorithm getTrafficAlgorithm(final TrafficStrategyConfiguration strategyConfig, final Map<String, TrafficAlgorithm> trafficAlgorithms) {
141 TrafficAlgorithm result = trafficAlgorithms.get(strategyConfig.getName() + "." + strategyConfig.getAlgorithmName());
142 Preconditions.checkState(null != result, "Traffic algorithm can not be null.");
143 return result;
144 }
145
146 private boolean match(final TrafficAlgorithm trafficAlgorithm, final QueryContext queryContext, final boolean inTransaction) {
147 if (trafficAlgorithm instanceof TransactionTrafficAlgorithm) {
148 return matchTransactionTraffic((TransactionTrafficAlgorithm) trafficAlgorithm, inTransaction);
149 }
150 if (trafficAlgorithm instanceof HintTrafficAlgorithm) {
151 return matchHintTraffic((HintTrafficAlgorithm) trafficAlgorithm, queryContext.getHintValueContext());
152 }
153 if (trafficAlgorithm instanceof SegmentTrafficAlgorithm) {
154 SQLStatement sqlStatement = queryContext.getSqlStatementContext().getSqlStatement();
155 return matchSegmentTraffic((SegmentTrafficAlgorithm) trafficAlgorithm, queryContext.getSql(), sqlStatement);
156 }
157 return false;
158 }
159
160 private boolean matchHintTraffic(final HintTrafficAlgorithm trafficAlgorithm, final HintValueContext hintValueContext) {
161 HintTrafficValue hintTrafficValue = new HintTrafficValue(hintValueContext);
162 return trafficAlgorithm.match(hintTrafficValue);
163 }
164
165 private boolean matchSegmentTraffic(final SegmentTrafficAlgorithm trafficAlgorithm, final String sql, final SQLStatement sqlStatement) {
166 SegmentTrafficValue segmentTrafficValue = new SegmentTrafficValue(sqlStatement, sql);
167 return trafficAlgorithm.match(segmentTrafficValue);
168 }
169
170 private boolean matchTransactionTraffic(final TransactionTrafficAlgorithm trafficAlgorithm, final boolean inTransaction) {
171 TransactionTrafficValue transactionTrafficValue = new TransactionTrafficValue(inTransaction);
172 return trafficAlgorithm.match(transactionTrafficValue);
173 }
174
175 private LoadBalanceAlgorithm getLoadBalancer(final TrafficStrategyConfiguration strategyConfig, final Map<String, LoadBalanceAlgorithm> loadBalancers) {
176 LoadBalanceAlgorithm result = loadBalancers.get(strategyConfig.getName() + "." + strategyConfig.getLoadBalancerName());
177 Preconditions.checkState(null != result, "Traffic load balance algorithm can not be null.");
178 return result;
179 }
180
181
182
183
184
185
186 public Collection<String> getLabels() {
187 Collection<String> result = new HashSet<>();
188 for (TrafficStrategyRule each : strategyRules) {
189 result.addAll(each.getLabels());
190 }
191 return result;
192 }
193
194 @Override
195 public RuleAttributes getAttributes() {
196 return new RuleAttributes();
197 }
198 }