Статьи

Couchbase Java SDK 2.0.0 Developer Preview 1

Эта статья была изначально написана Майклом Нитчингером

От имени команды разработчиков SDK я очень рад объявить о первом предварительном просмотре Java SDK следующего поколения! 

Эта новая основная версия, запланированная на 2.0, является полной перепиской старой серии 1.x (в настоящее время 1.4. *). Не оставляя равнодушным, он построен на основе RxJava  для реактивного и потокового программирования и использует Netty в качестве консолидированного уровня ввода-вывода для максимальной производительности.

Прежде чем мы начнем, вот небольшое предупреждение : этот первый предварительный просмотр для разработчиков выпущен для разработчиков, чтобы попробовать наш новейший подход, и, что очень важно, дать нам обратную связь как можно раньше в процессе. API будут меняться, также в зависимости от ваших отзывов и отзывов. Также обратите внимание, что поддержка ребалансировки реализована только частично, поэтому убедитесь, что добавили узлы в кластер, а затем сохраните его как есть, пока играете. Наконец, это лишь небольшое подмножество окончательного API и функциональности, которые мы развернем в ближайшие недели и месяцы, так что не ожидайте, что он будет на одном уровне с текущим SDK.

мотивация

Время идеально подходит для нового SDK. С выпуском Couchbase Server 2.0 сервер значительно перешел от модели использования, ориентированной на значение ключа, к шаблону, ориентированному на запрос (в основном благодаря добавлению Views). Текущая разработка нашего языка запросов следующего поколения (N1QL) только ускоряет это движение. В результате настало время, чтобы SDK также приняли другую модель программирования, чтобы помочь разработчику с точки зрения производительности и масштабируемости их систем.

Кроме того, хотя текущий Java SDK проверен и верен, становится все труднее добавлять новые функции, которые мы поставляем с новыми выпусками сервера. Текущий SDK построен поверх библиотеки spymemcached, которая обеспечивает превосходную поддержку наших операций на основе значений ключей, но большую часть остальной инфраструктуры, которую мы предоставляем (поддержка перебалансировки, представления и т. Д.), Необходимо обойти. Итак, мы решили, что вместо того, чтобы просто украсить гостиную, нам действительно нужно было перестроить фундамент.

То, что вы видите в этом предварительном обзоре для разработчиков, является лишь первым из многих выпусков, которые в конечном итоге получат совершенно новый, стабильный и производительный Couchbase Server SDK не только для Java, но и для всей JVM. Мы полностью осознаем, что все больше и больше языков в JVM становятся популярными (например, Scala, JRuby или Clojure), и вместо предоставления оболочек для Java SDK мы хотели пойти другим путем. SDK разделен на основной модуль, который реализует всю общую инфраструктуру, такую ​​как поддержка перебалансировки, ввод-вывод, механизмы повторных попыток, противодавление и т. Д., Все они обернуты полностью ориентированным на сообщения API. Это буквально выглядит так:

public interface Cluster {

    <R extends CouchbaseResponse> Observable<R> send(CouchbaseRequest request);

}

Теперь это, конечно, не тот API, который мы предоставляем среднему пользователю, но он позволяет нам создавать на его основе стопроцентные языковые SDK без необходимости переопределять жесткие биты снова и снова. Сначала мы начнем с Java-оболочки, но также активно ищем поддержку Scala, и мой коллега Сергей Авсеев уже работает над клиентом JRuby. Это также значительно облегчает разработку оболочек для сообщества.

Возможно, вы также заметили, что метод send не только возвращает R, но и Observable <R>. Observable похож на Iterable, но основывается на толчке, а не на тяге. Все методы в Java SDK также используют этот тип возвращаемых значений (примеры чуть позже покажут это). Это позволяет создавать полностью реактивные и асинхронные приложения поверх SDK, не работая напрямую с пулами потоков. Observables являются частью Rx (Reactive Extensions) , которые доступны на множестве языков благодаря различным библиотекам. Мы используем RxJava , который является вариантом Java. Он очень функционально ориентирован, поэтому люди приходят с таких языков, как Scala , Erlangили другие будут чувствовать себя как дома. На первый взгляд это может показаться странным, но вы быстро к этому привыкнете — и вам никогда не захочется возвращаться (обещаем!). И помните, вы всегда можете заблокировать Observable и превратить его в Iterable.

Внутри основного пакета мы также унифицировали уровень IO. Теперь он полностью работает на Netty, одной из самых быстрых сред NIO в JVM, и используется многими известными компаниями, такими как Twitter, Facebook или Redhat, в ключевых развертываниях. Это означает, что гораздо проще настроить и управлять, предоставляя одинаковые характеристики, независимо от того, выполняете ли вы поиск на основе ключей или выполняете запрос N1QL.

Привет SDK!

Вы должны скачать предварительный просмотр разработчика в первую очередь. Вы можете сделать это либо путем прямой загрузки всех JAR-файлов , либо с помощью maven:

   <dependencies>
        <dependency>
            <groupId>com.couchbase.client</groupId>
            <artifactId>couchbase-client</artifactId>
            <version>2.0.0-dp</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>couchbase</id>
            <name>couchbase repo</name>
            <url>http://files.couchbase.com/maven2</url>
            <snapshots><enabled>false</enabled></snapshots>
        </repository>
    </repositories>

