[Edgex-devel] Coupling Between Microservices
Drasko DRASKOVIC <drasko@...>
On Fri, Oct 20, 2017 at 1:35 PM, Car, Boran
I think it's time for a Jim moment: "So what I'm hearing is..." etc... to bring some conclusions :).Jim is wisely waiting that we shoot all our bullets before ;).
Possibly around the line that it's not all black and white, but I'm not going to even try it - I'd probably be a bad replacement.Thanks Boran - both your and Tony's inputs are very useful!
I have been thinking over this problematic, and I am inclined to say
that much of the difficulty comes from the coupling of domains
themselves, not necessarily from the implementation. Actually, EdgeX
code somewhat resembles me as a monolith broken into different repos,
rather then independent set of microservices. And I think that much of
this impressions comes from the nature of these services - these are
not some distinct architectural blocks - like for example pub/sub
broker or database would be, or Redis kv store. When you have these
kind of services, independent and self-sufficient, with different
responsibilities and task in the system and different nature then it
is easy to see clear separations - each of them is run in a separate
container, etc, etc...
However, whole EdgeX system can logically run very well as a monolith
app, and even do we introduce some separation that seems visible -
like between layer that does the export services and the core layer -
still there is reuse of the logic and data - both of these layers work
on the same task practically and I think domain coupling comes from
Having in mind this observation, I am not against sharing data models
between these microservices (some minor stuff can be duplicated, but
bigger dependencies would probably fit well in shared libs).
However, this also brings me back to one of my previous topics - monorepo :).
As I mentioned, having shared libs probably is not so bad in this
case, but having data models scattered over different repos can be
confusing. Let's take a concrete eample: you have microservice A that
uses some class, and also service B that use the same class. Where
would you define this class - in repo A or repo B? Or will you create
new repo C to be a meta-repo and hold data models only, these data
models that are used in both A and B.
And this is exactly the approach that Export Services take - both
Export Client (https://github.com/edgexfoundry/export-client) and
Export Distro (https://github.com/edgexfoundry/export-distro) use
models that are because of this fact that both services share them put
in a separate repo called Export Domain
(https://github.com/edgexfoundry/export-domain). And this looks OK so
far - but the problem is that these Java classes in Export Domain
include some references and dependencies on classes defined in EdgeX
Core (https://github.com/edgexfoundry/core-domain), and this is where
the things get a bit ugly, because while so far we were staying in the
same Export layer we now start sharing cross-domain data. But as I
mentioned, I am starting to think that this is actually not even
cross-domain, as these divisions between domains (layers) seem to be
The approach I took to lower the impact of this problem is that I've
put both EdgeX Client and EdgeX distro in the same repo:
https://github.com/drasko/edgex-export. Naturally - EdgeX Domain is
there also. But the good part is that nothing is lost but this move to
a single repo - there is still strong division between code - Client
stuff live in the `client` dir
(https://github.com/drasko/edgex-export/tree/master/client) and distro
stuff in `distro` dir
files hold the shared structures that are used in both client and
Note that we still have two distinct microservices, completely
independent of each other, built independently and deployed
independently via different Dockerfiles. Elegance of Go just helps us
organize the code better.
Note also - and this is very important - that this code separation
allowed two companies - Mainflux and Cavium - to workd completely
independently on differerent services. Mainflux contributed client
part, while Cavium is working on distro. Having a simple repo actually
help us sync on the common files using PRs and Issues of this GitHub
repo for discussion - for example:
In my opinion this speeds up development process and assures higher
quality and integrity of code.
I proposed earlier that we evaluate actually putting all EdgeX Go code
in one single repo, using this model that I proposed in export
servcies and following the practices from Google
(https://www.youtube.com/watch?v=W71BTkUbdqE) or Uber
But if this is to much integration, we can at least group the layers
that we have today - have separate repos for export, core, supporing
services and device services - just 4 repos for whole EdgeX Go code. I
think that will diminish the impact of shared cross-domain data
models, as all services from the same repo can reuse data defined in
the top-level files of the repo.
My $0.2 and sorry for the longer mail again, could not make it shorter.
Mainflux Author and Technical Advisor
www.mainflux.com | Industrial IoT Cloud
Engineering Division | Paris, France