Skip to content

Commit

Permalink
Merge pull request #30 from microserviceux/documentation-initial
Browse files Browse the repository at this point in the history
Documentation initial
  • Loading branch information
David Dawson committed Dec 17, 2015
2 parents 7ec0d81 + 70fd7a8 commit 51d4eba
Show file tree
Hide file tree
Showing 35 changed files with 387 additions and 52 deletions.
81 changes: 37 additions & 44 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,37 @@ ext {
}

subprojects { subproject ->
if (subproject.name in ["muon-tck", "doc"]) return
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"

group = "io.muoncore"
version = globalVersion.toString()

dependencies {
testCompile "org.codehaus.groovy:groovy-all:2.4.1"
testCompile "org.spockframework:spock-core:1.0-groovy-2.4"
testCompile 'cglib:cglib:2.2.2'
}

compileJava {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}

compileTestJava {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}

repositories {
jcenter()
}
}

subprojects { subproject ->
if (subproject.name in ["muon-examples", "doc"]) return
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"

publishing {
publications {
Expand Down Expand Up @@ -198,27 +220,6 @@ subprojects { subproject ->
}
}


dependencies {
compile "org.codehaus.groovy:groovy-all:2.4.1"
testCompile "org.spockframework:spock-core:1.0-groovy-2.4"
testCompile 'cglib:cglib:2.2.2'
}

compileJava {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}

compileTestJava {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}

repositories {
jcenter()
}

if (project.plugins.hasPlugin('java')) {
// manifest.mainAttributes(provider: 'gradle')
configurations {
Expand Down Expand Up @@ -261,13 +262,11 @@ project('muon-core') {
}
}

project('muon-tck') {
apply plugin: 'application'
project('muon-examples') {
apply plugin: 'groovy'

description = 'Muon TCK Implementation for testing the validity of this Muon library'

mainClassName = "com.simplicity.services.TCKService"

repositories {
maven { url 'http://repo.spring.io/libs-milestone' }
}
Expand Down Expand Up @@ -306,21 +305,6 @@ project('muon-codec-kryo') {
compile 'com.esotericsoftware:kryo-shaded:3.0.0'
}
}
//
//project('spring-boot-starter-muon') {
// description = 'Spring Boot integration for Muon'
// dependencies {
// compile project(":muon-spring")
// compile "org.springframework.boot:spring-boot-starter:1.3.0.RELEASE", {
//// exclude module:"logback-classic"
// }
// testCompile "ch.qos.logback:logback-classic:1.1.3"
// compile "org.springframework.boot:spring-boot-configuration-processor:1.3.0.RELEASE"
// testCompile('junit:junit:4.12')
// testCompile('org.mockito:mockito-core:1.10.19')
// testCompile('org.springframework:spring-test:4.1.6.RELEASE')
// }
//}

project('muon-spring') {
description = 'Spring integration for Muon'
Expand All @@ -346,6 +330,15 @@ project('muon-spring') {
}
}

project('doc') {
description = 'Documentation project'
dependencies {
compile project(":muon-spring")
compile project(":muon-transport-amqp")
compile project(":muon-discovery-amqp")
}
}

task wrapper(type: Wrapper) {
gradleVersion = '2.5'
}
Expand Down
7 changes: 7 additions & 0 deletions doc/amqp/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
== AMQP Support

== Transport


== Discovery

1 change: 0 additions & 1 deletion doc/helloworld.adoc

This file was deleted.

175 changes: 175 additions & 0 deletions doc/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
:source-highlighter: pygments

= Muon Java

Muon Java is the implementation of the Muon microservices toolkit for the Java platform. It enables you to easily build
microservices in many languages that have richer, more performant and fully reactive communication semantics.

Go from days to minutes.

== A Microservice based system in 5 minutes

The quickest way to start a new Muon Java Microservice is to use _Spring Boot_ and the _Spring CLI_.

You can install this by following the instructions at spring.io or using _SDK Man_

```
curl -s get.sdkman.io | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

sdk install springboot
```

You can then create a new Spring Boot based application as a Groovy script.

[source,groovy,indent=0]
----
include::src/main/groovy/io/muoncore/example/Introduction.groovy[lines=7..22]
----
(1) TODO, make these work ok.

[source,groovy,indent=0]
----
include::src/main/groovy/io/muoncore/example/Introduction2.groovy[lines=7..22]
----

These will run in production, as independent services and require no underlying platform or runtime.

== Service Discovery

When distributing computation in the way that Microservices encourage you to, there is a deep need to actually go and find
all the pieces currently are. Tracking all of the service instances in your distributed system, understand what logical services
are actually available, and what they are capable of is a necessary and easily overlooked piece of the puzzle.

Done properly, service discovery gives you the ability to change as needed, and to move and change your services without
having to update every other service to match. Muon takes the position that _availability_ (in the CAP theorum sense) is more
likely to be systemically useful than _consistency_. Not all service discovery systems take this same view.

Service discovery is baked into the core of Muon, and every implementation has a similar looking subsystem. This allows you
to build services that are _autonomous_ and _self healing_. As dependencies of a service start and stop, Muon can tell your application,
and it can react accordingly.

This is accessed in Muon Java by the ```Discovery``` object. This is accessible on the Muon and gives access to listings
of the existing services and a ```ServiceDescriptor``` for each remote service that is currently accessible by the local service.

The Discovery system has most effect when you access the various communication APIs that Muon provides. Each will generally accept
a URL of some kind. The 'host' within that url is a logical service identifier, not a DNS name. This identifier is declared
by the service itself and then registered in the backing discovery service. The actual service discovery
implementation used depends on the configuration.

== Communication Protocols and APIs

Muon is a polyglot toolkit for event based communication. Internally, it uses Communicating Sequential Processes to create and
manage flows of data between networks of services in a scalable, performant and reactive manner.

This underlying model is very powerful and flexible. TO make this easy to pick up and use, we have defined a series of _protocols_,
well known event based exchanges of data across the CSP web that gives semantics that are well known and understood by users.

For the protocol to enable communication between services, it must be implemented on both sides of a connection and so
we have defined a common set of core protocols that are implemented in every Muon library.

It is straightforward to add your own event protocols to give more advanced behaviours, however this comes with the caveat that you would
need to implement this in each muon implementation you want to access.

=== Reactive RPC

Request/ Response is a well understood communication style where you make a single request and expect to receive a single resonse

Muon supports this style of communication, over it's naturally scalable reactive and event based channel communication.

==== Simple RPC

Here is the simplest possible Muon RPC endpoint. It accepts any data pushed to it, and responsds with a simple text message

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveRPC.java[]
----

The client for this looks like

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveRPC.java[]
----

The Response object contains meta data about the reponse, if it succeeded.


==== Making it Reactive

The handler does not need to response synchronously as in the above example. The response can be invoked from any context, and by any thread.

This will cause an event to flow back down the channel and complete the request/ response cycle.

An example of this in action is

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveRPCAsync.java[]
----
//TODO, callouts and description

This demonstrates adding the requests onto a queue and processing them asynchronously.

Be aware that the request will time out on both the client and server side, depending on your configuration.

==== Batch handling RPC

A common failure of RPC based systems is that they attempt to perform too much work in concurrently, and in logical isolation.
This then ends up causing thread thrashing, overwhelming of the thread pool or overload on some backing data store.

Taking the above mechanism to it's logical conclusion, it becomes trivial to batch up the processing of request.

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveRPCBatch.java[]
----

This example will, every 5 seconds, drain the queue, generate a single answer and send it to all of them.


=== Reactive Streams

Muon is built to enable the creation of streams easily. Internally everything is treated as a _channel_, a naturally streaming
construction.

This is best accessed via the Reactive Streams API, a cross industry effort to standardise streaming communication with back pressure.

To publish a new stream, create a _Publisher_ and pass it into the publishStream method, giving it a name, and the semantics of the stream.

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveStreams.java[]
----

Here, we use _Spring Reactor_ to demonstrate the creation of a Publisher, however any Reactive Streams compatible framework or library could
be used.

To access the data from another service, use the subscribe method, passing in the logical Muon discovery url.

[source,java,indent=0]
----
include::src/main/java/io/muoncore/example/ReactiveStreams.java[]
----

Again, this example uses Java and shows two applications communicating over a stream, with back pressure.


=== Event Sourcing


== Event Based Testing


== Spring Support


== Encoding


== Wiretap


== Transports

22 changes: 22 additions & 0 deletions doc/src/main/groovy/io/muoncore/example/Introduction.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.muoncore.example

import io.muoncore.spring.annotations.EnableMuon
import io.muoncore.spring.annotations.MuonController
import io.muoncore.spring.annotations.MuonRequestListener
import org.springframework.boot.autoconfigure.SpringBootApplication


@Grapes([
@Grab('io.muoncore:muon-transport-amqp:6.4-SNAPSHOT'),
@Grab('io.muoncore:muon-discovery-amqp:6.4-SNAPSHOT'),
@Grab('io.muoncore:muon-spring:6.4-SNAPSHOT')])
@SpringBootApplication
@MuonController //(1) Enable Muon and set up
@EnableMuon(serviceName = "users") //(2)
class Introduction {

@MuonRequestListener(path = "/") //(3) An RPC Endpoint
def myRpcEndpoint(Map data) {
return data
}
}
22 changes: 22 additions & 0 deletions doc/src/main/groovy/io/muoncore/example/Introduction2.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.muoncore.example
import io.muoncore.spring.annotations.EnableMuon
import io.muoncore.spring.annotations.MuonController
import io.muoncore.spring.annotations.MuonRequestListener
import org.springframework.boot.autoconfigure.SpringBootApplication

@Grapes([
@Grab('io.muoncore:muon-transport-amqp:6.4-SNAPSHOT'),
@Grab('io.muoncore:muon-discovery-amqp:6.4-SNAPSHOT'),
@Grab('io.muoncore:muon-spring:6.4-SNAPSHOT')])
@SpringBootApplication
@MuonController //(1) Enable Muon and set up
@EnableMuon(serviceName = "gateway") //(2)
class Introduction2 {

@MuonRequestListener(path = "/") //(3) An RPC Endpoint
def myRpcEndpoint(Map data) {
return data
}
}


24 changes: 24 additions & 0 deletions doc/src/main/java/io/muoncore/example/ReactiveRPC.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.muoncore.example;

import io.muoncore.Muon;
import io.muoncore.protocol.requestresponse.Response;

import java.util.concurrent.ExecutionException;

import static io.muoncore.protocol.requestresponse.server.HandlerPredicates.all;

public class ReactiveRPC {

public void exec(Muon muon) throws ExecutionException, InterruptedException {

//request handler
muon.handleRequest(all(), Object.class, request -> {
request.ok("Hi There");
});

//request client
Response<String> data = muon.request("request://myservice/", String.class).get();

System.out.println("The Data is " + data.getPayload());
}
}
Loading

0 comments on commit 51d4eba

Please sign in to comment.