Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Microservices - 72 resources (arkency.com)
105 points by calineczka on July 6, 2014 | hide | past | favorite | 44 comments


One issue I have with this and similar architectures is that it often sticks an HTTP stack where it is not needed. The HTTP request/response paradigm does add a useful process management architecture, but it seems like you could implement that without the HTTP component, although then you would also need to figure out the inter-operability side of things if you wanted that flexibility to plugin into stuff. Which may lead you to wanting a protocol for making things easier.

Okay, I guess I do understand why the HTTP stack is wanted, but with HTTP/2 around the corner, it might be time to think about whether it makes sense to create a more primitive version of HTTP focused on non-networked or locally-networked applications


HTTP is great because it lets you use the same API in the browser. Given the right services, you can build your front end UI entirely based on your service APIs, no other back end needed.

If services used ZeroMQ or Thrift or similar, a browser front end would require an adapter layer. If you have 10+ services, that's a lot of redundant code.

Plus: You're leveraging a lot of great infrastructure. With HTTP APIs you can just curl into your APIs. Or load balance and proxy them with HAProxy, Nginx, Varnish etc.


Request/Reply pattern makes a poor choice for communication between services - it increases coupling. It doesn't matter much if it comes with HTTP or any other flavour.

Again, Jeppe nails it in very detailed post: http://www.tigerteam.dk/2014/microservices-its-not-only-the-...


I feel somewhat petty for this complaint as the content is good, but I found that link almost unreadable. It felt like someone awkwardly shouting random words in sentence, having every other word wrapped in <strong></strong>.

If anyone else finds this, here's a quick thing to paste into the developer console to make it more readable (the content is worth it):

    var jq = document.createElement('script');
    jq.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js";
    document.getElementsByTagName('head')[0].appendChild(jq);
    $("strong").each(function(i,e) {$(e).replaceWith($("<span>" + e.innerHTML + "</span>"))})


Just wanted to say I completely agree. The extremely heavy bolding is very distracting.


The post talks about synchronous communication increasing temporal coupling.

There's nothing in sending a request and getting a response that's increasing coupling in a traditional sense, and often there's no much of an alternative anyway, if you want donuts, you'll have to request donuts, and then receive donuts.

While I dislike shoving HTTP everywhere for many reasons (reminds me of XML abuse), HTTP is not synchronous, nor asynchronous. It's a protocol sent over a socket. Synchronicity is not the domain of HTTP at all. It's up to the application how it does it.

Additionally, the response can always be a blank acknowledgement of the received request. There are very few cases where you just want to go forward blindly without even receiving an ACK about your request at some level (or alternatively, an error), because sometimes things fail.


There seems to be quite a lot of work around this, eg the various protobuf-like solutions as astandard message, and various things like zerovm as transports. They havent quite been put together into an equivalent, but they are lightweight enough that its not clear this is needed.


Are people typically building their microservices infrastructure on top of a SQL database, or other datastores?

I'd be concerned not just about the overhead of managing lots of different (though simple) services, but also the fact that you give up a lot of convenient & useful features that you could get for free with a monolithic application, such as transactions. You either have to avoid needing transactions between microservices, or deal with the complexity of coordinating distributed transactions.

That seems like an awfully big hurdle to overcome for a new application, especially if you're a startup that needs to focus on delivering customer value as quickly as possible.


You have to design around such constraints.

You can emulate transactions to a certain extent by marking things are "incomplete" (which may result in things being invisible in some contexts) until they can be marked as complete across all services — an operation which cannot be atomic, but which can be "atomic enough" – or aborted. Versioning may be an option.

Sometimes you need "all or nothing" state management in a single microservice: You want to do "POST /object" multiple times and then cancel all of them on failure, for example. In one app we have a data import process which populates a microservice with a complex data model with many 1:n and n:m relationships. Instead of doing multiple REST calls (POST and so on), we build a "batch" object, which is essentially a JSON document. This batch lives in the microservice and acts like a persistent transaction. When we want to apply the changes, we tell the service to commit the batch. If the batch cannot be applied because it conflicts — ie., changes have been made by someone else since the batch started — the entire batch is dropped and the import starts from scratch. It's not terribly elegant or efficient, but it's fairly simple.


Transactions spanning several microservices violate their autonomy - one service should not lock resources of another.

Jeppe Cramon explains it pretty well in http://www.tigerteam.dk/2014/micro-services-its-not-only-the...


That's often not practical. Say you're a shop front.

If you have a goods purchase service and a goods delivery service, you want to reserve the good (limited quantity) and reserve a time slot for transport (limited number of deliveries a day) before you charge the customer, and make the "commit".

And if you'd merge two separate companies into one uber-service, you've just created more problems than you've solved.


Atomic transactions are one of several strategies for handling this problem, and not always the right answer.

Starbucks is a good analogy (http://www.eaipatterns.com/ramblings/18_starbucks.html). If Starbucks were transactional, you would have to stand there at with the money on the counter and wait until your drink was finished, then exchange at the exact same time. Even the mental image is ridiculous.

In practice, it makes much more sense to allow the system to enter certain inconsistent states and then remediate them. Out of an ingredient? Refund the money. Can't pay? Pull the drink out of the queue, or just write it off. This can involve some cost, but less cost than than the throughput you'd lose by enforcing consistency.

For your specific example of a goods delivery service, most take-out restaurants fly in the face of these claims: you can pay the driver in cash when they arrive. They are willing to accept the risk that you made your order fraudulently, won't pay, etc. because it's still better for them to have your business.

If you reserved a time-slot or inventory for someone whose credit card is declined, so what? Just un-reserve it. It's not hard to UPDATE a row in a database. The system was in an inconsistent state for 10 seconds. Big whoop. (You might have turned down a legitimate customer, but only if they were consuming the last resource, and if demand is that high, another customer will buy the item.)

Notice that Ticketmater and most airlines will hold your seats (i.e. leave the system in an inconsistent state) for up to 15 minutes while you enter your card details. Hell, Ticketmaster can easily reverse a transaction at any point up until the moment your ticket is scanned at the door. So could an airline, and they often do.

The classic example of account balances isn't necessarily the case either - banks can INSERT records of individual transactions. Since addition is commutative, race conditions are irrelevant. Balances are then calculated nightly offline by playing back the transaction records. I guess that's a form of locking, but even if it weren't, the balance isn't the source of truth - the transactions are, and the balance can be recomputed.

Banks also don't hide the complexities of transaction processing. Your "current balance" is different from your "available balance" and your most recent transactions show as pending anyway.

You don't need transactions as often as you think you do.


> "In practice, it makes much more sense to allow the system to enter certain inconsistent states and then remediate them. Out of an ingredient? Refund the money. Can't pay? Pull the drink out of the queue, or just write it off. This can involve some cost, but less cost than than the throughput you'd lose by enforcing consistency."

I don't know what practice you're referring to, but unlike commodity coffee drinks paid for in cash 1) CC refunds are not free, and they're not cheap in volume at all if you intend to do it casually during normal operation 2) not all goods are standardized and available in large quantities.

Your examples are all over the place. Ticketmaster is an example of a reservation system similar to one I was trying to give an example of (two step commit). A resource is locked, the lock is held for a short period while collecting answers from the other subsystems (in this case, payment gateway), and then a final commit is issued (or a rollback is issued).

Airline overselling isn't done because it was some microservice design dogma about how great inconsistent state is, but because every seat costs the airline a fortune if left empty, and a certain % of passengers cancel or reschedule their tickets, and the airline is trying to arrive at an airplane with as few empty seats as possible. Having your tickets canceled is certainly not something that happens "often", thank god, but it does happen as a result of that tradeoff.

