この記事について
Spring BootアプリーケーションをHeroku上に構築し、そこからRedisを利用する方法について書きます。公式のHeroku Redis- Connecting In Javaにも載ってはいるんですが、そのままだと情報不足だと感じたのでちょっと改良しRedisTemplateのBean定義まで含めて載せています。
前提
- HerokuにPush済みのSpring Bootアプリーケーション(2系)があること
Redisのセットアップ
こちらはHerokuの公式通りです。
RedisのAddOnを追加します。
$ heroku addons:create heroku-redis:hobby-dev -a <<APP_NAME>>
追加できるとheroku addons
でheroku-redis
が出てくるようになります。
また、Heroku上ではREDIS_URL
という環境変数に接続情報がセットされています。
$ heroku config | grep redis
REDIS_URL: redis://h:<<PASSWORD>>@<<HOST>>:<<PORT>>
この値は変わることがあるため、直接値をソース上に記載するのではなくSystem.getenv("REDIS_URL")
などとして環境変数のまま扱ってあげる必要があります。
Spring Data Redisの利用
SpringDataRedisを依存関係に追加します。
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
Bean定義
Redisを利用するために以下のBean定義を作成します。
-
JedisPoolConfig
: コネクションプールの設定 -
JedisConnectionFactory
:Jedisベースのコネクションを作成するファクトリ -
RedisTemplate
: Redisへのアクセスを抽象化してくるクラス
@Profile("heroku")
@Configuration
public class RedistConfigHeroku {
@Bean
JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(10);
poolConfig.setMaxIdle(5);
poolConfig.setMinIdle(1);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
return poolConfig;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) throws URISyntaxException {
String envRedisUrl = System.getenv("REDIS_URL");
URI redisUri = new URI(envRedisUrl);
RedisStandaloneConfiguration hostConfig = new RedisStandaloneConfiguration();
hostConfig.setPort(redisUri.getPort());
hostConfig.setHostName(redisUri.getHost());
hostConfig.setPassword(redisUri.getUserInfo().split(":", 2)[1]);
JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
JedisClientConfiguration clientConfig = builder
.usePooling()
.poolConfig(jedisPoolConfig)
.build();
JedisConnectionFactory factory = new JedisConnectionFactory(hostConfig, clientConfig);
return factory;
}
@Bean
public RedisTemplate<String, String> redisTemplate(JedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setHashKeySerializer(redisTemplate.getKeySerializer());
redisTemplate.setHashValueSerializer(redisTemplate.getValueSerializer());
return redisTemplate;
}
利用側の例は以下のようになります。
@Service
public class SomeService {
private final RedisTemplate<String, String> redisTemplate;
// コンストラクタインジェクション
public SomeService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void doSomething() {
// write
redisTemplate.opsForValue().set(key, value);
// read
String value = redisTemplate.opsForValue().get(key);
}
}
Profileの指定
この例ではHeroku用のConfigurationということでheroku
プロファイルを定義し@Profile("heroku")
としています。
このBean定義を読んであげるため、Procfileにも-Dspring.profiles.active=heroku
を追加してあげます。(すでにプロファイルが存在するならそれも含めて)
web: java -jar -Dspring.profiles.active=heroku target/app.jar --server.port=${PORT}