を使用したマイクロサービスの構築


DropWizardメイキングマジック。😎


このチュートリアルでは、DropWizardを使用してMicroServiceを作成します.このフレームワークはWebアプリケーションを構築するためのすべての種類のライブラリを提供します.以下に示すライブラリのいくつかを示します:
Jettyサーバー:これはオープンソースのWebサーバー、軽量で、任意のアプリケーションで埋め込むのは簡単です.
ジャージ:RESTful Webサービスを作成するための実装.
JSONオブジェクトからPOJOおよびその逆の操作を許可します.
メトリック:HTTPリクエスト、データベース接続、キューなどの状態に関する情報を提供します.
グアバ:コレクション、検証、文字列などに対処する多くのクラスをサポートします.
Hibernateバリデータ:Javaオブジェクトの制約としての妥当性検査.
JDBI : JDBCをラップし、リレーショナルデータベースを操作する柔軟な方法を提供します.
Liqubase:データベースの移行とDDLの変更に最適です.

MongoDBはNOSQLデータベースとはるかに。🌳


このドキュメントのドキュメントを指向したデータベース(JSONのようなドキュメントによる)は、リレーショナルデータベースからの機能の一部を組み合わせて使いやすく、マルチプラットフォームはスケールアップのための最良のオプションであり、フォールトトレランス、ロードバランシング、マップリダクションなどがあります.

このマイクロサービスで使用される技術📝

  • OpenJDK 8
  • Docker 2.0.0.0 - MAC 81 ( Mac用のバージョン)
  • MongoDB 4.0
  • マヴェン3.5
  • Mac OS MOJAVE (あるいはWindowsやLinuxのようなもの)
  • nginx 1.15
  • Intellijアイデア2018
  • プロジェクトを起動しましょう.DropWizardは、Webサイトから利用できるMavenアーキタイプを提供します.
    mvn archetype:generate -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DarchetypeVersion=1.3.5 -DgroupId=com.demo -DartifactId=dropwizard-mongodb-ms -Dversion=1.0.0-SNAPSHOT -Dname=DropwizardMongoDBMicroservice
    
    端末を開き、コマンドの前にペーストして、MavenとJavaのインストールと設定を確認します.
    最後の構造は次のようになります.
    dropwizard-mongodb-ms/
    ├── README.md
    ├── config.yml
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── demo
        │   │           ├── DropwizardMongoDBMicroserviceApplication.java
        │   │           ├── DropwizardMongoDBMicroserviceConfiguration.java
        │   │           ├── api
        │   │           ├── cli
        │   │           ├── client
        │   │           ├── core
        │   │           ├── db
        │   │           ├── health
        │   │           └── resources
        │   └── resources
        │       ├── assets
        │       └── banner.txt
        └── test
            ├── java
            │   └── com
            │       └── demo
            │           ├── api
            │           ├── client
            │           ├── core
            │           ├── db
            │           └── resources
            └── resources
                └── fixtures
    
    プロジェクトが作成されると、pom.xml ファイル
    . . .
    <properties>
            <dropwizard.version>1.3.5</dropwizard.version>
            <mainClass>com.demo.DropwizardMongoDBMicroserviceApplication</mainClass>
            <mongodb.version>3.8.2</mongodb.version>
            <jdk.version>1.8</jdk.version>
            <dropwizard.swagger.version>1.0.6-1</dropwizard.swagger.version>
            <mockito.core.version>2.23.0</mockito.core.version>
    </properties>
    . . .
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-sync</artifactId>
        <version>${mongodb.version}</version>
    </dependency>
    
    <dependency>
        <groupId>com.smoketurner</groupId>
        <artifactId>dropwizard-swagger</artifactId>
        <version>${dropwizard.swagger.version}</version>
    </dependency>
    
    <!-- Testing -->
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-testing</artifactId>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>${mockito.core.version}</version>
        <scope>test</scope>
    </dependency>
    <!-- Testing -->
    . . .
    
    ファイルにいくつかの設定を追加しましたconfiguration.yaml , 以下のようになります.
    server:
      maxThreads: 512
      applicationContextPath: /dropwizard-mongodb-ms
      applicationConnectors:
        - type: http
          port: 8080
      adminConnectors:
        - type: http
          port: 8081
    
    logging:
      level: INFO
      loggers:
        com.demo: INFO
    
    #You can choose the user and password what you want.
    mongoDBConnection:
      credentials:
        username: "user_donuts" 
        password: "pAsw0Rd"
      seeds:
        - host: "mongodb"
          port: 27017
      database: "donuts"
    
    swagger:
      basePath: /dropwizard-mongodb-ms
      resourcePackage: com.demo.resources
      scan: true
      info:
        version: "1.0.0"
        title: "Donuts API CRUD"
        description: "A simple API used for expose CRUD operation on MongoDB collection"
        termsOfService: "http://swagger.io/terms/"
        contact:
          name: "Donuts API "
        license:
          name: "Rich Lopez"
    
    設定.YMLは、io.dropwizard.Configuration 以下のようになります.
    package com.demo;
    
    import com.demo.db.configuration.MongoDBConnection;
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    import io.dropwizard.Configuration;
    import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
    
    public class DropwizardMongoDBMicroserviceConfiguration extends Configuration {
    
        /**
         * The data configuration for MongoDB.
         */
    
        private MongoDBConnection mongoDBConnection;
    
        @JsonProperty("swagger")
        private SwaggerBundleConfiguration swaggerBundleConfiguration;
    
        //Getters and setters
    }
    
    このMicroServiceは、CRUD(CREATE、READ、UPDATE、DELETE)でAPI RESTベースを公開します.私はドーナツのような製品を選びました🍩 🤤), このチュートリアルの最後にGithubリポジトリで見つけることができるコードの一部.
    私は、使用しているcom.mongodb.client.MongoCollection コレクションへのアクセスのインターフェイスdonuts 操作により多くの粒度を持つために、私はCRO操作を操作するためにDAO(Data Access Object)を作成しました.
    package com.demo.db.daos;
    //imports ... 
    public class DonutDAO {
    
        /** The collection of Donuts */
        final MongoCollection<Document> donutCollection;
    
        /**
         * Constructor.
         *
         * @param donutCollection the collection of donuts.
         */
        public DonutDAO(final MongoCollection<Document> donutCollection) {
            this.donutCollection = donutCollection;
        }
    
        /**
         * Find all donuts.
         *
         * @return the donuts.
         */
        public List<Donut> getAll() {
            final MongoCursor<Document> donuts = donutCollection.find().iterator();
            final List<Donut> donutsFind = new ArrayList<>();
            try {
                while (donuts.hasNext()) {
                    final Document donut = donuts.next();
                    donutsFind.add(DonutMapper.map(donut));
                }
            } finally {
                donuts.close();
            }
            return donutsFind;
        }
    
        /**
         * Get one document find in other case return null.
         *
         * @param id the identifier for find.
         * @return the Donut find.
         */
        public Donut getOne(final ObjectId id) {
            final Optional<Document> donutFind = Optional.ofNullable(donutCollection.find(new Document("_id", id)).first());
            return donutFind.isPresent() ? DonutMapper.map(donutFind.get()) : null;
        }
    
        public void save(final Donut donut){
            final Document saveDonut = new Document("price", donut.getPrice())
                                          .append("flavor", donut.getFlavor());
            donutCollection.insertOne(saveDonut);
        }
    
        /**
         * Update a register.
         *
         * @param id the identifier.
         * @param donut the object to update.
         */
        public void update(final ObjectId id, final Donut donut) {
            donutCollection.updateOne(new Document("_id", id),
                    new Document("$set", new Document("price", donut.getPrice())
                            .append("flavor", donut.getFlavor()))
            );
        }
    
        /**
         * Delete a register.
         * @param id    the identifier.
         */
        public void delete(final ObjectId id){
            donutCollection.deleteOne(new Document("_id", id));
        }
    
    地図のために、私はMongoDBからPOJOまでフィールドをフィルターするユーティリティクラスを使用します.
    package com.demo.util;
    
    import com.demo.api.Donut;
    import org.bson.Document;
    
    public class DonutMapper {
    
        /**
         * Map objects {@link Document} to {@link Donut}.
         *
         * @param donutDocument the information document.
         * @return A object {@link Donut}.
         */
        public static Donut map(final Document donutDocument) {
            final Donut donut = new Donut();
            donut.setId(donutDocument.getObjectId("_id"));
            donut.setFlavor(donutDocument.getString("flavor"));
            donut.setPrice(donutDocument.getDouble("price"));
            return donut;
        }
    }
    
    その後、MongoDBの情報を操作するPOJOを作成します.
    package com.demo.api;
    //imports ...
    public class Donut implements Serializable {
    
        /** The id.*/
        @JsonSerialize(using = ObjectIdSerializer.class)
        private ObjectId id;
    
        /** The price. */
        @NotNull
        private double price;
    
        /** The principal flavor.*/
        @NotNull
        private String flavor;
    
        /**Constructor.*/
        public Donut() {
        }
    
    //getters & setters
    //hashcode, equals and toString methods
    
    このクラスはエンドポイントに対してのみ使用されます.
    package com.demo.api;
    //imports ...
    public class Response {
        /** The message.*/
        private String message;
    
        /** Constructor.*/
        public Response() {
        }
    //getters & setters
    //hashcode, equals and toString methods
    
    ここでは変換用のユーティリティクラスorg.bson.types.ObjectId to String ジャクソンを使っているオブジェクト.
    package com.demo.util;
    
    import java.io.IOException;
    
    import org.bson.types.ObjectId;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    
    public class ObjectIdSerializer extends JsonSerializer<ObjectId> {
        @Override
        public void serialize(final ObjectId objectId, final JsonGenerator jsonGenerator,
                              final SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(objectId.toString());
        }
    }
    
    変換用String object to array of char .
    package com.demo.util;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    
    import java.io.IOException;
    
    public class PasswordSerializer extends JsonSerializer<String> {
        @Override
        public void serialize(final String input, final JsonGenerator jsonGenerator,
                              final SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(input.toCharArray(), 0, input.toCharArray().length);
        }
    
        @Override
        public Class<String> handledType() {
            return String.class;
        }
    }
    
    これらのPOJOを使用して情報をマップしますconfiguration.yml .
    package com.demo.db.configuration;
    
    import java.util.Arrays;
    import java.util.Objects;
    
    import com.demo.util.PasswordSerializer;
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    
    /**
     * This class is used for credentials.
     * @version 1.0.0
     * @since 1.0.0
     * @author Rich Lopez
     */
    public class Credentials {
    
        /** The user name.*/
        private String username;
    
        /** The password.*/
        @JsonSerialize(using = PasswordSerializer.class)
        private char[] password;
    
        //getters, setters, hashcode and equals methods.
    }
    
    package com.demo.db.configuration;
    
    import java.util.Objects;
    
    public class Seed {
    
        /** The host.*/
        private String host;
    
        /** The port.*/
        private int port;
        //getters, setters, hashcode and equals methods.
    }
    
    package com.demo.db.configuration;
    
    import java.util.List;
    
    public class MongoDBConnection {
    
        /**
         * The credentials user and password.
         */
        private Credentials credentials;
    
        /**
         * The lis of seeds.
         */
        private List<Seed> seeds;
    
        /**
         * The db.
         */
        private String database;
    }
    
    MongoDBとの接続を管理するために、このクラスにYAMLファイル構成から来る情報をマップする必要がありますcom.demo.db.configuration.Credentials , com.demo.db.configuration.MongoDBConnection , com.demo.db.configuration.Seed .
    クラスcom.demo.db.MongoDBFactoryConnection MoogoDB用のクライアントを作成します.
    package com.demo.db;
    //imports ...
    public class MongoDBFactoryConnection {
    
        /** The configuration for connect to MongoDB Server.*/
        private MongoDBConnection mongoDBConnection;
    
        /**
         * Constructor.
         *
         * @param mongoDBConnection the mongoDB connection data.
         */
        public MongoDBFactoryConnection(final MongoDBConnection mongoDBConnection) {
            this.mongoDBConnection = mongoDBConnection;
        }
    
        /**
         * Gets the connection to MongoDB.
         *
         * @return the mongo Client.
         */
        public MongoClient getClient() {
            LOGGER.info("Creating mongoDB client.");
            final Credentials configCredentials = mongoDBConnection.getCredentials();
    
            final MongoCredential credentials = MongoCredential.createCredential(
                    configCredentials.getUsername(),
                    mongoDBConnection.getDatabase(),
                    configCredentials.getPassword());
    
            final MongoClient client = MongoClients.create(
                    MongoClientSettings.builder()
                            .credential(credentials)
                            .applyToClusterSettings(builder -> builder.hosts(getServers())).build()
            );
    
            return client;
        }
    
        /**
         * Map the object {@link Seed} to objects {@link ServerAddress} that contain the information of servers.
         *
         * @return the list of servers.
         */
        private List<ServerAddress> getServers() {
            final List<Seed> seeds = mongoDBConnection.getSeeds();
            return seeds.stream()
                    .map(seed -> {
                        final ServerAddress serverAddress = new ServerAddress(seed.getHost(), seed.getPort());
                        return serverAddress;
                    })
                    .collect(Collectors.toList());
        }
    
    DropWizardのライフサイクルでは、オブジェクトのインターフェイスで管理することができますio.dropwizard.lifecycle.Managed そして、クラスio.dropwizard.lifecycle.MongoDBManaged .
    package com.demo.db;
    //imports ...
    public class MongoDBManaged implements Managed {
    
        /** The mongoDB client.*/
        private MongoClient mongoClient;
    
        /**
         * Constructor.
         * @param mongoClient   the mongoDB client.
         */
        public MongoDBManaged(final MongoClient mongoClient) {
            this.mongoClient = mongoClient;
        }
    
        @Override
        public void start() throws Exception {
        }
    
        @Override
        public void stop() throws Exception {
            mongoClient.close();
        }
    
    もう一つの重要なクラスはHealthcheckですcom.codahale.metrics.health.HealthCheck メソッドを実装するcheck .
    package com.demo.health;
    //imports ...
    public class DropwizardMongoDBHealthCheck extends HealthCheck {
         /** A client of MongoDB.*/
        private MongoClient mongoClient;
    
        /**
         * Constructor.
         *
         * @param mongoClient the mongo client.
         */
        public DropwizardMongoDBHealthCheck(final MongoClient mongoClient) {
            this.mongoClient = mongoClient;
        }
        @Override
        protected Result check() {
            try {
                final Document document = mongoClient.getDatabase("donuts").runCommand(new Document("buildInfo", 1));
                if (document == null) {
                    return Result.unhealthy("Can not perform operation buildInfo in Database.");
                }
            } catch (final Exception e) {
                return Result.unhealthy("Can not get the information from database.");
            }
            return Result.healthy();
        }
    
    このマイクロサービスのエントリポイントはクラスですcom.demo.DropwizardMongoDBMicroserviceApplication すべてのバンドルの設定、初期化クラスなどを読み込みます.io.dropwizard.Application のうち、io.dropwizard.Configuration .
    package com.demo;
    
    import com.demo.db.MongoDBFactoryConnection;
    import com.demo.db.daos.DonutDAO;
    import com.demo.db.MongoDBManaged;
    import com.demo.health.DropwizardMongoDBHealthCheck;
    import com.demo.resources.DonutResource;
    
    import io.dropwizard.Application;
    import io.dropwizard.setup.Bootstrap;
    import io.dropwizard.setup.Environment;
    import io.federecio.dropwizard.swagger.SwaggerBundle;
    import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class DropwizardMongoDBMicroserviceApplication extends Application<DropwizardMongoDBMicroserviceConfiguration> {
    
        /**
         * Logger class.
         */
        private static final Logger LOGGER = LoggerFactory.getLogger(DropwizardMongoDBMicroserviceApplication.class);
    
        /**
         * Entry point for start Application.
         *
         * @param args the args.
         * @throws Exception when the app can not start.
         */
        public static void main(final String[] args) throws Exception {
            LOGGER.info("Start application.");
            new DropwizardMongoDBMicroserviceApplication().run(args);
        }
    
        @Override
        public String getName() {
            return "DropwizardMongoDBMicroservice";
        }
    
        @Override
        public void initialize(final Bootstrap<DropwizardMongoDBMicroserviceConfiguration> bootstrap) {
            bootstrap.addBundle(new SwaggerBundle<DropwizardMongoDBMicroserviceConfiguration>() {
                @Override
                protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(
                            final DropwizardMongoDBMicroserviceConfiguration dropwizardMongoDBMicroserviceConfiguration) {
                    return dropwizardMongoDBMicroserviceConfiguration.getSwaggerBundleConfiguration();
                }
            });
        }
    
        @Override
        public void run(final DropwizardMongoDBMicroserviceConfiguration configuration,
                        final Environment environment) {
    
            final MongoDBFactoryConnection mongoDBManagerConn = new MongoDBFactoryConnection(configuration.getMongoDBConnection());
    
            final MongoDBManaged mongoDBManaged = new MongoDBManaged(mongoDBManagerConn.getClient());
    
            final DonutDAO donutDAO = new DonutDAO(mongoDBManagerConn.getClient()
                    .getDatabase(configuration.getMongoDBConnection().getDatabase())
                    .getCollection("donuts"));
    
            environment.lifecycle().manage(mongoDBManaged);
            environment.jersey().register(new DonutResource(donutDAO));
            environment.healthChecks().register("DropwizardMongoDBHealthCheck",
                    new DropwizardMongoDBHealthCheck(mongoDBManagerConn.getClient()));
        }
    }
    
    コマンドを使用してプロジェクトを構築するには、次の手順に従います.$ mvn clean packageアプリケーションを起動する前に、MongoDBを使用すると、ウェブサイトからダウンロードしたりDockerHubでDocker画像を使用してデータベースを持っている必要があります.
    MongoDBのイメージをダウンロードしたら、新しいコンテナを起動します.$ docker run --name mongodb -d -p 27017:27017 mongo注:情報の持続性を維持するためのボリュームの作成を確認します.
    次のコマンドを入力し、次のコマンドを入力します.$ docker exec -it [container name or id] /bin/bash $ mongo $ use donuts > db.createUser({ user: "user_donuts", pwd: "pAsw0Rd", roles: [ { role: "readWrite", db: "donuts"} ]});デフォルトでは、MongoDBは認証メカニズムをscramに設定します.
    では、コマンドでアプリケーションを起動します.$ java -jar target/dropwizard-mongodb-ms-1.0.0-SNAPSHOT.jar server configuration.ymlユーザとデータベースを作成したら、次のURLでswaggerドキュメントを入力できます.
    http://localhost:8080/dropwizard-mongodb-ms/swagger

    Dockerの作成🐳


    毎日の使用者のための理由の一つは、ユニークな環境を提供し、すべての開発者は依存関係、データベース、Webサーバーなどを同期して維持する理由です.アーチファクトを構築し、展開する簡単な方法は、配信時間を短縮します.
    私はDockerをアプリケーションとMongoDBサーバの起動に使用しています.
    version: '3'
    services:
      mongodb:
        image: mongo
        restart: always
        container_name: mongodb
        environment:
          MONGO_INITDB_ROOT_USERNAME: admin
          MONGO_INITDB_ROOT_PASSWORD: admin
        ports:
          - 27017:27017
        networks:
          - dropw-mongodb-ntw
    
      nginx:
        image: nginx
        container_name: nginx
        volumes:
        - ./nginx.conf:/etc/nginx/nginx.conf
        ports:
        - "8080:80"
        - "443:443"
        networks:
        - dropw-mongodb-ntw
    
      dropw-ms:
        image: openjdk:8-jre
        container_name: dropw-ms
        volumes:
        - ./target/dropwizard-mongodb-ms-1.0.0-SNAPSHOT.jar:/microservice/dropwizard-mongodb-ms-1.0.0-SNAPSHOT.jar
        - ./configuration.yml:/microservice/configuration.yml
        working_dir: /microservice
        command: ["java", "-jar", "dropwizard-mongodb-ms-1.0.0-SNAPSHOT.jar", "server", "configuration.yml"]
        ports:
        - "8090:8080"
        - "8091:8081"
        networks:
        - dropw-mongodb-ntw
    
    networks:
      dropw-mongodb-ntw:
        external:
          name: dropw-mongodb-ntw
    
    コマンドでDockerネットワークを作成します.docker network create dropw-mongodb-ntwコマンドを使用してプロジェクトを構築します$ mvn clean packageDockerを起動する$ docker-compose upデータベースのユーザーを作成するために必要なサービスをすべて作成したら、次のコマンドでコンテナにアクセスします.$ docker exec -it [container name or id] /bin/bash $ mongo > use donuts > db.createUser({ user: "user_donuts", pwd: "pAsw0Rd", roles: [ { role: "readWrite", db: "donuts"} ]});http://localhost:8080/dropwizard-mongodb-ms/swagger

    結論


    DropWizardはいくつかのツールを簡単にマイクロサービスを作成するために提供します.MongoDB、Docker、Nginxのような他の技術と統合できます.すべてが要件と問題解決に依存することを忘れないでください、しかし、私にとって、これはスタートと共有経験によいです.
    githubリポジトリhttps://github.com/ricdev2/dropwizard-mongodb-ms