But if I reserve and buy my seats online for a cinema movie, and then I go with company and get handed my money back because "it's practical", I'll make a scene. And so no one implements cinema ticket reservation this way.

For bank overdrafting, it's a very special case - your money is a number in a computer, and the bank owns that computer. They make the rules... so they did. It's easy to mess around with numbers like that. Bank account overdrafting is probably the biggest exception of them all as no physical products and services are involved. No one's going to have their lawn un-mowed because the bank allowed your account to overdraft.

The only common thing between your examples is that they're driven by business concerns, not some ivory tower concern about service design. And this is why they're so different, and reserving resources is and will remain a common practice for many, as long as the business logic calls for it. There's nothing wrong about it.


I apologize. For some reason I thought you were attacking the viability of microservice architecture because you can't do database-level transactions across several backends. You were arguing that services will sometimes need to lock each other, and I agree with that.

In the Ticketmaster example, I would be able to get a Ticket resource assigned to me before paying for it. But the ticket would be "locked" (in the sense that I couldn't print the barcode) until the Payments service marked it as okay, which would indeed be an example of one service locking another's resource.

I thought you were claiming that the action needed to be performed in a single database transaction, but you don't need or want isolation here. You want the world to observe inconsistent state in this case (i.e. no one sees my seat as "available" while I'm fumbling around with my credit card number). In which case it's perfectly practical to implement transactionality at the application layer, between microservices, rather than at the database level. But that point was never in contention. I apologize.

Obvviously there's not a dogmatic preference for inconsistent state, just an acknowledgement that ACID properties are not necessarily needed as often as some people think they are.

Also, obviously, you have to be careful with your failure modes. Charging someone without delivering shouldn't happen often but you don't need to design your entire infrastructure around making it impossible, given that refunds (and simply not capturing the charge you authorized) are both relatively easy to do, even if you want to avoid doing them all the time.


Well, as usual most arguments revolve around misunderstanding terms, and not substance, heh. I was too harsh in few places, as well. Sorry.

I really don't feel there's a need for us to separate "native" database transactions and app-level transactions. They're both implemented using the same underlying principles. But I've noticed people see a huge difference between them in blog posts, articles and conversations.

I think it reveals a kind of thinking that database transactions look like magic, while those we roll ourselves... we see all the ugly parts of the sausage factory there, and it no longer feels as "atomic" or magical as what databases expose as an encapsulated abstraction.


It seems to be that, roughly, if a service is doing joins on a datastore it might not be a microservice any more...


Yeah, that makes sense. It's not just joins, though. Consider the transactional nature of something like the signup process, where you want it to either succeed completely or fail completely.

If you're creating objects independently in multiple microservices during signup, and one of those fails, you've then got to deal with rolling back any changes that have already completed with other services.

Maybe traditional web applications just aren't a good use case for microservices?


Signup might not be a good case. Its a very occasional service with transactional issues, versus continuous high performance services (like authentication).


amazon.com is pretty traditional web application and they've been doing SOA for ages.


Right, but they also have their own internal Paxos service to manage distributed transactions, and they have thousands of engineers and thus can deal with the increased complexity.

As I said in my original comment:

> That seems like an awfully big hurdle to overcome for a new application, especially if you're a startup that needs to focus on delivering customer value as quickly as possible.

I'm really curious to hear if/how others are able to leverage the benefits of microservices yet avoid the perceived complexity that goes along with it.

Edit: I was reminded that Pat Helland (from Amazon) wrote a famous paper "Life Beyond Distributed Transactions" which gives some great guidelines on how to build an SOA that avoids reliance on distributed transactions: http://www-db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf

I still think this is clearly quite a bit more complex and harder to develop than i.e. a single Rails app, so I'm still very curious to hear when this approach starts making sense.


Service owns it's data. Other services can't access this data directly. Within service, on it's data, you can do as many "joins" as you want.


The point of a microservice is you can build it on anything, and change what you built it on over time, without changing its interface.

As for your concerns... you know how every time some good idea pops up people have to ruin it by pushing it to ridiculous extremes? Case in point, microservices.

You don't have to make things so modular that you give up SQL, transactions, or anything. With experience you'll naturally start finding where the domain of each microservice falls, and coordinating between them won't be a problem.

I strongly disagree with the poster who said that having joins means it's not a microservice anymore. That's non-sense. A microservice is defined by what it does, not how it does it.

Even the simplest service might be managing several entities that are in some kind of relationship. If the entities in one service are not in strong relationship with one another, it's a sign you can split them in two services. But if two microservices talk to each other so extensively, that the service boundary is becoming a bottleneck, it's a sign that they should be one service.

Do not break down a service into several services, just because it manages 2-3 entities. That's counterproductive, and it'll be the topic of DHH's upcoming blogpost "Why microservices suck" sometime in 2017.


> If the entities in one service are not in strong relationship with one another, it's a sign you can split them in two services. But if two microservices talk to each other so extensively, that the service boundary is becoming a bottleneck, it's a sign that they should be one service.

In other words it's best to break down services by Bounded Contexts.


What do people recommend for learning about SOA / microservices? I liked Patterns of Enterprise Application Architecture and Enterprise integration patterns, but didn't have a great experience with the SOA design with Rails book - it felt much to focused on very basic details (e.g., here is how you consume JSON).


The best advice I can think of is to build one. There really aren't any general rules. Everyone's needs (and languages/platforms/tools) and experiences are going to be different, which is great to learn from, but isn't going to present you with prescriptive advice.

However, since microservices are, by definition, small, building something basic is not complex or time-consuming. I'd suggest tackling something fundamental, such as user login and restricting service actions based on, say, a user's role.

This is all well-established stuff in web-based apps via sessions, etc., but presents a number of issues when using microservices. For example, you'll probably want some sort of token (for the user) and a way to manage it.

Going through those steps will get your brain ticking over about any number of problems and will provide you with much learning.

Since you are using Rails, I'd suggest creating a User service (one rails app) and a Blah service (another rails app) that requires authorisation to access some actions. Building that, and thinking through the issues, and building solutions, will give you a lot of feel for building microservices.

Rails (specifically v4 in API-mode, which avoids a lot of MVC stuff) is actually quite cool for microservices, where you can leverage its filters and gems to provide cross service functionality -- like the token handling I alluded to above.

