Microsoft Orleans – An approach to building distributed applications in .NET
dotnet.github.io
dotnet.github.io
If you can write a sentence "X are called Y", and X is more well-known, drop Y.
"You can then send messages to the grain by creating a proxy object, and calling the methods: var grain = GrainClient.GrainFactory.GetGrain<IMyGrain>("grain1"); await grain.SayHello("World");"
var brain = BrainClient.BrainFactory.GetBrain<IMyBrain>("brain1"); await brain.Say("WTF");
All C#/Java style static typing code not only looks like that, but often calls it "best practice."
Worth noting that "await" use is quite elegant in what it does here.
I'd been away from .NET/C# for a few years and came back to find that they dialed the abstraction level to 11.
I adore C# as a language but I find myself increasingly alienated by its generally accepted coding style.
I find that Microsoft's products have extremely unintuitive naming schemes at both a low level (language, standard libraries) and a high level (.NET product word salad naming schemes, Office 365 referring to a diverse and inconsistent range of products...).
The skeptic in me thinks that this may be an attempt at educational lock-in.
The lines between marketing and technology have definitely been blurred.
See also:
iTunes (OSX), iTunes (iOS), "Music" (iOS), Apple Music, iTunes Match, Genius and the iCloud Music tab. Podcasts and videos are also all in there somewhere, know what dear user, you figure it out k?
"Say, Steve, what have you been doing last year?" - "Welp, just making sure things work, fixed some bugs, documentation, took customer calls. The product essentially works, people love it". "Wait, so we haven't shipped any new features, hmm, ok...".
vs the response of "We implemented fizz, bar, quux features. We tore down old zig and added zag instead. It is really the same as old zig, but now look green and re-written with latest framework we saw in HN headlines". "Oh great, you get a promotion and a raise".
I am being a bit silly, but it is only half-joking, it is how software industry often works.
Let's break the problem down.
You have a language that doesn't natively support actors or message passing. You can solve this by having the developer stub each method (`this.DispatchActorMessage(...)`) or you can implement the interface on behalf of the developer (`Factory.CreateProxy<T>()`). Microsoft doesn't always use the runtime emit approach and, as someone who has used both approaches[1][2], runtime emit is far preferable. This means that something in your code has a responsibility to create actor proxies. That's the first concept: the responsibility to create actor proxies. Not only that, but so far as Reliable Actors go the proxy needs to do quite a bit of work: actors can be rescheduled to another machine and the proxy needs to continue representing that single durable instance.
You also have context: "which cluster controls this actor?" Depending on your scenario you might be able to assume that there is no context. Microsoft cannot make these assumptions because federation is quite important in the enterprise. In fact, the ability for Reliable Actors to have context [will] allow our customers to extend our product without us worrying about noisy neighbors (they are in charge of their own actor cluster, we simply federate to it). Additionally, there are scenarios where the consumption of an actor occurs outside of the context. For example: calling an actor from a GUI app.
In order to create the actor, you're going to have to use the object with that responsibility (unless you fancy doing the emit yourself): `ActorFactory.Create<IBrainActor>()`. You then need to pass in the context. Orleans uses a `Client` instance (which should make sense to .Net developers), while Reliable Actors pass the context into the `Create` method. So either: `Context.Factory.Create()` or `Factory.Create(Context)`. Nothing more than a stylistic choice necessitated by the requirements that Orleans and Reliable Actors don't share.
The goal here is not to replicate Erlang. It is to make a framework where developers can write distributed systems with a low amount of ceremony. Actors so happen to be the best candidate as a primitive but are most certainly not the be-all and end-all of Reliable Actors (which were inspired by Orleans, so I assume the goal is the same for Orleans). In that way, it makes some things far simpler than Erlang[3] but there's always a cost to that. If distributed systems is the primary goal, then you're going to have overhead if you are not creating a distributed system.
If you're talking about terrible naming, that outright I can agree with. Orleans, however, is no more and no less abstracted than it needs to be.
[1]: https://msdn.microsoft.com/en-us/library/system.diagnostics.... [2]: https://azure.microsoft.com/en-us/documentation/articles/ser... [3]: http://erlang.org/doc/reference_manual/distributed.html
I must confess that I sort of lumped several criticisms together there, conflating API nomenclature, with product nomenclature, with abstraction, as one tends to do when speaking semi-casually.
Not to mention that the standard OO cult of unit test / mock everything and make everything "reusable" leads to such shitty designs that almost fall out naturally from the language/paradigm. Oh and the one class per file with 3 method interfaces and 10 ceremony lines with namespaces and import definitions/braces.
I prefer C# over Java, and in some cases even over F# (it's slightly lover level and therefore it's simpler to control for things like heap allocation) but it usually is that verbose and crazy in the real world from my experience.
Not sure I'd call it a cult. From an F# perspective I do it this way:
* REPL-driven work to get it up and running
* Unit tests to protect what needs to be correct against change
* Mock the service boundaries
* Expose object-oriented layer to C#/VB consumers
Unit tests, mocking, and reusability are good things. Overuse (e.g., mocking to make sure that X calls Y in some business logic engine) is just what it is - overuse. Users of functional languages have their own problems, like suffering from code golf and over-using partial application. I wouldn't call one any worse than the other, it's just the functional crowd is smaller so you see it less.
I agree that both have their own issues but I do think one is better than the other, F# is more succinct (without turning in to code golf) and (actually) being multi paradigm avoids cases where OO just doesn't fit well. With micro services, actors, distributed computing, etc. those cases are expanding.
This is the bad coding style I'm talking about... C# is pretty great but it cant stop people from just writing more for no reason.
You're calling the global reference, asking it to give you a proxy to that object, and you need to mention somewhere in the line what type you expect. Without a stronger type system or a complete abandonment of type safety, the most you could do is shorten this by 1 term and move the type from the template term to the left (something has to assert the programmer expects IBrainStuff).
The only other way to do this is explicit code generation (ugh) or implicit code generation (e.g., F# type providers). Which is why in a sibling comment I mentioned I think that an F# binding to this library would be generally more acceptable for people who dislike that kind of abstraction, because the type system can do a lot more to help.
Erlang's model of actors and messages isn't "enterprisey" and this isn't "enterprisey" code, this is just "sufficiently complex OO code." If you like strongly typed OO languages, this style of coding is your nemesis and your hero at the same time.
Preferably, all established terms should be replaced by buzzword candidates.
e.g. javascript classes/inheritance/OOPs in general.
var grain = GrainClient.GrainFactory.
GetGrain<IMyGrain("grain1")
await grain.SayHello("World");
var brain = BrainClient.BrainFactory.
GetBrain<IMyBrain>("brain1");
await brain.Say("WTF");
Heh, Erlang: GrainPid ! "HelloWorld"
BrainPid ! "WTF"Otherwise it's just
await grain.SayHello("World");
grain1 ! "HelloWorld"
brain1 ! "WTF" do! GrainPid <! "HelloWorld"
via Orleankka F# https://github.com/OrleansContrib/Orleankka/blob/master/Sour...stilll a bit more verbose than erlang though
343 Industries famously used Orleans for Halo 4 backend services infrastructure. Caitie McCaffrey's presentation can be found here: https://www.infoq.com/presentations/halo-4-orleans
You may be interested in Obit ( https://github.com/orbit/orbit ). It is inspired and based on Orleans, except it's written in Java. Similar concepts and semantics. ( a BioWare project )
I'm not sure claims to Akka.NET's maturity hold water relative to Orleans. Akka proper has a lot of miles on it, but so does Orleans, and I'm not sure Akka.NET is as heavily tested and stressed as Orleans.
1. Orleans is very clean but highly opionated and this results in what I see as operational shortcomings, e.g. I prefer running discrete Windows services that I can start/shutdown to provide fault isolation and safe upgrades, but this doesn't seem to be directly supported in Orleans (the documentation speaks about "restrictive placement strategies" to ensure certain grains are located in certain silos, but I could never figure out how to achieve that, and it also seems against the design to have such a level of control). If it fits what you need, it's really a nice solution.
2. Akka.net's API is very messy and out-dated, in my opinion; I'll give some examples. You have to inherit from Akka.net classes, which makes me very nervous from a testing standpoint. Messages are untyped. There is no easy way to understand the interface (sequence of valid message flows) to an actor. This suggests maintenance will be tricky after some time away from the code unless you carefully design your actors (yes, arguably this could be said of any code). Documentation for fundamental topics is still incomplete in places (e.g. http://getakka.net/docs/working-with-actors/handling-message...). Persistence still confuses me after reading it 5 times. That all being said, it's a straightforward API clone of something that is proven and accommodating to the different development styles required for a broad range of back-end services.
In the actor model you often end up modeling state machines, and especially in the presence of asynchrony, it is impossible to meaningfully add types to such state machines. Because you see, the full set of messages that an actor recognizes at some point is much less interesting than the set of messages an actor accepts right now.
Another problem is that actors often communicate with multiple other actors at the same time, possibly aggregating data from multiple sources, outputting data on multiple channels. Thus a single actor can expose different APIs, depending on whom it is taking to.
And yet another problem is that often actors act as proxies or supervisors, simply forwarding messages around.
Basically people complaining about the untyped nature of actors are terribly misunderstanding the actor model. Or distributed systems.
How do classes make you nervous? Testing support is one of the strongest parts of akka (see Akka.TestKit) - you can even simulate things like networks delays or VM shutdowns.
> Persistence still confuses me after reading it 5 times.
Yes for people not familiar with concepts of eventsourcing, Akka.Persistence can be enigmatic indeed. But you're not forced to do eventsourcing when using Akka.
These questions add nothing to the conversation beyond a veiled promotion of someone's pet technology
Whenever you're seeing a new technology that seems to do the same thing as a pre-existing technology, I think it's perfectly sane and reasonable to ask, "What does $NEW_THING do differently from $THING_I_ALREADY_USE?" For starters, it lets you get up to speed on its merits much more quickly. You only need to go over the memetic equivalent of a patch file rather than having to read the entire spec.
Ooohh i love this sentence ;)
And yes - it is only sane and reasonable to ask.. but should be mandatory !!
MBrace supports F# and C# and is designed to work well in interactive scripting scenarios, which lets you develop scalable systems gradually using REPL. I think it is complementary to Orleans/Akka.Net, so it is worth knowing it exists!
http://christophermeiklejohn.com/papers/2015/05/03/orleans.h...
[1]https://github.com/quozd/awesome-dotnet https://www.microsoft.com/en-us/research/project/orleans-vir...
Service Fabric is a confusing beast. It includes a Virtual Actor runtime which is indeed very heavily inspired from Orleans, but it is a reimplementation. Orleans is built for "cloud" scenarios. You can run Orleans on top of Service Fabric using a host I wrote: https://github.com/OrleansContrib/OrleansFabricSilo
They do go into that in the research paper [1].
"Actor platforms such as Erlang [3] and Akka [2] are a step forward in simplifying distributed system programming. However, they still burden developers with many distributed system complexities because of the relatively low level of provided abstractions and system services. The key challenges are the need to manage the lifecycle of actors in the application code and deal with inherent distributed races, the responsibility to handl e failures and recovery of actors , the placement of actors, and thus distributed resource management. To build a correct solution to such problems in the application, the developer must be a distributed systems expert. To avoid these complexities, we built the Orleans programming model and runtime, which raises the level of the actor abstraction."
It's an interesting question how hard it would be to offer such a often-good-enough option in Akka for the cases when you don't have the need or the time or the team to develop a custom distributed computing model.
Edit: maybe Lagom is meant to fit that space. I think it's wider in scope than 'easy actors' though.
https://github.com/akka/akka-meta/blob/master/ComparisonWith...
Shameless plug: I wrote about this in chapter ten of my recent book (https://www.packtpub.com/packtlib/book/Application%20Develop...). You'll need to have bought it for that chapter, but the first one is free.
https://azure.microsoft.com/en-us/services/service-fabric/
It's really slick. Persistent distributed .Net collections. Actor model support.
https://channel9.msdn.com/Events/Build/2015/3-618 Service Fabric stuff starts at ~38 minutes in...
https://channel9.msdn.com/Events/Build/2016/KEY02 Scott Hanslemann demos its use for a game called Age of Ascent? (Something like that.)
In addition to being in production use in Azure for several years it also runs on Linux.
Still, the name makes searching for help and information difficult.
http://hanselminutes.com/536/exploring-the-orleans-distribut...