📜 ⬆️ ⬇️

Monolithic Message-Oriented Application (MMOA)

Message Just finished the project
you have full knowledge
how it should be implemented.
(C) Tom Demarco

I always wanted to try to write an application, the modules of which communicate with each other through messaging. In principle, it is quite even in the spirit of the classical understanding of its founders. However, before Erlang, I was not old enough and I was familiar only with Golang, so it was on him that I tried to create a slightly bizarre, but nonetheless curious, web application architecture.

I conditionally broke the application into parts, which I call services. Services receive and send messages, and this is the only way they interact with each other. Of course, there is a significant overhead in this - it will be faster to call a method with the transfer of a message than to send them through channels and a bus. In addition, in addition to the overhead projector, there is also a complication of architecture, this is also important. If for the reader these are important and critical requirements, then perhaps he should not continue to bother reading this article, because MMOA is just an experiment and a curious piece of work.

However, if you still decided to spend your time reading (for which many thanks), then in addition to the minuses, I will point out one implicit plus, which is in all this strange construction. The fact is that communication through messages implies a little more freedom and independence of the services included in the monolith. Probably not obvious. But whenever possible, I tried to ensure that services and channels of communication with them were formed outside the core of the application. In the example lying in the distribution kit, it is clearly seen that the service initialization code lies in the main package.
')
Well, if everything is exactly as I say, then what is actually next? Monolith - not a monolith, but what is the profit? (the last phrase was in rhyme, an unexpected surprise!). Here I am just like a cap, I will say that the service, which is fairly easy to select from the monolith, if necessary, can be distinguished from the monolith. Dedicated service can be called microservice, which is what it will be by and large. Why allocate service in microservice? This is an important question. Under normal conditions, this is not required, but if, for example, this service suddenly became so heavy that it’s time for him to move to his own server? Then it is possible.

However, the issue of allocating a service to microservice is quite hypothetical, but the desire to play around with messages and touch them is quite real)) Although MMOA can be called a framework (more likely a microform), however, for me it is in many ways more like a library or a toolkit with some implementation concepts or, frankly, hypotheses. If I am to avoid tautology, perhaps I will sometimes call MMOA in different ways, please understand and forgive.

Wikipedia about frameworks
A framework (sometimes a framework; Anglicism, a neologism from a framework - a framework, a structure) is a software platform defining the structure of a software system; software that facilitates the development and integration of various components of a large software project.

General principles

MMOA

The concept of an MMAA is as follows: fairly independent services are developed (for this framework I have divided into several libraries), these services are combined into a single application and in the process of work they exchange data with each other by sending messages. The delivery address of the message consists of the name of the service and the subject of the message. (Themes are in essence events of events in services, however in this case for messages I preferred to call them that way).

Initially, after reading smart books, I created a very complex and intricate architecture, but over time, the husks fell off and a small amount of ingredients were left. I had to cut it alive. From the remote I will probably mention balancing channels supporting queues with priorities. Well, let them rest in peace))

Fast start


MMOA service As part of the distribution, there is a ready-made example that vividly demonstrates the work of MMOA on the example of a simple site, following my old tradition, dedicated to the Latin American dance “rumba”. Go to the examples folder, compile and run the application. The result of the work look in the browser at localhost . As a router, I used my Bxog development, but you can use any router of your choice. Templating is done by the standard html / template library.

Details


The demo application has two services:


MMOA Composition


For convenience and ease of creating services as part of the application, some parts of the MMAA are separated into separate libraries.

tools


This library is required when creating both applications and services.


service


This library is used to create utility services and is required when writing custom services.


support


This library contains the aggregator and basket service services, as well as a bus for sending messages.


Application root


These files are the core of the MMOA, and are not used outside of it.


How to add your service


For a bunch of the above words, it can be very incomprehensible how convenient / inconvenient to use the concept described by MMOA, so with a simple example I will describe the process of adding a new service. For example, we wanted the date to always be displayed on the page.

Update the list of services and topics


In the tools / services_themes.go add structure

// ThemeCalendar structure type ThemeCalendar struct { Date TypeTHEME } 

We add the Calendar ThemeCalendar line to the Themes structure and the Calendar TypeSERVICE line to the ListServices structure.

Create a service file


Create the directory example / calendar and the calendar.go file with the following contents:

 package calendar // Monolithic Message-Oriented Application (MMOA) // Calendar // Copyright 2016 Eduard Sesigin. All rights reserved. Contacts: <claygod@yandex.ru> import ( "time" "github.com/claygod/mmoa/service" "github.com/claygod/mmoa/tools" ) func NewServiceCalendar(chIn chan *tools.Message, chBus chan *tools.Message) *ServiceCalendar { the := tools.NewThemes() s := &ServiceCalendar{ service.NewService(the.Service.Calendar, chIn, chBus), } s.MethodWork = s.Work s.setEvents() s.Start() return s } type ServiceCalendar struct { service.Service } func (s *ServiceCalendar) setEvents() { s.Methods[s.The.Calendar.Date] = s.dateEvent } func (s *ServiceCalendar) dateEvent(msgIn *tools.Message) { t := time.Now() msgOut := tools.NewMessage().Cid(msgIn.MsgCid). From(s.Name).To(msgIn.AddsRe). Theme(msgIn.MsgTheme). Field("Day", t.Day()). Field("Month", int(t.Month())). Field("Year", t.Year()) s.ChBus <- msgOut } 

Templates


In the example / data directory, create a date.html file with the line {{.Day}}. {{. Month}}. {{. Year}} , and change the contents of the general page template to:

 <!DOCTYPE html> <html> <head> <title>{{.Title}}</title> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <link rel="stylesheet" href="file/twocolumn.css"> </head> <body> <div id="header"><h1>Rumba</h1></div> <div id="sidebar"> {{.Sitemap}} {{.Date}} </div> <div id="content"> {{.Record}} </div> </body> </html> 

Rule the application


Now it remains for us to add a new library to the import files, create a channel for it, create a new structure, and add a line to the handler's initialization:

 package main // Monolithic Message-Oriented Application (MMOA) // Application // Copyright 2016 Eduard Sesigin. All rights reserved. Contacts: <claygod@yandex.ru> import ( "github.com/claygod/Bxog" "github.com/claygod/mmoa" "github.com/claygod/mmoa/example/article" "github.com/claygod/mmoa/example/calendar" "github.com/claygod/mmoa/example/menu" "github.com/claygod/mmoa/tools" ) const chLen int = 1000 func main() { chBus := make(chan *tools.Message, chLen) chMenu := make(chan *tools.Message, chLen) chArticle := make(chan *tools.Message, chLen) chCalendar := make(chan *tools.Message, chLen) the := tools.NewThemes() app := mmoa.NewController(chBus) sm := menu.NewServiceMenu(chMenu, chBus) app.AddService(sm.Name, chMenu) sa := article.NewServiceArticle(chArticle, chBus) app.AddService(sa.Name, chArticle) sc := calendar.NewServiceCalendar(chCalendar, chBus) app.AddService(sc.Name, chCalendar) hPage := app.Handler("./data/template.html"). ContentType("text/html; charset=UTF-8"). Service(tools.NewPart(sm.Name).Theme(the.Menu.Sitemap).Template("./data/sitemap.html")). Service(tools.NewPart(sa.Name).Theme(the.Article.Record).Template("./data/record.html")). Service(tools.NewPart(sc.Name).Theme(the.Calendar.Date).Template("./data/date.html")). StatusCodeOf(the.Article.Record) m := bxog.New() m.Add("/:id", hPage.Do) m.Start(":80") } 

Performance


As we have already learned, despite the fact that the application is compiled, MMOA, this is not the best solution for tasks where speed is the main and decisive factor, since in the process, the application services send messages to each other through the channels, which is natural is a brake. In order to at least understand about how productive MMOA is, purely for reference, I spent a simple ab testing a running example from the example folder. My computer issued the following spherical horse in a vacuum:


Below, the benchmark shows quite well that an application running only with the article service works much faster than with the menu , which sends a request to the article , waits for it, receives an answer and only then sends its answer to the aggregator. (Note: in parallel mode, the difference is somewhat reduced.)


What was / could be


If you wish, you can add priorities to the messages. By the way, initially they were, but I found their functionality premature. In addition to services, the handler can be “out”, having simultaneously got rid of the controller. I also tried this option, but decided that it’s better to the detriment of flexibility that everything lies inside and does not hurt the eyes. Handler is generally worth it to simplify and give him a splitter. There were other ideas, but sometimes you just want to stop.

Conclusion


Most likely in MMOA, many readers have something familiar: patterns, microservices, SOA, MQ, etc. This is good and I dare to assure you, MMOA does not pretend to overthrow or appropriate other people's laurels. This is only a tool whose ideas you might be interested in. From myself I will add only one IMHO - in many respects the MMOA is written under the influence of Golang, which I consider to be quite interesting and very suitable for developing a wide variety of applications, and many thanks to the authors of the language for their work.

Links


Github

Source: https://habr.com/ru/post/316692/


All Articles