(As an aside: if you do do the above, you'll probably find that you need some sort of "system/root" user access to some services. The "obvious" solution is to create such a user with super powers (that only the system can use). However, think through the implications of this -- massive potential security hole -- and other ways in which you can provide the required services. Actually, thinking about it, that might be a prescriptive rule: never create a super/root user -- that's not to say that a user can't have, say, an admin role.)


Thanks! I agree that just building something is a great way to get familiar with this stuff. I'm not looking for someone to say "this is how you build SOA" (which is probably why I found the rails book lacking) but rather "here is some complex challenge which I solved in this way, and here are the things we would have done differently in a re-write". Getting started with microservices is easy - there's probably more code to write in the deployment / testing / monitoring / logging plumbing than there is in your entire first service - but I'm sure there are subtle patterns that others have found that'd be good to know.


I have to echo the sibling comment: just build stuff. I worked on a startup (ended up failing for non-technical reasons, but that's beside the point) where the main application was in Rails, and we had about half a dozen microservices powering various other features.

I tried to find SOA-related literature but most of it was impenetrable, enterprise Java type stuff. So we just kinda made it up as we went along, splitting off any services that seemed like it'd work, and that went really well.


If I could recommend _just_one_ resource from that list, it would be http://www.tigerteam.dk/talks/IDDD-What-SOA-do-you-have-talk...


What is actually the difference between a "microservice" architecture, and a component based architecture?


This might help http://petritsch.co.at/download/SOA_vs_component_based.pdf

It seems like a distinction is between organization-wide, discoverable services (SOA -> microservices) and reusable components that may or may not communicate via a remote protocol.

EDIT - From reading more about component-based, another difference is that services are less tightly coupled. They often run on different machines & OS's, and are also often written in different languages. In the case of microservices, a common theme in these resources is that each microservice is owned by the part of the organization that created it, which is pretty interesting.


You can install a component and never upgrade it. You might fall behind on security concerns and be running different code from your counterparts but you can do that if you like.

If you consume some service, you're going to have to keep your app up-to-date should the service chage, go away, or fail. Therefore one could argue that services are easier to manage centrally at the expense of some overhead and less flexibility.


That doesn't sound like a primary difference between the two? You can certainly leave up an old service.


Yes, but that is not up to the consumer of the service (or not under the direct control of the consumer, in any case; assuming for the sake of argument that the consumer of the service is distinct from the producer)


I was expecting a list of 72 micro services, instead there are 72 articles on the subject. Feels like it's the opposite of "curated list" - a list everything.


Breaking down an application into micro services allows me to keep a clearer picture of the entire application and how it should work. Not to mention the advantage of evolving the services individually without affecting the entire system.

I've started a little library in Python for writing small services. It leverages nanomsg. link: https://github.com/walkr/nanoservice


Why have you chosen not to use HTTP and all the ease of use and interoperability advantages it confers?


Performance and simplicity would be two factors. Plus I think nanomsg doesn't play well with HTTP. And I'm saying this because I remember ZeroMQ didn't play well with HTTP also. nanomsg is a rewrite of ZeroMQ, so I might be wrong here.


Why do we need a new term for this? Isn't this just Unix philosophy applied to SaaS? No need to learn about "micro services" when you can learn about Unix/Linux and why it's built the way it is, then apply that knowledge to your SaaS product.


I agree with your sentiment. As an industry we spend way too much time rediscovering principles that are well known to previous generations of programmers. That said, I'm grateful to see these ideas showing up where they're desperately needed.


There are a couple of differences.

First, a key part of the Unix philosophy is the pipes. Programs do not really communicate without them. The closes thing I have seen in a microservice architecture is some magical bus, which is not easy to implement well, thanks to the fun of distributed systems: We don't spent time wondering if grep is going to get the data twice, or not at all, do we?

A second difference is that, in the unix world, we fully accept the concept of glue. Along with the reusable tools of the world, we have all the code that we know is not going to be reusable, that lets us do the task at hand. Depending on how hard it is, we might use something from bash to Perl. In a microservice architecture, such glue, if created, would be the actual logic of your application! So the moment you start adding glue, then the attention will quickly go to the glue, like the C gets pretty big in MVC.

Now, personally I am no believer in microservices as the panacea. The big advantage of the unix world is the reusable components. In a typical business application, the one we tend to get paid to do, how much code is actually stable enough, and reusable enough, that we really believe that its interface will last us a long time? In my experience, it's very little.

Where I have seen microservice-like architectures pull their weight is in actor systems, as a way to handle massive parallelism. But, just like many NoSQL implementations, they are solving a problem that many people would love to have, and very few people actually do. So we see startups building architectures in semi-exotic languages to handle hundreds of thousands of connections a second, when their actual volume of work could be handled with a boring Java app pointing to a Postgres database.


Because "the Unix philosophy" is a loaded term that generally leads to people arguing over exactly what it means every time it's brought up?


Reminds me about when the web finally realized that grids and ratios, common principles that print-related specialists have known and used for decades.

At least that case kept the same names, I think.


This is essentially what I ended up doing. I used to talk about an architecture where each component would be a standalone REST api and that together all these components would talk to each other to other standalone components with it's own REST api.

I'm really glad that there's a word for this, I bet in a few years we will see this become the new buzzword and see it in job requirements.

I really like the microservices architecture because it just feels efficient.


This article would be way better if each resource was in a separate blog post. :) #snark




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: