日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

容器化Spring Data Cassandra应用程序

發(fā)布時(shí)間:2023/12/3 javascript 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 容器化Spring Data Cassandra应用程序 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我正在繼續(xù)學(xué)習(xí)Docker的旅程。 在這一點(diǎn)上,我仍然保持簡單。 這次,我將解決將Spring和Cassandra應(yīng)用程序轉(zhuǎn)換為使用容器而不是在主機(jī)上本地運(yùn)行的問題。 更準(zhǔn)確地說,使用Spring Data Cassandra整理應(yīng)用程序。

我希望我前幾天看過進(jìn)行此更改。 我在Cassandra上寫了很多文章,每次我必須cd到正確的目錄或有啟動(dòng)它的快捷方式時(shí)。 我想這沒什么大不了的,但是還涉及其他一些事情。 例如,刪除和重新創(chuàng)建鍵空間,以便可以從頭開始測試我的應(yīng)用程序。 現(xiàn)在,我只刪除容器并重新啟動(dòng)它。 無論如何對(duì)我來說,這是有幫助的!

這篇文章與我以前的文章《 使用Docker將現(xiàn)有應(yīng)用程序推送到容器》稍有不同。 取而代之的是,我將更多地關(guān)注于應(yīng)用程序端,并刪除僅使用Docker的中間步驟,而直接跳入Docker Compose。

集裝箱集裝箱

我認(rèn)為最好從項(xiàng)目的容器端開始,因?yàn)閼?yīng)用程序取決于Cassandra容器的配置。

我們走吧!

FROM openjdk:10-jre-slim LABEL maintainer="Dan Newton" ARG JAR_FILE ADD target/${JAR_FILE} app.jar ENTRYPOINT ["java", "-jar", "/app.jar"]

這里沒有太多的事情。 這個(gè)Dockerfile構(gòu)建了Spring應(yīng)用程序映像,稍后將其放入容器中。

接下來是docker-compose文件。 這將同時(shí)構(gòu)建Spring應(yīng)用程序和Cassandra容器:

version: '3' services:app:build:context: .args:JAR_FILE: /spring-data-cassandra-docker-1.0.0.jarrestart: alwayscassandra: image: "cassandra"

同樣,這里沒有太多。 app容器使用Dockerfile定義的Dockerfile構(gòu)建Spring應(yīng)用程序。 cassandra容器而是依賴于現(xiàn)有的映像,適當(dāng)?shù)孛麨閏assandra 。

突出的一件事是,將restart屬性設(shè)置為always 。 這是我的懶惰嘗試,試圖超越Cassandra啟動(dòng)所需的時(shí)間,而且所有容器都以docker-compose開頭的事實(shí)是同時(shí)啟動(dòng)的。 這導(dǎo)致應(yīng)用程序在未準(zhǔn)備就緒的情況下嘗試連接到Cassandra的情況。 不幸的是,這導(dǎo)致應(yīng)用程序崩潰。 我希望它對(duì)內(nèi)置的初始連接將有一些重試功能……但事實(shí)并非如此。

當(dāng)我們遍歷代碼時(shí),我們將看到如何以編程方式處理初始Cassandra連接,而不是依賴于應(yīng)用程序死掉并重新啟動(dòng)多次。 您仍然會(huì)看到我處理連接的版本…我并不是真正的解決方案擁護(hù)者,但是我嘗試的所有其他操作都使我更加痛苦。

一點(diǎn)代碼

我說過這篇文章將把重點(diǎn)更多地放在應(yīng)用程序代碼上,但是我們不會(huì)深入研究我在該應(yīng)用程序中放置的所有內(nèi)容以及如何使用Cassandra。 有關(guān)此類信息,您可以查看我的較舊文章,這些文章將在最后鏈接。 不過,我們要做的是檢查配置代碼,該代碼創(chuàng)建連接到Cassandra的bean。

首先,讓我們看一下設(shè)置Cassandra集群的ClusterConfig :

@Configuration public class ClusterConfig extends AbstractClusterConfiguration {private final String keyspace;private final String hosts;ClusterConfig(@Value("${spring.data.cassandra.keyspace-name}") String keyspace,@Value("${spring.data.cassandra.contact-points}") String hosts) {this.keyspace = keyspace;this.hosts = hosts;}@Bean@Overridepublic CassandraClusterFactoryBean cluster() {RetryingCassandraClusterFactoryBean bean = new RetryingCassandraClusterFactoryBean();bean.setAddressTranslator(getAddressTranslator());bean.setAuthProvider(getAuthProvider());bean.setClusterBuilderConfigurer(getClusterBuilderConfigurer());bean.setClusterName(getClusterName());bean.setCompressionType(getCompressionType());bean.setContactPoints(getContactPoints());bean.setLoadBalancingPolicy(getLoadBalancingPolicy());bean.setMaxSchemaAgreementWaitSeconds(getMaxSchemaAgreementWaitSeconds());bean.setMetricsEnabled(getMetricsEnabled());bean.setNettyOptions(getNettyOptions());bean.setPoolingOptions(getPoolingOptions());bean.setPort(getPort());bean.setProtocolVersion(getProtocolVersion());bean.setQueryOptions(getQueryOptions());bean.setReconnectionPolicy(getReconnectionPolicy());bean.setRetryPolicy(getRetryPolicy());bean.setSpeculativeExecutionPolicy(getSpeculativeExecutionPolicy());bean.setSocketOptions(getSocketOptions());bean.setTimestampGenerator(getTimestampGenerator());bean.setKeyspaceCreations(getKeyspaceCreations());bean.setKeyspaceDrops(getKeyspaceDrops());bean.setStartupScripts(getStartupScripts());bean.setShutdownScripts(getShutdownScripts());return bean;}@Overrideprotected List getKeyspaceCreations() {final CreateKeyspaceSpecification specification =CreateKeyspaceSpecification.createKeyspace(keyspace).ifNotExists().with(KeyspaceOption.DURABLE_WRITES, true).withSimpleReplication();return List.of(specification);}@Overrideprotected String getContactPoints() {return hosts;} }

那里并沒有太多,但是如果Spring重試與Cassandra的初始連接,則將更少。 無論如何,讓我們將這一部分留出幾分鐘,集中討論本課程中的其他要點(diǎn)。

我創(chuàng)建ClusterConfig的最初原因是創(chuàng)建應(yīng)用程序?qū)⑹褂玫拿荑€空間。 為此, getKeyspaceCreations被覆蓋。 當(dāng)應(yīng)用程序連接時(shí),它將執(zhí)行此方法中定義的查詢以創(chuàng)建鍵空間。

如果不需要這樣做,并且以其他某種方式創(chuàng)建了鍵空間,例如,作為創(chuàng)建Cassandra容器的一部分執(zhí)行的腳本,則可以依靠Spring Boot的自動(dòng)配置。 實(shí)際上,這允許整個(gè)應(yīng)用程序由application.properties定義的屬性進(jìn)行配置,而僅此而已。 las,這本來不是。

由于我們定義了AbstractClusterConfiguration ,Spring Boot將在此區(qū)域中禁用其配置。 因此,我們需要通過重寫getContactPoints方法來手動(dòng)定義contactPoints (我將其命名為變量hosts )。 最初,這僅在application.properties定義。 我意識(shí)到一旦開始出現(xiàn)以下錯(cuò)誤,我需要進(jìn)行此更改:

All host(s) tried for query failed (tried: localhost/127.0.0.1:9042 (com.datastax.driver.core.exceptions.TransportException: [localhost/127.0.0.1:9042] Cannot connect))

在創(chuàng)建ClusterConfig之前,地址為cassandra而不是localhost 。

無需為集群配置其他任何屬性,因?yàn)樵谶@種情況下,Spring的默認(rèn)值就足夠了。

在這一點(diǎn)上,我已經(jīng)提到太多application.properties了,我應(yīng)該向您展示其中的內(nèi)容。

spring.data.cassandra.keyspace-name=mykeyspace spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS spring.data.cassandra.contact-points=cassandra

keyspace-name和contact-points已經(jīng)彈出,因?yàn)樗鼈兣c配置集群有關(guān)。 根據(jù)項(xiàng)目中的實(shí)體創(chuàng)建表需要schema-action 。 我們不需要在這里做任何其他事情,因?yàn)樽詣?dòng)配置仍在該領(lǐng)域中工作。

contact-points值設(shè)置為cassandra的事實(shí)非常重要。 該域名源自提供給容器的名稱,在本例中為cassandra 。 因此,既可以使用cassandra也可以使用容器的實(shí)際IP。 域名絕對(duì)容易,因?yàn)椴渴鹬g始終是靜態(tài)的。 只是為了驗(yàn)證這一理論,您可以將cassandra容器的名稱更改為所需的名稱,只要您在application.properties中也將其更改,它仍然可以連接。

返回到ClusterConfig代碼。 更確切地說,是cluster bean。 我再次粘貼了下面的代碼,以便于查看:

@Configuration public class ClusterConfig extends AbstractClusterConfiguration {// other stuff@Bean@Overridepublic CassandraClusterFactoryBean cluster() {RetryingCassandraClusterFactoryBean bean = new RetryingCassandraClusterFactoryBean();bean.setAddressTranslator(getAddressTranslator());bean.setAuthProvider(getAuthProvider());bean.setClusterBuilderConfigurer(getClusterBuilderConfigurer());bean.setClusterName(getClusterName());bean.setCompressionType(getCompressionType());bean.setContactPoints(getContactPoints());bean.setLoadBalancingPolicy(getLoadBalancingPolicy());bean.setMaxSchemaAgreementWaitSeconds(getMaxSchemaAgreementWaitSeconds());bean.setMetricsEnabled(getMetricsEnabled());bean.setNettyOptions(getNettyOptions());bean.setPoolingOptions(getPoolingOptions());bean.setPort(getPort());bean.setProtocolVersion(getProtocolVersion());bean.setQueryOptions(getQueryOptions());bean.setReconnectionPolicy(getReconnectionPolicy());bean.setRetryPolicy(getRetryPolicy());bean.setSpeculativeExecutionPolicy(getSpeculativeExecutionPolicy());bean.setSocketOptions(getSocketOptions());bean.setTimestampGenerator(getTimestampGenerator());bean.setKeyspaceCreations(getKeyspaceCreations());bean.setKeyspaceDrops(getKeyspaceDrops());bean.setStartupScripts(getStartupScripts());bean.setShutdownScripts(getShutdownScripts());return bean;}// other stuff }

僅需要此代碼才能允許在初始Cassandra連接上重試。 這很煩人,但是我無法提出另一個(gè)簡單的解決方案。 如果您有更好的選擇,請(qǐng)告訴我!

我所做的實(shí)際上很簡單,但是代碼本身并不是很好。 除了RetryingCassandraClusterFactoryBean (我自己的類)之外, cluster方法是AbstractClusterConfiguration重寫版本的副本。 原始函數(shù)改為使用CassandraClusterFactoryBean (Spring類)。

以下是RetryingCassandraClusterFactoryBean :

public class RetryingCassandraClusterFactoryBean extends CassandraClusterFactoryBean {private static final Logger LOG =LoggerFactory.getLogger(RetryingCassandraClusterFactoryBean.class);@Overridepublic void afterPropertiesSet() throws Exception {connect();}private void connect() throws Exception {try {super.afterPropertiesSet();} catch (TransportException | IllegalArgumentException | NoHostAvailableException e) {LOG.warn(e.getMessage());LOG.warn("Retrying connection in 10 seconds");sleep();connect();}}private void sleep() {try {Thread.sleep(10000);} catch (InterruptedException ignored) {}} }

原始CassandraClusterFactoryBean的afterPropertiesSet方法采用其值,并通過最終委托給Datastax Java驅(qū)動(dòng)程序來創(chuàng)建Cassandra集群的表示形式。 正如我在整個(gè)帖子中提到的。 如果無法建立連接,則將引發(fā)異常,如果未捕獲,將導(dǎo)致應(yīng)用程序終止。 這就是上面代碼的重點(diǎn)。 它將afterPropertiesSet包裝在為可能引發(fā)的異常指定的try-catch塊中。

添加了sleep ,使Cassandra有一些時(shí)間可以真正啟動(dòng)。 上一次嘗試失敗時(shí),嘗試立即重新連接沒有任何意義。

使用此代碼,應(yīng)用程序最終將連接到Cassandra。

在這一點(diǎn)上,我通常會(huì)向您顯示一些毫無意義的日志,以證明該應(yīng)用程序可以正常工作,但是在這種情況下,它實(shí)際上并沒有帶來任何好處。 當(dāng)您說以下命令時(shí),請(qǐng)相信我:

mvn clean install && docker-compose up

然后創(chuàng)建Spring應(yīng)用程序映像,并旋轉(zhuǎn)兩個(gè)容器。

結(jié)論

我們已經(jīng)看過如何將連接到Cassandra數(shù)據(jù)庫的Spring應(yīng)用程序放入容器中。 一個(gè)用于應(yīng)用程序,另一個(gè)用于Cassandra。 應(yīng)用程序映像是從項(xiàng)目的代碼構(gòu)建的,而Cassandra映像是從Docker Hub獲取的。 圖像名稱為cassandra只是為了確保沒有人忘記。 通常,將兩個(gè)容器連接在一起相對(duì)簡單,但是應(yīng)用程序需要進(jìn)行一些調(diào)整,以便在連接到另一個(gè)容器中運(yùn)行的Cassandra時(shí)允許重試。 這使代碼有些丑陋,但是至少可以工作……由于本文中編寫的代碼,現(xiàn)在我有了另一個(gè)不需要在自己的機(jī)器上設(shè)置的應(yīng)用程序。

這篇文章中使用的代碼可以在我的GitHub上找到 。

如果您認(rèn)為這篇文章有幫助,可以在Twitter上@LankyDanDev關(guān)注我,以跟上我的新文章。

鏈接到我的Spring Data Cassandra帖子

  • Spring Data Cassandra入門
  • 使用Spring Data Cassandra分隔鍵空間
  • 使用單個(gè)Spring Data CassandraTemplate的多個(gè)鍵空間
  • 使用Spring Data Cassandra進(jìn)行更復(fù)雜的建模
  • Spring Data Cassandra中的啟動(dòng)和關(guān)閉腳本
  • Spring Data Cassandra的反應(yīng)流
  • Spring Data Cassandra中自動(dòng)配置隨附的管道
  • 使用Datastax Java驅(qū)動(dòng)程序與Cassandra進(jìn)行交互

哇,我沒意識(shí)到我寫了那么多Cassandra帖子。

翻譯自: https://www.javacodegeeks.com/2018/09/spring-data-cassandra-application.html

總結(jié)

以上是生活随笔為你收集整理的容器化Spring Data Cassandra应用程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。