Kubernetes üzerinde çalışan Spring Boot’da Hazelcast

In: Genel


Halbuki Kubernet’ler uygulama yürütmenin hedef ortamıdır, burada gerekli hizmetleri veya dağıtımı en uygun şekilde nasıl bildireceğinizi bulamayacaksınız. Bazı temel Kubernetes yapılandırmaları yalnızca tanıtım amacıyla yeterlidir. Yine de, yapılandırmaları bir başlangıç ​​noktası olarak kullanabilir ve bunları aşağıdakilerin yardımıyla geliştirebilirsiniz. Kubernetes Belgeleri.

Teması BaharÖnbelleğe Alma da tam olarak kapsanmamıştır. Bu nedenle, Önbellek Soyutlamaları ile ilgileniyorsanız, lütfen bkz. Spring Framework belgelerinin ilgili kısmı.

Ne öğreneceksin

Makalenin ana odak noktası, nasıl inşa edileceğini göstermektir. Bahar Botu gerekli bileşenler ve konfigürasyonlar ile uygulama:

  • birlikte çalışmak Yay Verileri JPA dayalı hazırda bekletme
  • kullanmak Hazelcast IMDG (bellek içi veri ızgarası) gömülü modda
  • üzerinde bir uygulama dağıtmak için Kubernet’ler küme

Neye ihtiyacın var

Kılavuzun kodu şu adreste bulunabilir: Hazelcast üzerinde önbelleğe alma ile Kubernetes üzerinde Spring Data JPA uygulaması. Uygulama oluşturuldu ve çalıştırıldı Microsoft pencerelerancak bazı eğik çizgilerden sonra diğer platformlarda da çalışacağına inanıyorum.

Uygulama Yapısı

Her şeyden önce, uygulama veritabanı ile JPA soyutlaması aracılığıyla çalışmalıdır. İkinci seviye önbelleği tanıtacağımız için, bu şu anlama geliyor: hazırda bekletme ORM çerçevesi olarak kullanılır. Biraz zaman ayırmak için kullanıma hazır bir kod seçtim. Baharkılavuzu MySQL ile verilere erişme. Basit bir akış uygular denetleyici-depo ile birlikte MySQL depolama olarak. Orijinal kod, güncellenmiş sürümleri gibi küçük değişiklikler dışında neredeyse aynıdır. Bahar ve MySQL JDBC konektörü pom.xml ve paketlerin yeniden düzenlenmesi.

Ayrıca, depoya ve denetleyiciye birkaç yöntem ekledim. Bu yöntemler daha sonra önbelleğe almanın sonuçlarını göstermede yardımcı olacaktır.

    @Query(value = "SELECT name FROM user WHERE email = :email", nativeQuery = true)
    Optional<String> findNameByEmail(String email);

    @GetMapping(path = "{id}")
    public @ResponseBody ResponseEntity<User> getUser(@PathVariable Integer id) {
        return userRepository.findById(id)
                .map(user -> ResponseEntity.ok().body(user))
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

Genel olarak uygulama, kılavuzda açıklanan işlevlerin aynısını sağlar. MySQL ile verilere erişme. Yeni uç nokta /users/{id} tanımlayıcılarına göre kullanıcı bilgilerini döndüren ve /users/email/{email} kullanıcıların adını e-postalarıyla döndürür.

Hazelcast ile Yaylı Bot

Bahar Çerçevesi çok sayıda önbelleğe alma platformunu ve kitaplığı destekler. Bahar Botu bunları bir uygulama yapılandırmasında kullanmayı kolaylaştırır. Yani, Bahar Botu sınıf yolunda önbelleğe alma sağlayıcılarını bulur ve bunları varsayılan ayarları kullanarak otomatik olarak yapılandırır. Görmek Bahar Botu‘nin otomatik yapılandırma süreciyle ilgili belgeleri Hazelcast Önbellek Sağlayıcı yapılandırması.

kullanacağımız gibi fındıksonraki özellikleri açıkça ayarlayın:

spring.cache.type=hazelcast
spring.hazelcast.config=classpath:cache.yaml

Ve Ekle fındık uygulamanın bağımlılıklarına:

<dependency>
  <groupId>com.hazelcast</groupId>
  <artifactId>hazelcast-all</artifactId>
  <version>4.2.5</version>
</dependency>

Bununla, Bahar Botu bir fasulye bulur ve enjekte eder HazelcastInstance bir uygulama bağlamına dönüştürün. bu fındık ayarları tarafından yapılandırılacaktır cache.yaml.

Daha sonra, HazelcastInstance diğer fasulyelerde kullanılabilir, yani bizim yapıcımızda kullanılabilir. UserController:

private static final String CACHED_NAMES = "nameByEmail";
private UserRepository userRepository;
private ConcurrentMap<String, String> nameByEmailMap;

public UserController(UserRepository userRepository, HazelcastInstance hazelcastInstance) {
  this.userRepository = userRepository;
  nameByEmailMap = hazelcastInstance.getMap(CACHED_NAMES);
}

Yukarıdaki parçada kullandığımız Hazelcast Dağıtılmış Haritasıolarak sunulan ve kodda kullanılan , ConcurrentMap. Bu, basit haritada olduğu gibi önbelleğe alınmış verilerle çalışmak için basit ve esnek bir yol sağlar. Önbelleğe alınmış verileri küme boyunca dağıtmak için tüm ağır işler fındık perde arkasında gerçekleştirir. Bu nedenle, önbelleğin harita olarak kullanımı geliştiriciler için tamamen şeffaftır.

Hazırda Bekletme İkinci Düzey Önbellek

Ardından, ikinci düzey (L2) önbelleği etkinleştireceğiz. hazırda bekletme. Bizim uygulamada bu, özellikler ayarlanarak yapılır:

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastCacheRegionFactory
spring.jpa.properties.hibernate.cache.hazelcast.instance_name=users-app
spring.jpa.properties.hibernate.cache.hazelcast.shutdown_on_session_factory_close=false

Burada, genel bir ikinci seviye önbelleğin yanı sıra Sorgu önbelleğini de etkinleştiririz. Gömülü kullandığımız için fındık dağıtılmış bir ortamda kullanılacak olan fabrika sınıfı com.hazelcast.hibernate.HazelcastCacheRegionFactory. için özelliklerin ve ayarların ayrıntılı bir açıklaması hazırda bekletme önbelleğe alma ve fındık ikinci seviye önbellek için uygulama, ilgili belgelerde bulunabilir Hazırda Önbelleğe Alma ve Hazırda Bekletme İkinci Düzey Önbellek.

kullanarak uygulamayı yapmak için fındık ikinci seviye önbellek olarak, bağımlılığı pom.xml’e ekliyoruz:

<dependency>
  <groupId>com.hazelcast</groupId>
  <artifactId>hazelcast-hibernate53</artifactId>
  <version>2.2.1</version>
</dependency>

Birkaç dakikaya dikkat edeyim. Hazırda Beklet varlıkları için ikinci düzey önbellek varsayılan olarak kullanılmaz, bu nedenle hangi varlıkların önbelleğe alınmasını istediğinizi açıkça tanımlamanız gerekir. Uygulamamızda, User varlık şöyle:

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.Cacheable;
import javax.persistence.Entity;

@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Entity
public class User {
  // skipped
}

O zamanlar, hazırda bekletme işlem akışına ek yük getirdiği ve çoğu durumda genellikle fazla fayda sağlamadığı için Sorgu önbelleğini kullanmama konusunda uyarır. İşte belgelerden alıntı:

Sorgu sonuçlarının önbelleğe alınması, uygulamanızın normal işlem işlemesi açısından bazı ek yükler getirir. Örneğin, bir sorgunun sonuçlarını bir KişiHazırda Bekletme, bu sonuçların ne zaman geçersiz kılınması gerektiğini takip etmelidir, çünkü değişiklikler herhangi birine karşı taahhüt edilmiştir. Kişi varlık.

Bu, çoğu uygulamanın sorgu sonuçlarını önbelleğe almaktan hiçbir fayda sağlamadığı gerçeğiyle birleştiğinde, Hazırda Bekletme’nin varsayılan olarak sorgu sonuçlarının önbelleğe alınmasını devre dışı bırakmasına neden olur.

Uygulamamızda yalnızca tanıtım amaçlı olsa da, Sorgu önbelleği etkindir ve UserRepository geçersiz kılar findAll() sorgunun sonuçlarını önbelleğe almanın bir sonraki yolu:

import org.springframework.data.jpa.repository.QueryHints;
import javax.persistence.QueryHint;

import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
import static org.hibernate.jpa.QueryHints.HINT_CACHE_REGION;

// some code is skipped

@QueryHints({
  @QueryHint(name = HINT_CACHEABLE, value = "true"),
  @QueryHint(name = HINT_CACHE_REGION, value = "query-cache-users")
})
@Override
Iterable<User> findAll();

Son olarak, kullanmak mümkündür fındık saf bir önbelleğe alma çerçevesi olarak ayrı olarak hazırda bekletme L2 önbellek desteği. Yani, varsayılan olarak, HazelcastCacheRegionFactory yeni bir örneğini oluşturur fındık eğer mülk hibernate.cache.hazelcast.instance_name mevcut bir örneğe ayarlanmadı. Aynısını tekrar kullanmak için puslu hava tarafından oluşturulan örnek Bahar, özelliği şu şekilde kurduk:

spring.jpa.properties.hibernate.cache.hazelcast.instance_name=users-app

Örneğin adı, içinde tanımlananla aynı olmalıdır. fındık yapılandırma dosyası cache.yaml:

hazelcast:
  instance-name: users-app

Bu, farklı oluşumların oluşmasını önleyecektir. fındık uygulamadaki örnekler. Yani, hazırda bekletme L2 önbelleği, aynı yapılandırma ile kurulacak cache.yaml.

Hazelcast’i Kubernetes’te Dağıtma

fındık küme üyeleri için farklı otomatik keşif araçları sağlar. Örneğin, yerel (geliştirme) ortamı için, UDP üzerinden çok noktaya yayın mekanizması üyelerin birbirlerini bulmasını sağlar. Bu nedenle, uygulamanın birkaç örneğini yerel olarak çalıştırmak ve fındık çok noktaya yayın otomatik keşif kullanarak bir küme oluşturabilecektir. Bu keşif türü aşağıdaki şekilde etkinleştirilir:

hazelcast:
  network:
    join:
      multicast:
        enabled: true

Üretim ortamları için UDP kullanımı en iyi seçim değildir. Yani, diğerleri arasında, fındık çok noktaya yayın olmadan Kubernetes ortamında dağıtılan kümeleri destekler. Ayrıntılı bilgi için aşağıdaki belgelere bakın: Kubernetes’i Yapılandırma. Kubernetes’te keşfi etkinleştirmek için özellikleri aşağıdaki gibi ayarlayın:

hazelcast:
  instance-name: users-app
  cluster-name: users-app
  network:
    join:
      multicast:
        enabled: false
      kubernetes:
        enabled: true
        service-name: hazelcast

Bu, çok noktaya yayını devre dışı bırakır, Kubernet’ler keşif ve hizmetin adını tanımlar hazelcast, aracılığıyla küme üyelerini aramak için kullanılacak Kubernet’ler API. Ardından, bir sonraki olarak bildirilebilecek bu hizmeti oluşturmamız gerekiyor (ayrıca bkz. k8s/app-hazelcast-service.yaml):

apiVersion: v1
kind: Service
metadata:
  name: hazelcast
  labels:
    app: hazelcast
spec:
  ports:
    - port: 5701
      protocol: TCP
  selector:
    app: app-users
  type: ClusterIP

Buradaki kilit nokta, aynı adı tanımlamaktır, hazelcast tarafından kullanılan hizmetin fındık yapılandırma.

İzin vermek fındık içindeki hizmeti kullanmak için Kubernet’ler keşif için ayrıca belirli izinler vermemiz gerekiyor. için bir RBAC yapılandırması örneği default içinde bulabileceğiniz ad alanı fındık belgeler. Kodda bulabileceğiniz aynı YAML dosyası, bkz. k8sapp-hazelcast-rbac.yaml.

Hizmeti oluşturmak ve büyük rollere geçmek için aşağıdaki komutları çalıştırın:

kubectl apply -f k8sapp-hazelcast-service.yaml
kubectl apply -f k8sapp-hazelcast-rbac.yaml

Ardından, uygulamayı oluşturun ve bundan sonra bir Liman işçisi yerel dosyanızda saklanacak olan görüntü Liman işçisi depo:

mvn clean verify
docker build -f .dockerDockerfile -t rapp/appusers:1.0 .

Bundan sonra, komutu çalıştırarak görüntünün kullanılabilirliğini kontrol edebilirsiniz. docker image lsbunun gibi bir şey döndürmesi gerekir:

REPOSITORY              TAG                    IMAGE ID       CREATED         SIZE
rapp/appusers           1.0                    9c92dfd38bbf   24 hours ago    419MB

Bu, resmi kullanabileceğiniz anlamına gelir. rapp/appusers:1.0 Kubernetes kümesine dağıtmak için. Bunu yapmak için, uygulamalarla birlikte üç bölmeyi dağıtacak ve bölmeler için bir yük dengeleyici oluşturacak olan sonraki komutları çalıştırın:

kubectl apply -f k8sapp-k8s-deployment.yaml
kubectl apply -f k8sapp-k8s-service.yaml

Çalıştırarak kontrol edebileceğiniz dağıtımın sonucu kubectl get podsaşağıdakine benzer uygulama bölmelerinin durumunu göstermelidir:

NAME                            READY   STATUS    RESTARTS   AGE
app-users-55d9b89d86-gstwz      1/1     Running   0          23h
app-users-55d9b89d86-l67dx      1/1     Running   0          23h
app-users-55d9b89d86-l766r      1/1     Running   0          23h

Bu, tüm bölmelerin oluşturulduğu, hazır olduğu ve çalıştığı anlamına gelir. Ayrıca, çalıştırarak herhangi bir bölmenin günlüklerini kontrol edebilirsiniz. kubectl logs <name-of-pod>. Günlükler, başlatma hakkında olağan bilgileri içerecektir. Bahar Botu uygulama (bağlam oluşturma, erkek kedi koşma, hazırda bekletme somutlaştırma vb.). Bunun dışında etkinliklerini de görebilirsiniz. fındık: hangi keşif mekanizmasının aktif olduğu, keşif sürecinin ve kümenin inşasının nasıl yapıldığı. Son olarak, sonucunu görebilirsiniz fındık buna benzer küme yapısı:

Members {size:3, ver:3} [
        Member [172.17.0.4]:5701 - 8d7d80e4-d0e2-4bd6-8116-ab3a7b494a3f
        Member [172.17.0.5]:5701 - 9aa6f3f8-7da7-4037-8e36-761d8432ceea
        Member [172.17.0.6]:5701 - b21112b7-35a7-49fb-ad06-0f921b9823be this
]

Böylece, üç üyeli önbellek kümesi oluşturulur, yani üç bölmenin tümü bulunur ve kümeye eklenir.

Test yapmak

Kubernetes, bölmeleri kendi IP aralığına dağıttığından ve beyan edilen bağlantı noktalarında, farklı harici bağlantılarla eşlenen hizmetler oluşturduğundan, ikisinden birini belirlemeniz gerekir. Minikube‘s IP ve harici bağlantı noktaları veya çalıştırmak için Minikube dahili IP’lerin ve bağlantı noktalarının kullanılmasına izin veren bir tünel modunda. Almak Minikube‘nin IP’si ve uygulama bağlantı noktası, aşağıdaki komutları çalıştırın:

> minikube ip
172.20.164.53
> kubectl get service app-users
NAME        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
app-users   LoadBalancer   10.104.184.147   <pending>     8080:31434/TCP   24h

Böylece başvuru.

Uygulamaya erişmenin başka bir yolu da çalıştırmaktır. minikube tunnel ayrı bir konsolda komut. Ardından, uygulama hizmetine hangi harici IP’nin verildiğini kontrol edin:

> kubectl get service app-users
NAME        TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
app-users   LoadBalancer   10.104.184.147   10.104.184.147   8080:31434/TCP   24h

Bu, açabileceğiniz anlamına gelir. başvuru.

Bu yaklaşımlardan herhangi birini kullanarak, içinde bildirilen uç noktaları test edebilirsiniz. UserController kılavuzda önerildiği şekilde MySQL ile verilere erişme. Ek olarak, oluşturulan iki uç nokta vardır /users/{id} ve /users/email/{email} varlıkların nasıl önbelleğe alındığını ve nasıl yapıldığını kontrol etmek için fındık harita çalışır.

İlk uç nokta, tanımlayıcılarına göre kullanıcılar hakkında bilgi verir. Uygulama özellikleri ayarlandığında spring.jpa.show-sql=truegünlükler tarafından oluşturulan SQL isteklerini içerecektir. hazırda bekletme. Etkinleştirilmiş L2 önbelleğiyle, aynı kullanıcı için tekrarlanan istekler, istekleri veritabanına kaydetmez (nedeni, time-to-live-seconds: 300).

Eklenen ikinci uç nokta, fındık harita yapısı. Uç nokta, veritabanına özel (önbelleğe alınmamış) bir isteği tetiklediğinden, her SQL isteği günlüğe kaydedilebilirdi.

@Query(value = "SELECT name FROM user WHERE email = :email", nativeQuery = true)
Optional<String> findNameByEmail(String email);

Ancak isteğin sonuçları şurada saklanır: fındık veritabanından veri alındıktan sonra harita. Bu nedenle, harita belirli bir e-posta ile boş olmayan bir değer döndürürse, veritabanına ek bir istek gerçekleştirilmez:

private Optional<String> getFromCache(String email) {
  return Optional.ofNullable(nameByEmailMap.computeIfAbsent(email,
              (e) -> userRepository.findNameByEmail(e).orElse(null)));
}

dipnot

Önsözde belirtildiği gibi, bu kılavuz bahsedilen teknolojiler ve araçlar için kesin bir eğitim değildir. İşte iyileştirmeler için bazı öneriler.

“Kutunun dışında” kullanmak mümkündür BaharBizim durumumuzda önbelleğe alma desteği, HazelcastInstance tarafından keşfedilir Bahar ve içine sarılır CacheManager. Bu, kullanılmasına izin verir Bahar‘s @EnableCaching ve @Cacheable ek açıklamalar.

bizim basitleştirilmiş Kubernet’ler yapılandırmalar gibi hizmet türlerini değiştirmek mümkündür. NodePort, içine clusterIPBu, kümedeki uygulamaları çalıştırmamıza ve hizmetleri adlarına göre keşfetmemize izin verebilir. Bu nedenle, sabit kodlanmış IP’lerle gezinmeyi önlemeye yardımcı olabilir. Ek olarak, kullanmaktan kaçınmanız şiddetle tavsiye edilir. default ad alanı. Bu nedenle, uygulamada özel bir ad alanı kullanmayı düşünün ve fındık yapılandırma.

Nihayet, sırlarınızı asla kodda saklamayın. Kodumuzda, veritabanı kimlik bilgileri kodlanır ve yalnızca gösterim ve basitlik için doğrudan YAML yapılandırma dosyalarına yazılır. Bunu uygulamalarınızda tekrarlamayınız. İyi benimsenen uygulama, dağıtım sırasında CI/CD ardışık düzenleri tarafından alınan/değiştirilen ortam değişkenlerinde veya üçüncü taraf kasalarında gizli dizileri depolamaktır.

Bir cevap yazın

Ready to Grow Your Business?

We Serve our Clients’ Best Interests with the Best Marketing Solutions. Find out More

How Can We Help You?

Need to bounce off ideas for an upcoming project or digital campaign? Looking to transform your business with the implementation of full potential digital marketing?

For any career inquiries, please visit our careers page here.
[contact-form-7 404 "Bulunamadı"]