Giter Club home page Giter Club logo

vertx-blueprint-microservice's Introduction

Vert.x Microservice Blueprint

Travis Build Status

Vert.x blueprint application - A micro-shop microservice application developed with Vert.x. This repo is intended to be an illustration on how to design microservice architecture and develop microservice applications using Vert.x.

This blueprint works with Vert.x 3.4.1.

Note: We are refactoring the whole architecture of the microservice blueprint. This can take a long time and the improved new version is expected to be released by the end of May. See here for details.

Content

  • Microservice with Vert.x
  • Asynchronous development model
  • Reactive and functional patterns
  • Event sourcing patterns
  • Asynchronous RPC on the clustered event bus
  • Various type of services (e.g. REST, message source, event bus service)
  • Configuration retriever
  • Service discovery
  • Circuit breaker
  • Polyglot persistence support
  • API gateway
  • Global authentication (Local/OAuth 2)
  • Centralized logging using ELK stack
  • Monitoring

Documentation

Detailed tutorials are available here!

Architecture

Microservice Architecture

Build/Run

First, for api-gateway and monitor-dashboard component, you have to enter the src/main/resources/webroot directory and install the frontend dependencies with bower:

bower install

Then build the code:

mvn clean install -Dmaven.test.skip=true

To run the microservice with Docker Compose, please refer to the running instruction.

Contributing

Contributions are definitely welcome !

vertx-blueprint-microservice's People

Contributors

crazyfrozenpenguin avatar gadieichhorn avatar sczyh30 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vertx-blueprint-microservice's Issues

Exception Handling in the Service Implementations is unflexible

Hi,

the idea with the Rest API Class and the Service Impl is very good and i like it. My Problem is, that if an Impl. throws an exception, it results all the time in a HTTP Error 500.

From my point of view, there should be some default Exceptions.

An idea is to create a BaseException and some Special Exception (extends the BaseException) and containing the http error code.

Inside the Service Impl i can throw this special Exception and the function internalError handle this and change the HTTP Status.

protected void internalError(RoutingContext context, Throwable ex) {
		context.response().setStatusCode(500).putHeader(HttpHeaders.CONTENT_TYPE.toString(), "application/json");
		
		if (ex instanceof CustomBaseException) {
			context.response().setStatusCode(((CustomBaseException)ex).getHttpStatusCode());
		}
		
		context.response().end(new JsonObject().put("error", ex.getMessage()).encodePrettily());
	}

Or do you've an other concept to control the HTTP Status codes inside the Service Implementations ?

Thanks
Marcel

Multipart not working

Multipart/form-data with image

is not working.

any ideas?

I set createHttpServer -> req.setExpectMultipart(true); before router::accept.
It still not working.

In test, I make vertex.createHttpServer is working.

Use the Original ServiceImpl inside the RestVerticle can result in a vertx context issue

Hi,

inside your verticles you deploy the rest api with the same instance, created in the verticle.

// create the service instance
ProductService productService = new ProductServiceImpl(vertx, config());
// register the service proxy on event bus
ProxyHelper.registerService(ProductService.class, vertx, productService, SERVICE_ADDRESS);
...
.compose(servicePublished -> deployRestService(productService))
...

As an example:

  • you could use a http client inside your ProductServiceImpl (and create this one time with the constructor)

  • inside ProductServiceImpl there is a method "test" wich one use this http client

  • and following changes in the ProductVerticle:

private Future<Void> bindEventBusListener(ProductService productService) {
  Future<Void> future = Future.future();
  vertx.eventBus().consumer("cqrs.channel", m -> {
    productService.test(); // <--- this is important
  }).completionHandler(future.completer());
  return future.map(r -> null);
}

you will run in this:

[vert.x-eventloop-thread-1] WARN io.vertx.core.http.impl.ConnectionManager - Reusing a connection with a different context: an HttpClient is probably shared between different Verticles

as a solution, you should give a proxy instance inside the Rest API and inside the eventbus consumer.

ProductServiceVertxEBProxy productServiceProxy = new ProductServiceVertxEBProxy(vertx, SERVICE_ADDRESS);

...
.compose(servicePublished -> deployRestService(productServiceProxy))
.compose(servicePublished -> bindEventBusListener(productServiceProxy))
...

Maybe you ask why a eventBus consumer inside you verticles is needed. In my project i use CQRS and communicate with events.

As an example:

i've a customer and a email messaging verticle in your style.

a customer calls register and we write the data into a database and return the customer maybe a access_token.
at the same time, we're using the eventbus to send a CUSTOMER_REGISTER event.

this CUSTOMER_REGISTER is subscribed inside the messaging verticle and will send a email with a confirmation code to this customer
after that, the messaging verticle send a CONFIRMATION_MAIL_SEND event (including the generated confirmation code)

this CONFIRMATION_MAIL_SEND is subscribed by the customer verticle and save this confirmation code inside the customer database (via this testMethod from above)

i hope, i could describe my topic

Thanks
Marcel

P.s: i forget one thing to mention. both verticles DON'T share any Java Classes or generated code (to keep them decoupled). They just send plain JsonObject's to a channel.

Internal api security

Ho would you go about preventing the internal apis from getting accessed directly without routing requests through the api gateway?

We would like to enforce all requests to go through the api gateway only.

Bower

Hello,

Bower can be built with maven. Please add this to your "api-gateway/monitor-dashboard" poms:

  <!-- deploy bower -->
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.5.0</version>
    <configuration>
       <source>1.8</source>
       <target>1.8</target>
    </configuration>
    <executions>
      <execution>
        <id>exec-bower-install</id>
        <phase>generate-sources</phase>
        <configuration>
          <executable>bower</executable>
          <arguments>
            <argument>install</argument>
          </arguments>
          <workingDirectory>${basedir}/src/main/resources/webroot</workingDirectory>
        </configuration>
        <goals>
          <goal>exec</goal>
        </goals>
      </execution>

    </executions>
  </plugin>

  <!-- cleanup bower components -->
  <plugin>
    <artifactId>maven-clean-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
      <filesets>
        <fileset>
          <directory>${basedir}/src/main/resources/webroot/bower_components</directory>
        </fileset>
      </filesets>
    </configuration>
  </plugin>

This project has helped me a lot.
Thanks,
-J

Database middleware abstraction

The database middleware can be the abstraction of the whole database operations.

This can be a big change for both the entire architecture and service components:

  • The database middleware should support cache (e.g. Redis), simple load balancing and scalability (database sharding)
  • The database middleware should be HA in production environment (so should be fault-tolerant
  • The service components should operate the DB via the database middleware rather than directly connect to database

In addition, the internal DB library can be replaced with a more convenient and reactive one (maybe JOOQ).

The performance of this middleware component is of vital importance so this should be tested well.

Vertx 3.4.0 and Rx

Hello,

the class BaseMicroserviceRxVerticle.java is not compatible anymore with Vertx 3.4.0.

discovery.publishObservable
discovery.unpublishObservable

are renamed to publish/unpublish with and callback handler.

M

ClassNotFoundException XXXVertxProxyHandler

Hi,
if you build the repo with maven and then start one of the fat-jars (e.g. java -jar account-microservice-fat.jar -conf ../src/config/local.json) it lead to the following stacktrace.

The problem is that the generated-folders are not included in the fat-jar. What is best practice here?

java.lang.IllegalStateException: Cannot find proxyClass: io.vertx.blueprint.microservice.account.AccountServiceVertxProxyHandler at io.vertx.serviceproxy.ProxyHelper.loadClass(ProxyHelper.java:104) at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:78) at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:71) at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:65) at io.vertx.blueprint.microservice.account.UserAccountVerticle.start(UserAccountVerticle.java:30) at io.vertx.core.impl.DeploymentManager.lambda$doDeploy$8(DeploymentManager.java:434) at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:445) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.ClassNotFoundException: io.vertx.blueprint.microservice.account.AccountServiceVertxProxyHandler at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at io.vertx.serviceproxy.ProxyHelper.loadClass(ProxyHelper.java:102) ... 11 more

java.lang.IllegalStateException: Result is already complete: succeeded

你好,非常感谢提供的vertx系列向导教程。有个问题想请教下,我模仿TODO为microservice添加测试用例执行tearDown中close方法时报错Result is already complete: succeeded。实际debug发现BaseMicroserviceVerticle中的stop方法被调用了两遍。

@after
public void tearDown(TestContext context) {
vertx.close(context.asyncAssertSuccess());
}

提示异常:
[vert.x-eventloop-thread-0] 2016-11-07T08:42:09.981+08:00 SEVERE [io.vertx.core.impl.ContextImpl] Unhandled exception
java.lang.IllegalStateException: Result is already complete: succeeded
at io.vertx.core.impl.FutureImpl.checkComplete(FutureImpl.java:164)
at io.vertx.core.impl.FutureImpl.complete(FutureImpl.java:108)
at io.vertx.core.impl.FutureImpl.handle(FutureImpl.java:135)
at io.vertx.core.impl.FutureImpl.handle(FutureImpl.java:23)
at io.vertx.core.eventbus.impl.EventBusImpl.lambda$callCompletionHandlerAsync$2(EventBusImpl.java:340)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:316)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:418)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:440)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
at java.lang.Thread.run(Thread.java:745)

Enhance authentication

Current authentication implementation in the API Gateway is not very concise, and only supports Keycloak via Vert.x OAuth 2. So it's necessary to enhance the implementation of authentication. Maybe an individual authentication component is needed.

Rxjava jdbc

数据链接在官方的demo中,需要关闭链接,这里的演习程序没有关闭。是不需要吗?

如果使用传统的方式比如JDBI需要包装一层线程池运行吗

Unprotected resource

Looks like the /api/* resources are not protected by keycloak

 router.route("/api/*").handler(this::dispatchRequests);

error with the last step "sudo ./run.sh"

It has been built successfully, until the last step.

Error: No machine name(s) specified and no "default" machine exists.

I intend to run this project. I need help, thank you.

Improve health check and fault-tolerance mechanism

Hi,

you're using the CircuitBreaker for the proxy services and the health check. In general it's a good idea, but the implementation is a little bit useless.

an example:

ApiGateway
ProductMicroservice
AuthMicroservice

The Microservices are independent from each other.

Case: the ProductMicroservice is not answering in the health Check for 5 times. After that, the ApiGateway CB will stop.

BUT: if one auth request is comming and pass the CB, the complete Gateway is working again.

From my point of view. Every Service should have an independed CB. otherwise the implementation makes no sence in a microservice world. One service should not shutdown the whole system.

Do you've any ideas how to implements this ?

Thanks
Marcel

Lock down docker image versions

@sczyh30 First of all, thanks for this blueprint! looks really good and is well documented

However, I think it would be better to lock down the versions of the docker images instead of relying on "latest". Otherwise, you might be in a constant bug fixing everytime a new docker image breaks your project.

For example, elasticsearch:latest, logstash:latest and kibana:latest can no longer be found. MySQL currently has Unable to load authentication plugin 'caching_sha2_password'. Keycloak fails on first startup with Caused by: java.sql.SQLException: Access denied for user 'keycloak'@'172.27.0.2' (using password: YES).

Currently, I havent been able to run the project because Im still trying to address these docker issues.

Keycloak reporting error when first time connecting to MySQL

I'm running blueprint on MacOS High Sierra. All dependencies have been provided, but when running "sudo ./run.sh" it gave errors like this:

keycloak-server_1 | Caused by: java.sql.SQLException: Access denied for user 'keycloak'@'172.18.0.5' (using password: YES)

I could see the MicroShop page when pointing to localhost:8787, but the keycloak auth didn't show up.

Any idea why this happens, and whether it has anything to do with keycloak/mysql misconnection?

Error in HealthCheck for services

Hi,

in the file https://github.com/sczyh30/vertx-blueprint-microservice/blob/master/api-gateway/src/main/java/io/vertx/blueprint/microservice/gateway/APIGatewayVerticle.java

method: sendHeartBeatRequest

boolean notHealthy = statusList.anyMatch(status -> !status.getBoolean("status"));

        if (notHealthy) {
          String issues = statusList.filter(status -> !status.getBoolean("status"))
            .map(status -> status.getString("name"))
            .collect(Collectors.joining(", "));

          String err = String.format("Heart beat check fail: %s", issues);
          // publish log
          publishGatewayLog(err);
          return Future.failedFuture(new IllegalStateException(err));
        } else {
          // publish log
          publishGatewayLog("api_gateway_heartbeat_check_success");
          return Future.succeededFuture("OK");
        }

this code block will not work in an error case and don't log any error. After using the stream with notHealthy = statusList.anyMatch you cannot use the same stream again in statusList.filter

it will result in

java.lang.IllegalStateException: stream has already been operated upon or closed

Marcel

Redesign for distributed transactions

A redesign is needed for handling distributed transactions more correctly and effectively. One example is [decrease the inventory amount, create an order, store/dispatch].

Initial ideas:

  • Message middleware based architecture(maybe Kafka) with event sourcing
  • Compensating transaction support(rollback)

pending...

Logout not working

I tried to following your example to implement a gateway for my service.

The logout seems not to be working when the user goes back to a protected URL.

How can I fix this?

elasticsearch 5

the new version of ES doesnt work with docker OOtB so you need to do few changes to the process.

first, after you create a docker host (docker-machine) you need to ssh into the host and update the map
I called my machine "vertx"

docker-machine ssh vertx
Boot2Docker version 1.12.3, build HEAD : 7fc7575 - Thu Oct 27 17:23:17 UTC 201
Docker version 1.12.3, build 6b644ec
docker@vertx:~$ sudo sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144

you also need to make some changes to the docker-compose.yml

  elasticsearch:
    image: elasticsearch
    ports:
      - "9200:9200"
      - "9300:9300"
    restart: always
    command:
      - "-E"
      - "network.host=0.0.0.0"
      - "-E"
      - "discovery.zen.minimum_master_nodes=1"
    environment:
      ES_JAVA_OPTS: "-Xms1g -Xmx1g -Des.path.conf=/etc/elasticsearch"

here is a working ELK stack I used as reference.
https://github.com/deviantony/docker-elk

Refactor the microservice architecture for Vert.x 3.5

Some plans:

  • Adapt for API changes
  • Kafka integration #2
  • Enhance global authentication (JWT based) #5
  • Enhance API Gateway (e.g. file upload, WebSocket, fault-tolerance, performance)
  • Enhance integration with Vert.x Config
  • More functional and reactive code (with RxJava 2)
  • Improve fault-tolerance architecture (e.g. Circuit Breaker for each microservice component) #19
  • Redesign for distributed transactions #22
  • Improve performance / throughput test
  • Robust health check mechanism (Maybe integrate with Vert.x Health Check) #19
  • Database middleware layer #26
  • Initial design for service orchestration
  • Distributed tracing
  • Service mesh for cloud native architecture

This can be a huge change so it may take a long time to refactor.

Update (Feb 13, 2018): Redesigning...

3-layer architecture

There is no clear distinction between service layer and data access layer in micro-services. Is there any particular reason for that?
Also what about tests? I'm still not sure about the best practices to test the logic without relying on an actual data source. In other words what would be the best way to mock data while doing tests?

A question about Maven override #{main.verticle} property

I can't in my project package to override the main.verticle property.

When I execute the command mvn clean install then maven throw :

Cannot find 'MainVerticle' in class org.apache.maven.plugins.shade.resource.ManifestResourceTransformer

so I think the reason for the error is I can't override the property

What seems to be the problem

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.