Last active
October 15, 2023 08:39
Spring Boot MVC — Lettuce Command Latency Event Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
myapp: | |
redis: | |
lettuce: | |
host: host | |
port: port | |
username: username | |
password: password | |
ssl: | |
enabled: false | |
connection-pool: | |
min-idle: 0 | |
max-idle: 500 | |
max-total: 500 | |
timeout: | |
idle-timeout: 10 | |
connection-timeout: 300 | |
wait-timeout: 500 | |
command-timeout: 500 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugins { | |
java | |
id("org.springframework.boot") version "3.1.4" | |
id("io.spring.dependency-management") version "1.1.3" | |
} | |
group = "com.myapp" | |
version = "0.0.1-SNAPSHOT" | |
java { | |
sourceCompatibility = JavaVersion.VERSION_17 | |
} | |
configurations { | |
compileOnly { | |
extendsFrom(configurations.annotationProcessor.get()) | |
} | |
} | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
implementation("org.springframework.boot:spring-boot-starter-actuator") | |
implementation("org.springframework.boot:spring-boot-starter-web") | |
implementation("org.springframework.boot:spring-boot-starter-validation") | |
implementation("org.apache.commons:commons-lang3") | |
implementation("org.apache.commons:commons-pool2") | |
implementation("io.micrometer:micrometer-tracing-bridge-brave") | |
implementation("io.lettuce:lettuce-core") | |
implementation("redis.clients:jedis") | |
implementation("io.micrometer:micrometer-core") | |
compileOnly("org.projectlombok:lombok") | |
annotationProcessor("org.projectlombok:lombok") | |
testImplementation("org.springframework.boot:spring-boot-starter-test") | |
} | |
tasks.withType<Test> { | |
useJUnitPlatform() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.myproject.redis.controller; | |
import io.lettuce.core.RedisClient; | |
import lombok.RequiredArgsConstructor; | |
import lombok.SneakyThrows; | |
import lombok.extern.log4j.Log4j2; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestParam; | |
import org.springframework.web.bind.annotation.RestController; | |
import java.util.Set; | |
@Log4j2 | |
@RestController | |
@RequestMapping("/redis/v1") | |
@RequiredArgsConstructor | |
public class Controller { | |
private final RedisClient redisClient; | |
@SneakyThrows | |
@GetMapping("/lettuce") | |
public ResponseEntity<Set<String>> getLettuceSingle(@RequestParam("key") String key) { | |
redisClient.getResources() | |
.eventBus() | |
.get() | |
.subscribe(event -> { | |
log.info("Log Event: {}", event); | |
}); | |
return ResponseEntity.ofNullable(redisClient.connect().sync().smembers(key)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.myproject.redis.configuration; | |
import com.myproject.redis.property.LettuceClientProperty; | |
import io.lettuce.core.RedisClient; | |
import io.lettuce.core.RedisURI; | |
import io.lettuce.core.SslVerifyMode; | |
import io.lettuce.core.api.StatefulRedisConnection; | |
import io.lettuce.core.api.sync.RedisCommands; | |
import io.lettuce.core.event.DefaultEventPublisherOptions; | |
import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; | |
import io.lettuce.core.metrics.MicrometerOptions; | |
import io.lettuce.core.resource.DefaultClientResources; | |
import io.lettuce.core.support.ConnectionPoolSupport; | |
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; | |
import lombok.RequiredArgsConstructor; | |
import lombok.extern.log4j.Log4j2; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.commons.pool2.impl.GenericObjectPool; | |
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; | |
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import java.time.Duration; | |
@Log4j2 | |
@Configuration | |
@RequiredArgsConstructor | |
@EnableConfigurationProperties(LettuceClientProperty.class) | |
public class LettuceClientConfiguration { | |
private final LettuceClientProperty lettuceClientProperty; | |
@Bean | |
public RedisClient redisClient() { | |
var builder = RedisURI.builder() | |
.withHost(lettuceClientProperty.host()) | |
.withPort(lettuceClientProperty.port()) | |
.withSsl(lettuceClientProperty.ssl().enabled()); | |
if (StringUtils.isNotBlank(lettuceClientProperty.username()) || StringUtils.isNotBlank(lettuceClientProperty.password())) { | |
builder.withAuthentication(lettuceClientProperty.username(), lettuceClientProperty.password()); | |
} | |
if (lettuceClientProperty.ssl().enabled()) { | |
builder.withVerifyPeer(SslVerifyMode.NONE); | |
} | |
var micrometerOptions = MicrometerOptions.builder() | |
.enable() | |
.histogram(true) | |
.localDistinction(true) | |
.minLatency(Duration.ofMillis(1)) | |
.maxLatency(Duration.ofDays(1)) | |
.build(); | |
var commandLatencyPublisherOptions = DefaultEventPublisherOptions.builder() | |
.eventEmitInterval(Duration.ofSeconds(1)) | |
.build(); | |
var resources = DefaultClientResources.builder() | |
.commandLatencyRecorder( | |
new MicrometerCommandLatencyRecorder( | |
new SimpleMeterRegistry(), | |
micrometerOptions | |
) | |
) | |
.commandLatencyPublisherOptions(commandLatencyPublisherOptions) | |
.build(); | |
return RedisClient.create(resources, builder.build()); | |
} | |
@Bean | |
public StatefulRedisConnection<String, String> redisConnection(RedisClient redisClient) { | |
return redisClient.connect(); | |
} | |
@Bean | |
public RedisCommands<String, String> redisCommands(StatefulRedisConnection<String, String> redisConnection) { | |
return redisConnection.sync(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment