Lightweight framework for building java microservices

Overview

Ja-micro License

Ja-micro is a lightweight Java framework for building microservices.

Introduction

Ja-micro is a framework that allows developers to easily develop microservices in Java. It was developed at Sixt, primarily over the course of 2016, during a push to create a new platform. That platform was started with a goal of supporting two primary languages, being Golang and Java.

We use Go Micro as our framework for our Go services, so a primary concern for this framework is to be compatible with Micro. They diverge a bit in capabilities and methodologies, but they are indeed compatible.

The framework takes care of many of the concerns so that developers can simply focus on the functionality of their services instead.

See the wiki to get started.

Features

  • Simply build service as docker container or fat jar.
  • Configuration from environment, command-line and external configuration services.
  • Standardized json logging.
  • Standardized metrics reporting
  • Simple interface for calling endpoints on other services and handling errors from them.
  • Client-side load-balancer
  • Simple interface for a service to support health checks.
  • Database migrations built-in.
  • Simplified event-handling using Kafka.
  • Pluggable service registry to register and discover service instances.
  • Compatible with Go Micro to allow choice of implementation language.
  • Guice dependency injection for ease of implementation and testing scenarios.
  • Components to create service integration testing scenarios.

Details

Service Registry

The service registry is pluggable with different backends (consul, etc.) The purpose to for each service instance (which may be coming up on a rather anonymous IP address and random port) to register so that other instances can locate it. It is also by extension, available for services to use to locate instances of other services. The service information contains specially-formatted tags which contain information about the format of the request and response messages for each endpoint, and other tags.

Client-side Load-balancer

There is a client-side load-balancer in place behind the facade of the RpcClient. This interacts with the service registry to track instances of services a service wants to interact with, tracks their state of health in order to know whether the instances should receive requests, and tracks the response results of each rpc call in order to maintain 'circuit breakers' to limit exposure to non-healthy service instances.

RpcClient and Error Handling

In order to allow a service to call other services, there is support to easily create RpcClients. An RpcClient is an object that abstracts an rpc endpoint of another service. One can create an RpcClient by using the RpcClientFactory. Once one has an RpcClient, calling another service endpoint is as simple as calling the callSynchronous method (a future version of the framework will also support asynchronous calls) with a protobuf request message, and it will return a protobuf response message.

The timeout policy, the retry policy, and the error-handling are all handled by the client. By default, we have said that the default retry policy should be to retry a failed request one time, if the response is retriable. In a future release, we will add support for time budgeting, where a client of a service can set how much time is allowed to service the whole request. For now, we have a static policy with a default timeout of 1000ms, and this can be customized per client.

The RpcCallException class defines all of our exception categories, their default retriable setting, and what the resulting HTTP status code is (when using an HTTP transport). When one service calls another (client calling server), if a server throws an exception during processing the response, the exception is transparently transported back to the client and can be rethrown on the client-side (ignoring the retry aspect here).

Default RpcClient retry policy (1) can be overridden with setting 'rpcClientRetries'. Default RpcClient timeout policy (1000ms) can be overridden with setting 'rpcClientTimeout'.

Health Checks

Every few seconds, the health state for a service instance is reported to the service registry plugin. Using annotations, there is support for a service developer to easily hook into health checking to mark a service instance as unhealhty. There is also an interface to immediately change the health state of an instance.

Configuration Handling

For any component in a service requiring configuration, it can simply get a ServiceProperties object injected into it, and request the configuration properties from it. Properties are located from three locations: command-line, environment variables, and configuration plugin. They are applied in that order. The same property with a different value from a later source overwrites the earlier source. The configuration plugin provides the ability to do long-polling so that each service can get real-time updates to changes of the configuration from arbitrary sources. There are hooks for service components to get real-time notifications of configuration changes.

Logging

There is standardized logging in place. The log records are json objects, and Markers can be used to dynamically create properties on those objects. The log format can be completely customized.

Metrics

There is standardized metric handling in place. This is heavily opinionated to Sixt's infrastructure, and uses metrics formatted in a specific format and sent to an influx agent to be reported back to a central influxdb cluster. The metrics reporting is pluggable to support reporting metrics in any desired format to any desired destination.

Kafka Events

There are factories/builders in place to easily create publishers and subscribers for topics in Kafka.

Output Artifacts

One can build a shadow jar (fat jar - all dependencies included), or a docker image. One might use the shadow jar for developer testing. The shadow jar is a dependency of the docker image tasks as well. To start a service in a debugger, use the JettyServiceBase as a main class.

Database Migrations

