Статьи

Почему меня волнует использование Neo4j для бэкенда CMDB

Zkybase — это моя первая попытка создания базы данных управления конфигурацией с открытым исходным кодом (CMDB), но я не впервые создаю CMDB. На работе группа из нас создала и продолжает создавать собственную внутреннюю систему CMDB, называемую deathBURRITO, в рамках наших усилий по автоматизации развертывания. Мы создали deathBURRITO, используя Java, Spring, Hibernate и MySQL. У deathBURRITO даже есть роботизированный осел (на самом деле), цель которого мы еще не определили.

Пока смерть BURRITO хорошо сработала для нас. Некоторые из его функций, а именно те, которые непосредственно поддерживают автоматизацию развертывания, оказались более полезными, чем другие. Но общее согласие, по-видимому, заключается в том, что deathBURRITO устраняет важный пробел в управлении конфигурацией (CM), когда ранее мы «управляли» данными CM в вики отдела, в электронных таблицах, в файлах XML и на диаграммах Visio. Хотя впереди еще много работы, то, что мы сделали до сих пор, было достаточно правильным, и мы смогли развить его по мере развития наших потребностей.

Это не значит, что я бы ничего не изменил. Я думаю, что есть возможность сделать что-то лучше на бэкэнде. Это действительно был стимул для Zkybase.

Пересмотр бэкэнда с Spring Data

Поскольку CM включает в себя множество различных типов объектов (например, регионы, центры обработки данных, среды, фермы, типы экземпляров, образы машин, экземпляры, приложения, промежуточное программное обеспечение, пакеты, развертывания, группы безопасности EC2, пары ключей — список можно продолжить и на), было полезно создать небольшую структуру для более или менее автоматической обработки различных сквозных задач, таких как стандартные представления (представление списка, представление сведений, представления формы), веб-контроллеры (операции CRUD, стандартные запросы), DAO (опять же, операции и запросы CRUD), общие возможности объекта домена, безопасность и многое другое. И я думаю, будет справедливо сказать, что это помогло, хотя, возможно, не так сильно, как мне бы хотелось (по крайней мере, пока). Факт остается фактом, что каждый раз, когда мы хотим добавить новый объект в систему,нам все еще нужно проделать немалую работу, чтобы каждый слой фреймворка делал то, что должен.

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

Поэтому я начал искать способы упростить бэкэнд.

Недавно я начал бездельничать с Spring Data , в частности Spring Data JPA и Spring Data MongoDB . Для тех, кто не использовал Spring Data, он предлагает несколько приятных функций, которые я хотел бы попробовать:

  • Одна из особенностей заключается в том, что он может генерировать реализации DAO автоматически, используя механизм динамического прокси Java. Spring Data называет эти DAO «репозиториями», что меня устраивает. В основном, как разработчик, вы пишете интерфейс, расширяющий интерфейс репозитория для конкретного типа, например JpaRepository или MongoRepository. Вам не нужно объявлять операции CRUD, потому что интерфейс Repository уже объявляет те, которые вы обычно хотите (например, save (), findAll (), findById (), delete (), deleteAll (), exist (), count) (), и т.д.).
  • А если у вас есть пользовательские запросы, просто объявите их в интерфейсе, используя некоторые соглашения об именах методов, и Spring Data сможет выяснить, как создать реализацию для вас.
  • В некоторых случаях Spring Data обрабатывает сопоставление для вас. В случае Spring Data JPA вы все равно должны убедиться, что у вас есть правильные аннотации JPA, и это не так уж плохо. Но для MongoDB, поскольку бэкэнд MongoDB — это просто BSON (двоичный JSON), сопоставление объектов с MongoDB является простым, поэтому Spring Data справляется с этим очень хорошо, не требуя множества аннотаций.

«Изменитель игры» может быть слишком сильным для функций, которые я только что описал, но, черт возьми, они полезны. Помимо упрощения и ускорения реализации репозиториев, Spring Data позволяет мне избавиться от большого количества стандартного кода (множества реализаций DAO) и даже от некоторого кода среды DAO, подобного Spring Data, который я обычно пишу. (Вы знаете, определите общий интерфейс DAO, общий абстрактный класс DAO и т. Д.) Мои дни создания DAO непосредственно против Hibernate, вероятно, прошли.

Но это не единственное изменение бэкенда, на которое я смотрю.

Пересмотр бэкэнда, часть 2: Neo4j + Spring Data Neo4j

Поскольку Spring Data имеет тенденцию тяготеть к хранилищам NoSQL, я наконец-то нашел время для чтения Neo4j и некоторых других вещей, о которых мне, вероятно, следовало бы прочитать давно. Лучше поздно, чем никогда, я думаю. Меня поразило, что Neo4j может быть очень интересным способом реализации бэкэнда CM, и что Spring Data Neo4j может помочь мне сохранить уровень DAO тонким. Вот мысли:

Помните, как я упоминал, что Spring Data генерирует реализации репозитория автоматически на основе интерфейсов? Вот как это выглядит с Spring Data Neo4j:

package org.skydingo.zkybase.repository;

import org.skydingo.zkybase.model.Person;
import org.skydingo.zkybase.model.Project;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;

public interface ProjectRepository extends GraphRepository<Project> {
    Project findProjectByKey(String key);
    Project findProjectByName(String name);

    @Query("start person=node({0}) match person-->project return project")
    Iterable<Project> findProjectsByPerson(Person person);
}

Let me repeat that I don’t have to write the repository implementation myself. GraphRepository comes with various CRUD operations. Methods like findProjectByKey() and findProjectByName() obey a naming convention that allows Spring Data to produce the backing query automatically. And in the findProjectsByPerson() case, I provided a query using Neo4j’s Cypher query language (it uses ASCII art to define queries–how ridiculously cool is that?).

Exploring the ideas above with Zkybase

The point of Zkybase is to see whether we can build a better mousetrap based on the ideas above. I’m using Neo4j and Spring Data Neo4j to build it out. I haven’t decided yet whether Zkybase will focus on the CMDB piece or whether it’s a frontend to configuration management more generally (delegating on the backend to something like Chef or Puppet, say), but the CMDB will certainly be in there. That will include a representation of the as-is (current) configuration as well as representations for desired configurations as might be defined during a deployment planning activity.

So far I’m finding it a lot easier to work with the graph database than with a relational database, and I’m finding Spring Data Neo4j to be a big help in terms of repository building and defining app-level schemas. The code is a lot smaller than it was when I did this with a relational database. But it’s still early days, so the jury is out.

Watch this space for further developments.