Как только он попадет в ваш classpath, вы можете подключиться к кластеру и затем открыть контейнер (здесь для localhost с контейнером по умолчанию).

Cluster cluster = new CouchbaseCluster();
Bucket bucket = cluster.openBucket().toBlockingObservable().single();

Поскольку мы хотим блокировать текущий поток до тех пор, пока не будет подключено наше ведро, мы преобразуем его в наблюдаемую блокировку и затем вызываем `single ()`, чтобы вернуть наш экземпляр ведра. Теперь мы можем сохранить документ (который имеет ту же семантику, что и предыдущая команда `set`), а затем получить его и распечатать на консоли:

Document doc = JsonDocument.create("hello", JsonObject.empty().put("Hello", "World"));
bucket.upsert(doc).toBlockingObservable().single();

// Prints JsonDocument{id='hello', cas=122278124461233, expiry=0, status=SUCCESS, content={Hello=World}}
System.out.println(bucket.get("hello").toBlockingObservable().single());

Если вы проверите свой веб-интерфейс, вы увидите документ JSON с созданным ключом «привет». Обратите внимание, как теперь вы можете работать с документами JSON по сравнению с текущим SDK.

В то время как в предыдущем примере мы блокировали два раза (один раз для upsert и один раз для get), мы можем использовать Observables для моделирования этого реактивного способа. Вот Java 8:

Document doc = JsonDocument.create("hello", JsonObject.empty().put("Hello", "World"));
bucket
    .upsert(doc)
    .flatMap(document -> bucket.get("hello"))
    .doOnNext(System.out::println)
    .flatMap(document -> cluster.disconnect())
    .subscribe();

Это также возможно с Java 6 и 7, но выглядит немного более многословно, так как они не имеют лямбда-поддержки:

Document doc = JsonDocument.create("hello", JsonObject.empty().put("Hello", "World"));
bucket
    .upsert(doc)
    .flatMap(new Func1<Document, Observable<JsonDocument>>() {
        @Override
        public Observable<JsonDocument> call(Document document) {
            return bucket.get("hello");
        }
    })
    .doOnNext(new Action1<JsonDocument>() {
        @Override
        public void call(JsonDocument document) {
            System.out.println(document);
        }
     })
    .flatMap(new Func1<JsonDocument, Observable<Boolean>>() {
        @Override
        public Observable<Boolean> call(JsonDocument document) {
            return cluster.disconnect();
        }
    })
    .subscribe();

Этот код является полностью асинхронным и может быть разнесен на множество потоков при необходимости. Существует множество вариантов, касающихся планирования и обработки ошибок, о которых пойдет речь в последующих публикациях в блоге.

Запросы просмотров

Реальная сила с Observables приходит, когда вам нужно получить более одного значения. Это касается почти всех ответов на запросы, будь то просмотры или запросы N1QL. Вот синхронный пример запросов представления, вы можете видеть, что мы конвертируем Observable в Iterable (который является его двоюродным братом):

Iterator<ViewResult> iterator = bucket.query(ViewQuery.from("design", "view")).toBlockingObservable().getIterator();

while(iterator.hasNext()) {
    ViewResult result = iterator.next();
    System.out.println(result.id());
}

Или мы можем снова использовать асинхронный вариант:

bucket.query(ViewQuery.from("design", "view")).subscribe(viewResult ->
    System.out.println(viewResult.id())
);

В обоих примерах печатаются идентификаторы, найденные для каждого документа в запросе представления.

Запрос N1QL

Если у вас работает сервер N1QL , вы также можете запросить ваши документы следующим образом:

System.setProperty("com.couchbase.client.queryEnabled", "true");

Cluster cluster = new CouchbaseCluster();
Bucket bucket = cluster.openBucket().toBlockingObservable().single();

bucket.query(Query.raw("select * from default")).subscribe(result -> {
        System.out.println(result);
});

Убедитесь, что вы установили системное свойство, чтобы запросы были включены. Затем вы можете работать с полученными экземплярами `JsonObject`. Это просто базовый интерфейс. Подробнее об этом ниже.

Следующие шаги

Мы искренне верим, что с этим первым предварительным обзором для разработчиков была заложена основа для чего-то действительно замечательного. Этот выпуск уже содержит функциональные возможности, которые будут предоставлены в некоторых следующих версиях сервера, поэтому, если вы покопаетесь в источниках, вы можете найти подсказку или две. В следующих предварительных версиях для разработчиков будет добавлена ​​полная поддержка перебалансировки, и API будет ближе к завершению (т. Е. Текущие DSL для запросов View и N1QL, чтение реплик, ограничения долговечности и т. Д.). Кроме того, мы предоставим больше транскодеров, особенно один для устаревших кодовых баз и других целей сериализации (так что вам не нужно все время использовать JSON). На основе ваших отзывов мы настроим текущие API-интерфейсы, исправим ошибки по мере их появления и сделаем все, чтобы все стало более стабильным по мере приближения к бета-версии.

Пожалуйста, поднимите любые проблемы, которые вы найдете или улучшения, которые вы хотели бы видеть в нашем трекере . Вы также можете задать вопросы на странице нашего сообщества или даже связаться со мной напрямую через твиттер .

Наслаждайтесь!