There is currently support for Flyway database migrations, which supports many different SQL databases. This support extends into carefully controlling the service lifecycle and health checks. A future version should support basic migration support for DynamoDB instances.

Dependency Injection

Dependency injection is heavily used in Ja-micro. It is strictly supporting Guice.

Service Integration Testing

We heavily use automation at Sixt in our microservice projects. To support this, the framework gives the ability to developers to automate service integration tests. What this means is that core infrastructure dependencies (for example, on one service, this is consul, postgres, zookeeper and kafka) and the service itself are started as containers under docker-compose. Additionally, to eliminate the problem that would arise of starting containers for every other service dependency (and their dependencies, etc.), there exists a class called ServiceImpersonator that can serve as a complete service mock, available in service registry and serving real rpc requests. However, the developer maps the requests and responses instead of a real instance serving those requests.

Compatibility

Ja-micro is meant to keep compatibility so that service developers can easily choose between developing a service in Java or Go. Other languages can also be supported by using the Go Micro sidecar.

Comments
  • RPC retry timeout configurable

    RPC retry timeout configurable

    Requirements

    • Because of different possible timeouts in cross service RPC communications we need to be able to configure timeouts while making retries while receiving retriable RpcCallExceptions.

    Description of the Change

    1. RetryBackOffFunction interface introduced to use it while building RpcClient via RpcClientBuilder like: RpcClientBuilder.withRetryBackOff(RetryBackOffFunction)
    2. ExponentialRetryBackOff introduced as default posiibility for back off strategy
    3. One also can provide any custom function for backoff while building its cross service RPC communication like: RpcClientBuilder.withRetryBackOff(new RetryBackOffFunction() { @Override public Duration timeout(final int retryCounter) { return "Custom implementation"; } })

    Why Should This Be In Core?

    Chain of micro service calls in general then behave more predictable

    Benefits

    U could tune your RPC's based on various tests results or production behaviour

    Possible Drawbacks

    One should accurate use it with a number of retries more then lets say 5 - it can cause cross service interaction latency growth

    opened by alexborlis 19
  • Compile issue - missing java files

    Compile issue - missing java files

    Has anyone successfully imported this project into IntelliJ ? When I tried to do that, it failed complaining about gradle issue.

    Second, after I manually downloaded dependent jar libraries, and compiled this project, I found a lot of java files reference this java file, com.sixt.service.framework.protobuf.RpcEnvelope.java, but it does not exist. Same issue happens to com.sixt.service.framework.protobuf.FrameworkTest.java.

    Or these two java files will be generated automatically ? Did I miss anything ?

    Thanks.

    opened by zbhuang 7
  • add rpc.call span tag (OSRE-1222)

    add rpc.call span tag (OSRE-1222)

    To leverage the functionality of Instana 2.0 tracing we need to do the following improvements in our tracing implementations:

    • peer.service should be set on the exit spans (this is already done in ja-micro)
    • rpc.call should be set on both exit and entry spans for rpc calls (this is what this tiny PR is doing)
    opened by zserge 4
  • Support decoding of error responses without category

    Support decoding of error responses without category

    Ja-micro throws a NPE during RpcCallException.fromJson(error) if it tries to decode an error response from another service that does not conform with the new error handling and does not contain a category.

    Reproducable with this test:

    @Test
    public void testFromJson_OldErrorHandling() {
        String error = "{\"id\":\"com.sixt.service.foobar\",\"code\":500,\"detail\":\"error message\",\"status\":\"Internal Server Error\"}";
        RpcCallException ex = RpcCallException.fromJson(error);
        assertThat(ex).isNotNull();
    }
    
    opened by tomasulo 4
  • new exception for detailed logging of invalid requests

    new exception for detailed logging of invalid requests

    I added a new exception which gets thrown in case of unexpected reading of a RPC message. It will give you quite a few details about the request itself which will hopefully help to figure out where a request came from.

    opened by mier85 3
  • convert protobuf to json with including default field value

    convert protobuf to json with including default field value

    Description of the Change

    convert protobuf to json making null fields empty(default)

    Alternate Designs

    no

    Why Should This Be In Core?

    need to have possibility to get jsonObject with default field value from protobuf object

    Benefits

    the change provides possibility to check on "hasX" field in generated JsonObject

    Possible Drawbacks

    no

    Applicable Issues

    when convert protobuf to json and after it get value from json object by field name

    opened by reyzor1991 2
  • Use protobuf-java-util for protobuf parsing (to and from JSON)

    Use protobuf-java-util for protobuf parsing (to and from JSON)

    Description of the Change

    I propose to use http://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util for parsing protobuf messages to and from JSON instead of a combination of self-written code and http://mvnrepository.com/artifact/com.googlecode.protobuf-java-format/protobuf-java-format.

    Benefits

    • Exchanging protobuf-java-format (is not being maintained anymore, last release: November 2015) with the actively maintained protobuf-java-util
    • protobuf-java-util provides standardized serialization and deserialization
    • version of protobuf-java-util matches the protobuf version we use in the projects
    • using official code published by google instead of our own version

    Possible Drawbacks

    None, as far as I know.

    opened by tomasulo 2
  • Having a PR template in order to setup proper PRs

    Having a PR template in order to setup proper PRs

    https://help.github.com/articles/creating-a-pull-request-template-for-your-repository/

    If we have a proper template it would be clear to everybody who wants to participate what information has to be provided in a pull request.

    My proposal is to have at least the information proposed in the article from GitHub. But I'm open for a more stricter set of data. What do you think?

    opened by rhoetsc 2
  • bind a diagnostic correlation-id to the kafka event subscriber threads

    bind a diagnostic correlation-id to the kafka event subscriber threads

    Requirements

    Log statements from kafka subscriber threads should include a correlation-id

    Description of the Change

    Added MDC correlation-id mapping

    Why Should This Be In Core?

    So the logs from each event consumer thread could be correlated

    Benefits

    Helps troubleshoot issues in event consumers

    opened by danishnawab 1
  • Support for multiple proto files in System Integration Tests

    Support for multiple proto files in System Integration Tests

    RpcMethodScanner (used in SITs) now continues to search for RPC methods even after finding some. This means that splitting a service's proto interface into multiple files is now possible. Previously this had caused SITs to fail as only the first found proto file was detected and registered meaning only a sub-set of the RPC methods were then available for testing.

    Benefits

    It is helpful in many cases to segregate a proto interface into several smaller interfaces for better code organisation and to separate out different responsibilities.

    opened by jamesblewitt 1
  • Service can't reregister in Consul

    Service can't reregister in Consul

    What did you do Stop consul agent. Start new instance of consul with fresh database. I also notice this when consul agent can't connect to cluster (network partitioning) for some time and then join again but old service registrations and health checks are not valid in cluster anymore.

    What did you expect to see Services which use ja-micro reregister themselves with the new health checks (like services which use go-micro)

    What did you see instead Java services is trying to update old health checks but but getting error 500:

    2018/04/27 07:58:31 [ERR] http: Request PUT /v1/agent/check/pass/service:8b298f948734, error: CheckID "service:8b298f948734" does not have associated TTL from=10.254.26.1:52890
        2018/04/27 07:58:32 [ERR] http: Request PUT /v1/agent/check/pass/service:7559eca09166, error: CheckID "service:7559eca09166" does not have associated TTL from=10.254.26.1:52944
        2018/04/27 07:58:33 [ERR] http: Request PUT /v1/agent/check/pass/service:7dc2b04fd50f, error: CheckID "service:7dc2b04fd50f" does not have associated TTL from=10.254.26.1:53030
        2018/04/27 07:58:34 [ERR] http: Request PUT /v1/agent/check/pass/service:c98c1b816f12, error: CheckID "service:c98c1b816f12" does not have associated TTL from=10.254.26.1:53084
        2018/04/27 07:58:35 [ERR] http: Request PUT /v1/agent/check/pass/service:4d83c1bd8ada, error: CheckID "service:4d83c1bd8ada" does not have associated TTL from=10.254.26.1:53154
        2018/04/27 07:58:35 [ERR] http: Request PUT /v1/agent/check/pass/service:d407da4e2393, error: CheckID "service:d407da4e2393" does not have associated TTL from=10.254.26.1:53160
    

    It is necessary to restart service just to register again in Consul

    opened by andriisabitov 1
  • FastClasspathScanner is outdated -- consider porting to ClassGraph

    FastClasspathScanner is outdated -- consider porting to ClassGraph

    Your project, Sixt/ja-micro, depends on the outdated library FastClasspathScanner in the following source files:

    FastClasspathScanner has been significantly reworked since the version your code depends upon:

    • a significant number of bugs have been fixed
    • some nontrivial API changes have been made to simplify and unify the API
    • FastClasspathScanner has been renamed to ClassGraph: https://github.com/classgraph/classgraph

    ClassGraph is a significantly more robust library than FastClasspathScanner, and is more future-proof. All future development work will be focused on ClassGraph, and FastClasspathScanner will see no future development.

    Please consider porting your code over to the new ClassGraph API, particularly if your project is in production or has downstream dependencies:

    • https://github.com/classgraph/classgraph/wiki/Porting-FastClasspathScanner-code-to-ClassGraph
    • https://github.com/classgraph/classgraph/wiki/Code-examples
    • https://github.com/classgraph/classgraph/wiki/ClassGraph-API

    Feel free to close this bug report if this code is no longer in use. (You were sent this bug report because your project depends upon FastClasspathScanner, and has been starred by 612 users. Apologies if this bug report is not helpful.)

    opened by classgraph-robot 0
  • Exit application if environment verification failed

    Exit application if environment verification failed

    Description of the Change

    This change performs exit from Java process if AbstractService.verifyEnvironment() throws an exception during application start up.

    Benefits

    Currently, if method throws an exception, process stays alive, even though application won't function properly. This change makes sure, that if application's environment isn't valid (or something went wrong while trying to verify it), the program will terminate with the proper error logged. (Before, even though the message was logged, application continued to work in a broken state and could potentially confuse monitoring systems)

    Possible Drawbacks

    None, unless the semantic of AbstractService.verifyEnvironment() isn't supposed to be treated like that and it's ok to fail and not terminate the application (or if someone has been using it like that already, in which case after this fix application won't start unless no exception is thrown)

    opened by welandaz 4
  • Requests that can't be unmarshaled correctly should throw RpcCallException

    Requests that can't be unmarshaled correctly should throw RpcCallException

    Json that can't be unmarshaled back to the request object, or in the case that we receive a non-matching protobuf object, an RpcCallException with category BadRequest should be thrown. The JsonHandler is currently silently ignoring these

    opened by bkrahmer 0
  • Service-to-service calls larger than 2M broken

    Service-to-service calls larger than 2M broken

    When calling another micro service from a ja-micro service, there is an issue when getting a response larger than 2M. I started implementing a fix from jetty's documentation, but tests are failing, so it needs a bit more work.

    opened by bkrahmer 1
  • Add support for map proto fields for service registry

    Add support for map proto fields for service registry

    The problem field looks like: map<string, OtherMessageType> metadata = 10;

    18:39:53.248 [Thread-287] INFO c.s.s.f.s.mockservice.MessageHandler - Starting message handler for com.sixt.service.zoning on port 42378 18:39:53.261 [pool-49-thread-1] ERROR c.s.s.f.r.consul.RegistrationManager - Error inspecting handlers java.lang.NoSuchMethodException: com.google.protobuf.MapEntry.() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.getDeclaredConstructor(Class.java:2178) at com.sixt.service.framework.registry.consul.RegistrationManager.getProtobufClassFieldDescriptions(RegistrationManager.java:320) at com.sixt.service.framework.registry.consul.RegistrationManager.getProtobufClassFieldDescriptions(RegistrationManager.java:341) at com.sixt.service.framework.registry.consul.RegistrationManager.getProtobufClassFieldDescriptions(RegistrationManager.java:341) at com.sixt.service.framework.registry.consul.RegistrationManager.addEndpointsTags(RegistrationManager.java:306) at com.sixt.service.framework.registry.consul.RegistrationManager.getRegistrationTags(RegistrationManager.java:248) at com.sixt.service.framework.registry.consul.RegistrationManager.buildJsonRequest(RegistrationManager.java:203) at com.sixt.service.framework.registry.consul.RegistrationManager.attemptRegistration(RegistrationManager.java:133) at com.sixt.service.framework.registry.consul.RegistrationManager.run(RegistrationManager.java:106) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

    opened by bkrahmer 0
Releases(3.2.42)
Owner
Sixt
Sixt
Sixt
WSO2 Microservices Framework for Java (MSF4J)

Build status: WSO2 Microservices Framework for Java (MSF4J) WSO2 Microservices Framework for Java (MSF4J) is a lightweight high performance framework

WSO2 359 Dec 27, 2022
Microserver is a Java 8 native, zero configuration, standards based, battle hardened library to run Java Rest Microservices via a standard Java main class. Supporting pure Microservice or Micro-monolith styles.

Microserver is a Java 8 native, zero configuration, standards based, battle hardened library to run Java Rest Microservices via a standard Java main class. Supporting pure Microservice or Micro-monolith styles.

AOL 936 Dec 19, 2022
Sample application demonstrating an order fulfillment system decomposed into multiple independant components (e.g. microservices). Showing concrete implementation alternatives using e.g. Java, Spring Boot, Apache Kafka, Camunda, Zeebe, ...

Sample application demonstrating an order fulfillment system decomposed into multiple independant components (e.g. microservices). Showing concrete implementation alternatives using e.g. Java, Spring Boot, Apache Kafka, Camunda, Zeebe, ...

Bernd Ruecker 1.2k Dec 14, 2022
Source Code for 'Pro Java Microservices with Quarkus and Kubernetes' by Nebrass Lamouchi

Apress Source Code This repository accompanies Pro Java Microservices with Quarkus and Kubernetes by Nebrass Lamouchi (Apress, 2021). Download the fil

Apress 24 Oct 31, 2022
Takin is an Java-based, open-source system designed to measure online or test environmental performance test for full-links, Especially for microservices

Takin is an Java-based, open-source system designed to measure online environmental performance test for full-links, Especially for microservices. Through Takin, middlewares and applications can identify real online traffic and test traffic, ensure that they enter the right databases.

ShulieTech 1.2k Dec 21, 2022
A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)

