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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mongodb实验报告_Dropwizard,MongoDB和Gradle实验

發(fā)布時(shí)間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mongodb实验报告_Dropwizard,MongoDB和Gradle实验 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

mongodb實(shí)驗(yàn)報(bào)告

介紹

我使用Dropwizard,MongoDB和Gradle創(chuàng)建了一個(gè)小項(xiàng)目。 它實(shí)際上是作為一個(gè)實(shí)驗(yàn)性的Guava緩存開始的,作為將計(jì)數(shù)器發(fā)送到MongoDB(或任何其他DB)的緩沖區(qū)。 我也想嘗試MondleDB插件的Gradle。 接下來,我想創(chuàng)建某種界面來檢查此框架,因此我決定嘗試使用DropWizard。 這就是這個(gè)項(xiàng)目的創(chuàng)建方式。

本文不是使用任何選定技術(shù)的教程。 這是一個(gè)小展示柜,我做過實(shí)驗(yàn)。 我猜有一些缺陷,也許我沒有使用所有“最佳實(shí)踐”。 但是,我確實(shí)相信,在本文的幫助下,該項(xiàng)目可以成為我使用的各種技術(shù)的良好起點(diǎn)。 我還嘗試顯示一些設(shè)計(jì)選擇,這些選擇有助于實(shí)現(xiàn)SRP,去耦,內(nèi)聚等。

我決定從用例描述及其實(shí)現(xiàn)方式開始。 之后,我將解釋我對(duì)Gradle,MongoDB(和嵌入式)和Dropwizard所做的工作。

在開始之前,這里是源代碼:

  • https://github.com/eyalgo/CountersBuffering

用例:帶緩沖區(qū)的計(jì)數(shù)器

我們對(duì)服務(wù)器有一些輸入請(qǐng)求。 在請(qǐng)求過程中,我們選擇用一些數(shù)據(jù)(由某些邏輯決定)“繪制”它。 有些請(qǐng)求將由Value-1繪制,某些請(qǐng)求將由Value-2繪制,等等。有些將根本不會(huì)繪制。 我們要限制繪畫請(qǐng)求的數(shù)量(每個(gè)繪畫值)。 為了有限制,對(duì)于每個(gè)繪制值,我們知道最大值,但是還需要計(jì)算(每個(gè)繪制值)繪制請(qǐng)求的數(shù)量。 由于系統(tǒng)具有多個(gè)服務(wù)器,因此計(jì)數(shù)器應(yīng)由所有服務(wù)器共享。

延遲至關(guān)重要。 通常,每個(gè)請(qǐng)求處理會(huì)得到4-5毫秒(對(duì)于所有流程。不僅僅是繪畫)。 因此,我們不希望增加計(jì)數(shù)器會(huì)增加延遲。 相反,我們將保留一個(gè)緩沖區(qū),客戶端將向緩沖區(qū)發(fā)送“增加”。 緩沖區(qū)將定期以“批量增量”增加存儲(chǔ)庫。

我知道可以直接使用Hazelcast或Couchbase或其他類似的快速內(nèi)存數(shù)據(jù)庫。 但是對(duì)于我們的用例,那是最好的解決方案。

原理很簡單:

  • 從屬模塊將調(diào)用服務(wù)以增加某個(gè)密鑰的計(jì)數(shù)器
  • 該實(shí)現(xiàn)為每個(gè)鍵保留一個(gè)計(jì)數(shù)器緩沖區(qū)
  • 這是線程安全的
  • 編寫在單獨(dú)的線程中進(jìn)行
  • 每次寫入都會(huì)大量增加

柜臺(tái)高級(jí)設(shè)計(jì)

緩沖

對(duì)于緩沖區(qū),我使用了Google Guava 緩存 。

緩沖結(jié)構(gòu)

創(chuàng)建緩沖區(qū):

private final LoadingCache<Counterable, BufferValue> cache; ...this.cache = CacheBuilder.newBuilder().maximumSize(bufferConfiguration.getMaximumSize()).expireAfterWrite(bufferConfiguration.getExpireAfterWriteInSec(), TimeUnit.SECONDS).expireAfterAccess(bufferConfiguration.getExpireAfterAccessInSec(), TimeUnit.SECONDS).removalListener((notification) -> increaseCounter(notification)).build(new BufferValueCacheLoader()); ...

( 可逆的描述如下)

BufferValueCacheLoader實(shí)現(xiàn)了CacheLoader接口。 當(dāng)我們調(diào)用增加(見下文)時(shí),我們首先通過鍵從緩存中獲取。 如果鍵不存在,則加載器返回值。

BufferValueCacheLoader:

public class BufferValueCacheLoader extends CacheLoader<Counterable, BufferValue> {@Overridepublic BufferValue load(Counterable key) {return new BufferValue();} }

BufferValue包裝一個(gè)AtomicInteger (在某些時(shí)候我需要將其更改為Long)

增加柜臺(tái)

增加計(jì)數(shù)器,如果超過閾值則發(fā)送:

public void increase(Counterable key) {BufferValue meter = cache.getUnchecked(key);int currentValue = meter.increment();if (currentValue > threashold) {if (meter.compareAndSet(currentValue, currentValue - threashold)) {increaseCounter(key, threashold);}} }

當(dāng)增加一個(gè)計(jì)數(shù)器時(shí),我們首先從緩存中獲取當(dāng)前值(在加載程序的幫助下。如上所述)。 compareAndSet將自動(dòng)檢查是否具有相同的值(未被另一個(gè)線程修改)。 如果是這樣,它將更新該值并返回true。 如果成功(返回true),則緩沖區(qū)調(diào)用更新程序。

查看緩沖區(qū)

開發(fā)服務(wù)之后,我想要一種查看緩沖區(qū)的方法。 因此,我實(shí)現(xiàn)了以下方法,該方法由前端層(Dropwizard的資源)使用。 Java 8 Stream和Lambda表達(dá)式的小示例。

獲取所有計(jì)數(shù)器在緩存中:

return ImmutableMap.copyOf(cache.asMap()).entrySet().stream().collect(Collectors.toMap((entry) -> entry.getKey().toString(),(entry) -> entry.getValue().getValue()));

MongoDB

我之所以選擇MongoDB是因?yàn)閮蓚€(gè)原因:

  • 我們的系統(tǒng)中有類似的實(shí)現(xiàn),我們決定在那里也使用MongoDB。
  • 易于與嵌入式服務(wù)器一起使用。
  • 我試圖設(shè)計(jì)系統(tǒng),以便可以選擇其他任何持久性實(shí)現(xiàn)并進(jìn)行更改。

    我使用嗎啡作為MongoDB客戶端層,而不是直接使用Java客戶端。 使用Morphia,您可以創(chuàng)建dao ,它是與MongoDB集合的連接。 您還聲明了一個(gè)簡單的Java Bean(POJO),它表示集合中的文檔。 一旦有了dao,就可以使用相當(dāng)簡單的API以“ Java方式”對(duì)集合進(jìn)行操作。 您可以查詢和其他任何CRUD操作,以及更多。

    我有兩個(gè)操作:增加計(jì)數(shù)器和獲取所有計(jì)數(shù)器。 服務(wù)實(shí)現(xiàn)不擴(kuò)展Morphia的BasicDAO,而是具有一個(gè)繼承它的類。 我使用了組合 (過度繼承),因?yàn)槲蚁M麅煞N服務(wù)都具有更多的行為。

    為了與鍵表示保持一致,并從依賴代碼中隱藏其實(shí)現(xiàn)方式,我使用了一個(gè)接口:可通過單個(gè)方法counterCount()來 抵消 。

    public interface Counterable {String counterKey(); }

    DAO,是服務(wù)內(nèi)部的組成部分:

    final class MongoCountersDao extends BasicDAO<Counter, ObjectId> {MongoCountersDao(Datastore ds) {super(Counter.class, ds);} }

    增加柜臺(tái)

    MongoCountersUpdater擴(kuò)展了實(shí)現(xiàn)CountersUpdater的AbstractCountersUpdater:

    @Override protected void increaseCounter(String key, int value) {Query<Counter> query = dao.createQuery();query.criteria("id").equal(key);UpdateOperations<Counter> ops = dao.getDs().createUpdateOperations(Counter.class).inc("count", value);dao.getDs().update(query, ops, true); }

    嵌入式MongoDB

    為了在持久層上運(yùn)行測試,我想使用內(nèi)存數(shù)據(jù)庫。 有一個(gè)MongoDB插件。 使用此插件,您可以通過僅在運(yùn)行時(shí)創(chuàng)建服務(wù)器來運(yùn)行服務(wù)器,或者在Gradle中的maven / task中作為目標(biāo)運(yùn)行。

    • https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo
    • https://github.com/sourcemuse/GradleMongoPlugin

    Gradle上的嵌入式MongoDB

    稍后我將詳細(xì)介紹Gradle,但這是設(shè)置嵌入式mongo所需的操作。

    dependencies {// More dependencies heretestCompile 'com.sourcemuse.gradle.plugin:gradle-mongo-plugin:0.4.0' }

    設(shè)置屬性

    mongo {// logFilePath: The desired log file path (defaults to 'embedded-mongo.log')logging 'console'mongoVersion 'PRODUCTION'port 12345// storageLocation: The directory location from where embedded Mongo will run, such as /tmp/storage (defaults to a java temp directory) }

    嵌入式MongoDB Gradle任務(wù)

    • startMongoDb只會(huì)啟動(dòng)服務(wù)器。 它將運(yùn)行直到停止它。
    • stopMongoDb將停止它。
    • startManagedMongoDb test ,這兩個(gè)任務(wù)將在測試運(yùn)行之前啟動(dòng)嵌入式服務(wù)器。 jvm完成(測試完成)后,服務(wù)器將關(guān)閉

    盡管我只觸碰到冰山一角,但我開始看到Gradle的力量。 設(shè)置項(xiàng)目甚至都不是那么困難。

    Gradle設(shè)置

    首先,我在eclipse中創(chuàng)建了Gradle項(xiàng)目(安裝插件后)。 我需要設(shè)置依賴項(xiàng)。 很簡單。 就像行家一樣。

    一個(gè)大的JAR輸出

    當(dāng)我想從Maven中的所有庫中創(chuàng)建一個(gè)大jar時(shí),我會(huì)使用shade插件。 我在尋找類似的東西,并發(fā)現(xiàn)gradle-one-jar插入。 https://github.com/rholder/gradle-one-jar我添加了該插件apply plugin: 'gradle-one-jar' 。 在類路徑中添加了一個(gè)jar:

    buildscript {repositories { mavenCentral() }dependencies {classpath 'com.sourcemuse.gradle.plugin:gradle-mongo-plugin:0.4.0'classpath 'com.github.rholder:gradle-one-jar:1.0.4'} }

    并添加了一個(gè)任務(wù):

    mainClassName = 'org.eyalgo.server.dropwizard.CountersBufferApplication' task oneJar(type: OneJar) {mainClass = mainClassNamearchiveName = 'counters.jar'mergeManifestFromJar = true }

    這些是我需要執(zhí)行的必要操作,才能使應(yīng)用程序運(yùn)行。

    Dropwizard

    Dropwizard是一堆庫,可以輕松快速地創(chuàng)建Web服務(wù)器。 它將Jetty用于HTTP,將Jersey用于REST。 它具有其他成熟的庫來創(chuàng)建復(fù)雜的服務(wù)。 它可以用作易于開發(fā)的微服務(wù)。

    正如我在簡介中所解釋的,我不會(huì)介紹Dropwizard的所有功能和/或設(shè)置。 有很多的網(wǎng)站。 我將簡要介紹為使應(yīng)用程序運(yùn)行而執(zhí)行的操作。

    Gradle運(yùn)行任務(wù)

    run { args 'server', './src/main/resources/config/counters.yml' }

    第一個(gè)參數(shù)是服務(wù)器。 第二個(gè)參數(shù)是配置文件的位置。 如果不將Dropwizard作為第一個(gè)參數(shù),則會(huì)收到有關(guān)可能選項(xiàng)的錯(cuò)誤消息。

    positional arguments:{server,check} available commands

    我已經(jīng)在Gradle部分中展示了如何創(chuàng)建一個(gè)jar。

    組態(tài)

    在Dropwizard中,您可以使用擴(kuò)展Configuration的類來設(shè)置應(yīng)用程序。 類中的字段應(yīng)與yml配置文件中的屬性對(duì)齊。

    優(yōu)良作法是根據(jù)屬性的用途/職責(zé)將其分組。 例如,我為mongo參數(shù)創(chuàng)建了一個(gè)組。

    為了使配置類正確讀取子組,您需要?jiǎng)?chuàng)建一個(gè)與組中的屬性對(duì)齊的類。

    然后,在主配置中,將該類添加為成員,并使用批注進(jìn)行標(biāo)記: @JsonProperty 。

    例:

    @JsonProperty("mongo") private MongoServicesFactory servicesFactory = new MongoServicesFactory(); @JsonProperty("buffer") private BufferConfiguration bufferConfiguration = new BufferConfiguration();

    示例:更改端口

    這是配置文件的一部分,用于設(shè)置應(yīng)用程序的端口。

    server:adminMinThreads: 1adminMaxThreads: 64applicationConnectors:- type: httpport: 9090adminConnectors:- type: httpport: 9091

    健康檢查

    Dropwizard提供了開箱即用的基本管理API。 我將端口更改為9091。我為MongoDB連接創(chuàng)建了運(yùn)行狀況檢查。 您需要擴(kuò)展HealthCheck并實(shí)施檢查方法。

    private final MongoClient mongo; ... protected Result check() throws Exception {try {mongo.getDatabaseNames();return Result.healthy();} catch (Exception e) {return Result.unhealthy("Cannot connect to " + mongo.getAllAddress());} }

    其他功能幾乎是不言自明的,或者像任何入門教程一樣簡單。

    增強(qiáng)想法

    這些是我可能會(huì)嘗試添加的內(nèi)容。

    • 將測試添加到Dropwizard部分。
      該項(xiàng)目以PoC開頭,因此與往常不同,我跳過了服務(wù)器部分中的測試。
      Dropwizard擁有“ 測試Dropwizard” ,我想嘗試一下。
    • 不同的持久性實(shí)現(xiàn)。 (couchbase?Hazelcast?)。
    • 使用Google Guice進(jìn)行注射。 并借助它注入不同的持久性實(shí)現(xiàn)。

    就這樣。 希望有幫助。

    • 源代碼: https : //github.com/eyalgo/CountersBuffering

    翻譯自: https://www.javacodegeeks.com/2015/02/dropwizard-mongodb-and-gradle-experimenting.html

    mongodb實(shí)驗(yàn)報(bào)告

    總結(jié)

    以上是生活随笔為你收集整理的mongodb实验报告_Dropwizard,MongoDB和Gradle实验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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