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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Dropwizard,MongoDB和Gradle实验

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dropwizard,MongoDB和Gradle实验 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

我使用Dropwizard,MongoDB和Gradle創建了一個小項目。 它實際上是從一個實驗性的Guava緩存開始的,作為將計數器發送到MongoDB(或任何其他DB)的緩沖區。 我也想嘗試MondleDB插件的Gradle。 接下來,我想創建某種接口來檢查此框架,因此我決定嘗試使用DropWizard。 這就是該項目的創建方式。

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

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

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

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

用例:帶緩沖區的計數器

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

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

我知道可以直接使用Hazelcast或Couchbase或其他類似的快速內存數據庫。 但是對于我們的用例,那是最好的解決方案。

原理很簡單:

  • 從屬模塊將調用服務以增加某個密鑰的計數器
  • 該實現為每個鍵保留計數器的緩沖區
  • 這是線程安全的
  • 編寫在單獨的線程中進行
  • 每次寫入都會大量增加

柜臺高級設計

緩沖

對于緩沖區,我使用了Google Guava cache 。

緩沖結構

創建緩沖區:

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實現了CacheLoader接口。 當我們調用增加(見下文)時,我們首先通過鍵從緩存中獲取。 如果鍵不存在,則加載器返回值。

BufferValueCacheLoader:

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

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

增加柜臺

增加計數器,如果超過閾值則發送:

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);}} }

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

查看緩沖區

開發服務之后,我想要一種查看緩沖區的方法。 因此,我實現了以下方法,該方法由前端層(Dropwizard的資源)使用。 Java 8 Stream和Lambda表達式的小示例。

獲取所有計數器在緩存中:

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

MongoDB

我之所以選擇MongoDB是因為兩個原因:

  • 我們的系統中有類似的實現,我們決定在那里也使用MongoDB。
  • 易于與嵌入式服務器一起使用。
  • 我試圖設計系統,以便可以選擇其他任何持久性實現并進行更改。

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

    我有兩個操作:增加計數器和獲取所有計數器。 服務實現不擴展Morphia的BasicDAO,而是具有一個繼承它的類。 我使用了組合 (過度繼承),因為我希望兩種服務都具有更多的行為。

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

    public interface Counterable {String counterKey(); }

    DAO,是服務內部的組成部分:

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

    增加柜臺

    MongoCountersUpdater擴展了實現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

    為了在持久層上運行測試,我想使用內存數據庫。 有一個MongoDB插件。 使用此插件,您可以通過僅在運行時創建服務器來運行服務器,或者在Gradle中的maven / task中作為目標運行。

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

    Gradle上的嵌入式MongoDB

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

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

    設置屬性

    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任務

    • startMongoDb只會啟動服務器。 它將運行直到停止它。
    • stopMongoDb將停止它。
    • startManagedMongoDb test ,這兩個任務將在測試運行之前啟動嵌入式服務器。 jvm完成(測試完成)后,服務器將關閉

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

    搖籃設置

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

    一個大的JAR輸出

    當我想從Maven中的所有庫中創建一個大jar時,我會使用shade插件。 我在尋找類似的東西,并發現gradle-one-jar插入。 https://github.com/rholder/gradle-one-jar我添加了該插件apply plugin: 'gradle-one-jar' 。 在類路徑中添加了一個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'} }

    并添加了一個任務:

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

    這些是我需要執行的必要操作,才能使應用程序運行。

    Dropwizard

    Dropwizard是一堆庫,可以輕松快速地創建Web服務器。 它對HTTP使用Jetty,對REST使用Jersey。 它具有其他成熟的庫來創建復雜的服務。 它可以用作易于開發的微服務。

    正如我在簡介中所解釋的,我不會介紹Dropwizard的所有功能和/或設置。 有很多的網站。 我將簡要介紹為使應用程序運行而執行的操作。

    Gradle運行任務

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

    第一個參數是服務器。 第二個參數是配置文件的位置。 如果不將Dropwizard作為第一個參數,則會收到有關可能選項的錯誤消息。

    positional arguments:{server,check} available commands

    我已經在Gradle部分中展示了如何創建一個jar。

    組態

    在Dropwizard中,您可以使用擴展Configuration的類來設置應用程序。 類中的字段應與yml配置文件中的屬性對齊。

    優良作法是根據屬性的用途/職責將其分組。 例如,我為mongo參數創建了一個組。

    為了使配置類正確讀取子組,您需要創建一個與該組中的屬性對齊的類。

    然后,在主配置中,將該類添加為成員,并使用批注進行標記: @JsonProperty 。

    例:

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

    示例:更改端口

    這是配置文件的一部分,用于設置應用程序的端口。

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

    健康檢查

    Dropwizard提供了開箱即用的基本管理API。 我將端口更改為9091。我為MongoDB連接創建了運行狀況檢查。 您需要擴展HealthCheck并實施檢查方法。

    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());} }

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

    增強想法

    這些是我可能會嘗試添加的內容。

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

    就這樣。 希望能有所幫助。

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

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

    總結

    以上是生活随笔為你收集整理的Dropwizard,MongoDB和Gradle实验的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。