Sentinel: The Sentinel of Your Microservices Introduction As distributed systems become increasingly popular, the reliability between services is beco

Alibaba 20.4k Dec 31, 2022
ColocationSim: Simulate Colocation Datacenter in a Fine Granularity with Microservices and Interference Modeling

ColocationSim Introduction 将在线作业和离线作业混合部署在同一集群(简称混部,Colocation)提升数据中心资源利用率的主流方法,如何在保证在线作业性能的前提下最大化集群的资源利用率成为混部相关研究中最主要问题。混部作业调度算法从集群层面解决这一问题,是学术界、企业界的

null 93 Jan 4, 2023
KBE Spring Boot Microservices

SFG Beer Works - Brewery Microservices This project has a services of microservices for deployment via Docker Compose and Kubernetes. You can access t

John Thompson 29 Nov 2, 2022
Govern Service is a lightweight, low-cost service registration, service discovery, and configuration service SDK.

Govern Service is a lightweight, low-cost service registration, service discovery, and configuration service SDK. By using Redis in the existing infrastructure (I believe you have already deployed Redis), it doesn’t need to bring extra to the operation and maintenance deployment. Cost and burden. With the high performance of Redis, Govern Service provides ultra-high TPS&QPS (10W+/s JMH Benchmark).

Ahoo Wang 61 Nov 22, 2022
CoSky is a lightweight, low-cost service registration, service discovery, and configuration service SDK.

High-performance, low-cost microservice governance platform. Service Discovery and Configuration Service

Ahoo Wang 61 Nov 22, 2022
Apache Dubbo is a high-performance, java based, open source RPC framework.

Apache Dubbo Project Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit official site for quick start and document

The Apache Software Foundation 38.3k Jan 9, 2023
LINE 4.1k Jan 2, 2023
A simple rpc framework.

werpc 微RPC 介绍 A simple rpc framework —— werpc. RPC(Remote Procedure Call):远程过程调用,像调用本地方法一样调用远程过程。采用Client-Server结构,通过request-response消息模式实现。 RPC框架就是指封

stubbornwdb 29 Dec 5, 2022
Cloud native multi-runtime microservice framework

Femas: Cloud native multi-runtime microservice framework Show me femas username:admin password:123456 If you like,star fork it and join us English | 简

PolarisMesh 352 Apr 23, 2022
[JAVA] Projeto exemplo de uma arquitetura modular em Java

Arquitetura modular O objetivo do bom design de software, como já diria Robert C. Martin, em seu livro 'Clean Architecture: A Craftsman's Guide to Sof

HelpDEV 97 Dec 29, 2022
Java client for Consul HTTP API

consul-api Java client for Consul HTTP API (http://consul.io) Supports all API endpoints (http://www.consul.io/docs/agent/http.html), all consistency

Ecwid 402 Jan 6, 2023
Define Java service providers by annotating them directly

Annotated Service Provider Define JVM service providers by annotating the provider class directly. This annotation processor will add to the class-pat

Emily 5 Oct 31, 2021
Lightweight framework for building java microservices

Ja-micro Ja-micro is a lightweight Java framework for building microservices. Introduction Ja-micro is a framework that allows developers to easily de

Sixt 621 Aug 21, 2022
A fast, lightweight and more productive microservices framework

A fast, lightweight and cloud-native microservices framework. Stack Overflow | Google Group | Gitter Chat | Subreddit | Youtube Channel | Documentatio

null 3.5k Jan 5, 2023
[INACTIVE] Avian is a lightweight virtual machine and class library designed to provide a useful subset of Java's features, suitable for building self-contained applications.

Avian - A lightweight Java Virtual Machine (JVM) PLEASE NOTE: This project is not currently being developed, maintained, or supported. Feel free to us

ReadyTalk 1.2k Dec 22, 2022