MSEARCH-49 Caching for language configs

MSEARCH-49 Caching for language configs

For distributed caching can be used Hazelcast In-memory caching. It is fast, reliable and scalable solution, that can be used for different clusters - AWS, Kubernetes and etc.

Required dependencies for mod-search project:

</properties> ... <hazelcast.version>4.2</hazelcast.version> ... </properties> </dependencies> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-all</artifactId> <version>${hazelcast.version}</version> </dependency> </dependencies>

Hazelcast cache can be configured using XML, YAML or using Java.

Spring configuration

Configuration class should looks like:

package org.folio.search.configuration; import com.hazelcast.config.ClasspathYamlConfig; import com.hazelcast.config.Config; import com.hazelcast.config.EvictionConfig; import com.hazelcast.config.EvictionPolicy; import com.hazelcast.config.InMemoryFormat; import com.hazelcast.config.MapConfig; import com.hazelcast.config.MaxSizePolicy; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @RequiredArgsConstructor public class CacheProperties { @Bean public Config hazelcastConfig(@Value("${HAZELCAST_CONFIG_TYPE:multicast}") String configType) { return new ClasspathYamlConfig(String.format("hazelcast-%s.yaml", configType)) .addMapConfig(new MapConfig("testHazelcastCache") .setInMemoryFormat(InMemoryFormat.BINARY) .setEvictionConfig(new EvictionConfig() .setEvictionPolicy(EvictionPolicy.LRU) .setMaxSizePolicy(MaxSizePolicy.PER_NODE) .setSize(1000)) .setTimeToLiveSeconds(600)); } }

Common cache settings can be stored in Java configuration, environment specific can be defined using configuration properties in Java or as external YAML configurations in project:

hazelcast-k8s.yaml
hazelcast: instance-name: hazelcast-cache network: join: multicast: enabled: false kubernetes: enabled: true service-name: mod-search namespace: falcon

Which is equal to Java configuration:

config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); config.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) .setProperty("namespace", "falcon") .setProperty("service-name", "mod-search");

 

Kubernetes configuration

Using Kubernetes API requires granting certain permissions. To grant them for 'default' service account in 'default' namespace execute the following command.

https://raw.githubusercontent.com/hazelcast/hazelcast-kubernetes/master/rbac.yaml

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: hazelcast-cluster-role rules: - apiGroups: - "" resources: - endpoints - pods - nodes - services verbs: - get - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: hazelcast-cluster-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: hazelcast-cluster-role subjects: - kind: ServiceAccount name: default namespace: default

Load balancer should allow to pods communicate with each other using port 5071

apiVersion: v1 kind: Service metadata: name: mod-search spec: type: LoadBalancer selector: app: mod-search ports: - name: hazelcast port: 5701 - name: app port: 8081