Update Jedis 4.x plugin to support Sharding and Cluster models. (#677)

This commit is contained in:
pg.yang 2024-03-31 20:13:03 +08:00 committed by GitHub
parent a751e324f6
commit 30d60b9c61
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 478 additions and 8 deletions

View File

@ -19,6 +19,7 @@ Release Notes.
* Fix a bug in Spring Cloud Gateway if HttpClientFinalizer#send does not invoke, the span created at NettyRoutingFilterInterceptor can not stop.
* Fix not tracing in HttpClient v5 when HttpHost(arg[0]) is null but `RoutingSupport#determineHost` works.
* Support across thread tracing for SOFA-RPC.
* Update Jedis 4.x plugin to support Sharding and Cluster models.
#### Documentation
* Update docs to describe `expired-plugins`.

View File

@ -18,6 +18,7 @@
package org.apache.skywalking.apm.plugin.jedis.v4;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
@ -39,6 +40,8 @@ public abstract class AbstractConnectionInterceptor implements InstanceMethodsAr
private static final String CACHE_TYPE = "Redis";
private static final StringTag TAG_ARGS = new StringTag("actual_target");
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
Iterator<Rawable> iterator = getCommands(allArguments);
@ -49,12 +52,15 @@ public abstract class AbstractConnectionInterceptor implements InstanceMethodsAr
// Use lowercase to make config compatible with jedis-2.x-3.x plugin
// Refer to `plugin.jedis.operation_mapping_read`, `plugin.jedis.operation_mapping_write` config item in agent.config
String cmd = protocolCommand == null ? UNKNOWN : protocolCommand.toLowerCase();
String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
ConnectionInformation connectionData = (ConnectionInformation) objInst.getSkyWalkingDynamicField();
// Use cluster information to adapt Virtual Cache if exists, otherwise use real server host
String peer = StringUtil.isBlank(connectionData.getClusterNodes()) ? connectionData.getActualTarget() : connectionData.getClusterNodes();
AbstractSpan span = ContextManager.createExitSpan("Jedis/" + cmd, peer);
span.setComponent(ComponentsDefine.JEDIS);
readKeyIfNecessary(iterator).ifPresent(key -> Tags.CACHE_KEY.set(span, key));
Tags.CACHE_CMD.set(span, cmd);
Tags.CACHE_TYPE.set(span, CACHE_TYPE);
TAG_ARGS.set(span, connectionData.getActualTarget());
parseOperation(cmd).ifPresent(op -> Tags.CACHE_OP.set(span, op));
SpanLayer.asCache(span);
}

View File

@ -26,6 +26,8 @@ public class ConnectionConstructorInterceptor implements InstanceConstructorInte
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable {
HostAndPort hostAndPort = ((DefaultJedisSocketFactory) allArguments[0]).getHostAndPort();
objInst.setSkyWalkingDynamicField(hostAndPort.getHost() + ":" + hostAndPort.getPort());
ConnectionInformation connectionData = new ConnectionInformation();
connectionData.setActualTarget(hostAndPort.toString());
objInst.setSkyWalkingDynamicField(connectionData);
}
}

View File

@ -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 org.apache.skywalking.apm.plugin.jedis.v4;
import lombok.Data;
@Data
public class ConnectionInformation {
private String clusterNodes;
private String actualTarget;
}

View File

@ -0,0 +1,43 @@
/*
* 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 org.apache.skywalking.apm.plugin.jedis.v4;
import java.util.Collection;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import org.apache.skywalking.apm.util.StringUtil;
import redis.clients.jedis.HostAndPort;
public class ConnectionProviderConstructorInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(final EnhancedInstance objInst, final Object[] allArguments) throws Throwable {
if (objInst.getSkyWalkingDynamicField() != null) {
return;
}
Object arg = allArguments[0];
if (arg instanceof Collection) {
Collection<?> collection = (Collection<?>) arg;
final String[] array = collection.stream().map(Object::toString).toArray(String[]::new);
objInst.setSkyWalkingDynamicField(StringUtil.join(',', array));
}
if (arg instanceof HostAndPort) {
objInst.setSkyWalkingDynamicField(arg.toString());
}
}
}

View File

@ -0,0 +1,60 @@
/*
* 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 org.apache.skywalking.apm.plugin.jedis.v4;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
public class ConnectionProviderGetConnectionInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
}
@Override
public Object afterMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final Object ret) throws Throwable {
if (ret instanceof EnhancedInstance) {
EnhancedInstance connection = (EnhancedInstance) ret;
if (connection.getSkyWalkingDynamicField() != null
&& connection.getSkyWalkingDynamicField() instanceof ConnectionInformation) {
((ConnectionInformation) connection.getSkyWalkingDynamicField()).setClusterNodes(
(String) objInst.getSkyWalkingDynamicField());
}
}
return ret;
}
@Override
public void handleMethodException(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final Throwable t) {
}
}

View File

@ -18,6 +18,7 @@
package org.apache.skywalking.apm.plugin.jedis.v4;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
@ -27,18 +28,23 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInt
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.util.StringUtil;
public class JedisMethodInterceptor implements InstanceMethodsAroundInterceptor {
private static final StringTag TAG_ARGS = new StringTag("actual_target");
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
final ConnectionInformation connectionData = (ConnectionInformation) objInst.getSkyWalkingDynamicField();
// Use cluster information to adapt Virtual Cache if exists, otherwise use real server host
String peer = StringUtil.isBlank(connectionData.getClusterNodes()) ? connectionData.getActualTarget() : connectionData.getClusterNodes();
AbstractSpan span = ContextManager.createExitSpan("Jedis/" + method.getName(), peer);
span.setComponent(ComponentsDefine.JEDIS);
SpanLayer.asCache(span);
Tags.CACHE_TYPE.set(span, "Redis");
Tags.CACHE_CMD.set(span, "BATCH_EXECUTE");
TAG_ARGS.set(span, connectionData.getActualTarget());
}
@Override

View File

@ -0,0 +1,81 @@
/*
* 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 org.apache.skywalking.apm.plugin.jedis.v4.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch;
public class ConnectionProviderInstrumentation extends AbstractWitnessInstrumentation {
private static final String ENHANCE_INTERFACE = "redis.clients.jedis.providers.ConnectionProvider";
private static final String CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderConstructorInterceptor";
private static final String CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderGetConnectionInterceptor";
@Override
protected ClassMatch enhanceClass() {
return byHierarchyMatch(ENHANCE_INTERFACE);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[]{
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return ElementMatchers.takesArgument(0, named("redis.clients.jedis.HostAndPort"))
.or(ElementMatchers.takesArgument(0, hasSuperType(named("java.util.Collection"))));
}
@Override
public String getConstructorInterceptor() {
return CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS;
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("getConnection");
}
@Override
public String getMethodsInterceptor() {
return CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}

View File

@ -16,4 +16,5 @@
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionInstrumentation
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.PipelineInstrumentation
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionProviderInstrumentation

View File

@ -36,6 +36,7 @@ segmentItems:
- {key: cache.key, value: a}
- {key: cache.cmd, value: set}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/get
operationId: 0
@ -53,6 +54,7 @@ segmentItems:
- {key: cache.key, value: a}
- {key: cache.cmd, value: get}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: read}
- operationName: Jedis/del
operationId: 0
@ -70,6 +72,7 @@ segmentItems:
- {key: cache.key, value: a}
- {key: cache.cmd, value: del}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/syncAndReturnAll
operationId: 0
@ -86,6 +89,7 @@ segmentItems:
tags:
- {key: cache.type, value: Redis}
- {key: cache.cmd, value: BATCH_EXECUTE}
- {key: actual_target, value: 'redis-server:6379'}
- operationName: Jedis/exec
operationId: 0
parentSpanId: 0
@ -101,6 +105,7 @@ segmentItems:
tags:
- {key: cache.type, value: Redis}
- {key: cache.cmd, value: BATCH_EXECUTE}
- {key: actual_target, value: 'redis-server:6379'}
- operationName: Jedis/discard
operationId: 0
parentSpanId: 0
@ -116,6 +121,7 @@ segmentItems:
tags:
- {key: cache.type, value: Redis}
- {key: cache.cmd, value: BATCH_EXECUTE}
- {key: actual_target, value: 'redis-server:6379'}
- operationName: Jedis/xadd
operationId: 0
parentSpanId: 0
@ -132,6 +138,7 @@ segmentItems:
- {key: cache.key, value: abc}
- {key: cache.cmd, value: xadd}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/xread
operationId: 0
@ -148,6 +155,7 @@ segmentItems:
tags:
- {key: cache.cmd, value: xread}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: read}
- operationName: Jedis/xdel
operationId: 0
@ -165,6 +173,109 @@ segmentItems:
- {key: cache.key, value: abc}
- {key: cache.cmd, value: xdel}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/set
parentSpanId: 0
spanId: 10
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-server:6379,redis-server:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: set}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/get
parentSpanId: 0
spanId: 11
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-server:6379,redis-server:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: get}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: read}
- operationName: Jedis/del
parentSpanId: 0
spanId: 12
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-server:6379,redis-server:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: del}
- {key: cache.type, value: Redis}
- {key: actual_target, value: 'redis-server:6379'}
- {key: cache.op, value: write}
- operationName: Jedis/set
parentSpanId: 0
spanId: 13
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: set}
- {key: cache.type, value: Redis}
- {key: actual_target, value: not blank }
- {key: cache.op, value: write}
- operationName: Jedis/get
parentSpanId: 0
spanId: 14
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: get}
- {key: cache.type, value: Redis}
- {key: actual_target, value: not blank}
- {key: cache.op, value: read}
- operationName: Jedis/del
parentSpanId: 0
spanId: 15
spanLayer: Cache
startTime: gt 0
endTime: gt 0
componentId: 30
isError: false
spanType: Exit
peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
skipAnalysis: false
tags:
- {key: cache.key, value: x}
- {key: cache.cmd, value: del}
- {key: cache.type, value: Redis}
- {key: actual_target, value: not blank }
- {key: cache.op, value: write}
- operationName: GET:/jedis-scenario/case/jedis-scenario
operationId: 0
@ -181,4 +292,4 @@ segmentItems:
tags:
- {key: url, value: 'http://localhost:8080/jedis-scenario/case/jedis-scenario'}
- {key: http.method, value: GET}
- {key: http.status_code, value: '200'}
- {key: http.status_code, value: '200'}

View File

@ -21,8 +21,27 @@ startScript: ./bin/startup.sh
environment:
- REDIS_HOST=redis-server
- REDIS_PORT=6379
- REDIS_CLUSTER_M1_HOST=redis-cluster-m1
- REDIS_CLUSTER_M1_PORT=6379
- REDIS_CLUSTER_M2_HOST=redis-cluster-m2
- REDIS_CLUSTER_M2_PORT=6379
- REDIS_CLUSTER_M3_HOST=redis-cluster-m3
- REDIS_CLUSTER_M3_PORT=6379
dependencies:
redis-server:
image: redis:7.0.4
hostname: redis-server
redis-cluster-m1:
image: redis:7.2.4
hostname: redis-cluster-m1
command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh"
redis-cluster-m2:
image: redis:7.2.4
hostname: redis-cluster-m2
command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh"
redis-cluster-m3:
image: redis:7.2.4
hostname: redis-cluster-m3
command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh"

View File

@ -18,10 +18,13 @@
package org.apache.skywalking.apm.testcase.jedis.controller;
import java.util.Arrays;
import java.util.HashSet;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.HostAndPort;
@RestController
@RequestMapping("/case")
@ -35,6 +38,21 @@ public class CaseController {
@Value("${redis.port:6379}")
private Integer redisPort;
@Value("${redis.cluster.m1.host:127.0.0.1}")
private String redisClusterM1Host;
@Value("${redis.cluster.m1.port:6379}")
private Integer redisClusterM1Port;
@Value("${redis.cluster.m2.host:127.0.0.1}")
private String redisClusterM2Host;
@Value("${redis.cluster.m2.port:6379}")
private Integer redisClusterM2Port;
@Value("${redis.cluster.m3.host:127.0.0.1}")
private String redisClusterM3Host;
@Value("${redis.cluster.m3.port:6379}")
private Integer redisClusterM3Port;
@RequestMapping("/jedis-scenario")
@ResponseBody
public String testcase() throws Exception {
@ -43,7 +61,6 @@ public class CaseController {
command.get("a");
command.del("a");
}
try (RedisPipelineCommandExecutor command = new RedisPipelineCommandExecutor(redisHost, redisPort)) {
command.pipelineExecute();
}
@ -55,7 +72,18 @@ public class CaseController {
try (RedisStreamCommandExecutor executor = new RedisStreamCommandExecutor(redisHost, redisPort)) {
executor.exec();
}
try (ShardingExecutor shardingExecutor = new ShardingExecutor(
Arrays.asList(new HostAndPort(redisHost, redisPort), new HostAndPort(redisHost, redisPort)))) {
shardingExecutor.exec();
}
try (ClusterExecutor clusterExecutor = new ClusterExecutor(new HashSet<>(
Arrays.asList(
new HostAndPort(redisClusterM1Host, redisClusterM1Port),
new HostAndPort(redisClusterM2Host, redisClusterM2Port),
new HostAndPort(redisClusterM3Host, redisClusterM3Port)
)))) {
clusterExecutor.exec();
}
return SUCCESS;
}

View File

@ -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 org.apache.skywalking.apm.testcase.jedis.controller;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class ClusterExecutor implements AutoCloseable {
private final JedisCluster jedisCluster;
public ClusterExecutor(Set<HostAndPort> jedisClusterNodes) {
this.jedisCluster = new JedisCluster(jedisClusterNodes);
}
public void exec() {
jedisCluster.set("x", "1");
jedisCluster.get("x");
jedisCluster.del("x");
}
public void close() {
this.jedisCluster.close();
}
}

View File

@ -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 org.apache.skywalking.apm.testcase.jedis.controller;
import java.util.List;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisSharding;
public class ShardingExecutor implements AutoCloseable {
private JedisSharding jedisSharding;
public ShardingExecutor(List<HostAndPort> hostAndPorts) {
this.jedisSharding = new JedisSharding(hostAndPorts);
}
public void exec() {
jedisSharding.set("x", "1");
jedisSharding.get("x");
jedisSharding.del("x");
}
public void close() {
jedisSharding.close();
}
}

View File

@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
4.4.6
4.3.2
4.2.3
4.1.1
4.0.1
4.0.1