|
June 2007
June 30, 2007
Grid computing and SOA
For a great description of what grid computing really is, read this.
What they say about the connection to SOA, though, requires some clarification. Here's the quote:
There is a lot of talk going on about synergy between Grid Computing and SOA. It is however driven primarily by implementation concerns at this point rather than by any deeper considerations. Clearly, Grid Computing can deliver unchanged value without SOA, yet WS-* based implementation (such as Globus) can be beneficial in some cases (highly distributed heterogeneous environments that should only exist in unfortunate legacy-support situations).
The main thing that I want to call out is that "grids" don't cross service boundaries - not at the logical level anyway. Although, even if you did share a single grid infrastructure between services implementations, you may have some problems maintaining service-level agreements, autonomy may be put in danger.
Just something to keep in mind.
Posted by Udi Dahan at 11:38 AM Permalink
|
June 22, 2007
Testing services the hard way with WCF
I just read the kind of hoops you have to go through in order to test your WCF service implementations. Oh. My. GOD.
If that's the best there is, NOBODY is going to be testing their WCF services. That's scary.
When using this message-based design, your service implementations tend to look like this:
public class WorkflowMessageHandler : IMessageHandler
{
public void Handle(Stage1Msg msg)
{
using (IDBScope scope = this.DbServices.GetScope(TransactionOption.On))
{
IWorkflow wf = this.DbServices.Get(msg.WorkFlowID);
wf.Handle(msg);
scope.Complete();
}
}
}
And it's this easy to test them:
[TestMethod]
public void TestWorkflowMessageHandler()
{
WorkflowMessageHandler handler = new WorkflowMessageHandler();
handler.Bus = this.MockBus;
// set up expectations on bus in terms of messages returned
Stage1Msg msg = new Stage1Msg();
// fill msg with data
handler.Handle(msg);
// verify expectations on bus
}
That's right, it's just plain old unit testing the way we test everything else these days.
I'm beginning to get the impression that the new suite of technologies that is coming out of Microsoft is making things more complicated than they need to be.
Well, maybe that's just me.
Posted by Udi Dahan at 08:50 AM Permalink
|
June 19, 2007
Service-Enabled Workflows with WF and WCF
I’ve looked over the example Guy put up in his blog on how to interact with external services from a workflow, and tried it out using asynchronous APIs with WCF. This is done quite simply by having our service accept an object as a parameter that it can call methods on (which has availability issues, but whatever). The object that we pass in is quite simply a reference to our own service. Anyway, I haven’t been able to get the SendActivity in WF to work with it. Bummer. I guess I’m "stuck" doing things the "old fashioned" way. Check out the full ESB API as well.
By having messages dealing with workflow contain the ID of the specific instance they refer to, we can do simple message to workflow mapping. When a message handler receives a message containing a workflow ID, it just goes to the workflow store and retrieves the object by its ID. Finally, it calls the Handle method on that object, and I’m done. Workflow classes are just state machines whose triggers are the arrival of a message.
Here’s some example code so you can see how simple it really is:
public class WorkflowMessageHandler : IMessageHandler<Stage1Msg>
{
public void Handle(Stage1Msg msg)
{
using (IDBScope scope = this.DbServices.GetScope(TransactionOption.On))
{
IWorkflow wf = this.DbServices.Get(msg.WorkFlowID);
wf.Handle(msg);
scope.Complete();
}
}
}
You can see how easy it would be to take this and make it generic. Just define an IWorkflowMessage that inherits from IMessage and has a single property - WorkFlowID. Then we could have a BaseWorkflowMessageHandler<T> which would inherit from IMessageHandler<T> where T : IWorkflowMessage.
After that, it would be enough to have a class inherit from the base for a specific message and you'd be done, just like this:
public class Stage1Message : IWorkflowMessage { // WorkFlowID and other data };
public class WorkflowMessageHandler : BaseWorkflowMessageHandler<Stage1Msg> {}
I could even automate the creation of these message handlers given the set of messages that correspond to a workflow. I could then create all sorts of sexy designers on top of that.
But, seeing as there's so little extra code to get long-running workflows to work with "asynchronous services", I don't think I'll bother. I mean, why do I even need a "SendActivity"? It's just a simple little call:
this.Bus.Send(msg);
It appears that clean designs don't leave much to be draggy-dropped. Oh well. Your mileage may vary.
Posted by Udi Dahan at 06:20 PM Permalink
|
June 02, 2007
Tasks and Spaces versus Messages and Handlers
While going through the JavaSpace presentation I found on Owen Taylor's blog, I kept saying to myself, "well, I can do that without a space", until I got to one part of it.
The ability to introduce a new task at runtime without restarting any servers, and have new clients be able to send those tasks, and existing servers perform them. I never did that before.
This is very important when you've already got a system running and you want to expand on it. I think that this covers at least half of all the software work being done on the planet.
The interesting thing is that this ability comes in two parts - one design, the other technology.
In terms of design, in order for existing servers to be able to do the work of the new task without any kind of restart, we need the code for performing the work of the task to reside in the task itself, possibly in some kind of "execute" method. The server would simply take a task out of the "queue" of pending tasks and call that execute method.
Now, those of us trying to do this with Microsoft technology know that if the assembly containing the code for that task was not available on that machine, this wouldn't work. Technologically speaking, we'd receive some kind of deserialization exception that resulted from a TypeNotFoundException. In other words, in order to support the new task, we'd need to "install" all of its participating assemblies on all our servers.
For those of us who know and use Jini with Java, we get this behavior automatically - the bytecode of the task is downloaded automatically. This is an advantage in terms of operations, but I'm not an operations guy so I can't say how huge this really is.
The interesting thing for me in this design is that it's somewhat different from the messaging paradigm I've been so successful with. Here we don't use messages as simple Data Transfer Objects. Tasks contain both data and behavior. This behavior used to belong to message handlers. I like having separate message handlers, it enables me to create very flexible pipelines.
Here's how I'd trade it off. When using Jini, the tasks style gives me zero footprint deployment. When using .NET, if I'm already installing things on my existing servers, I can deploy new messages and handlers just as well as the task assemblies. The problem is that I'd need some way for the server to pick up on the new handlers - a background thread scanning the deployment directory, or the FileSystemWatcher (given the fact that it sometimes misses things).
Well, it looks like both design styles are feasible on both platforms. The ability to have code download automatically on the Java platform is a plus that is most felt when using tasks.
Bottom line so far, there's a lot to learn from JavaSpaces, and even if you don't use Java, Jini, or Space technologies (like this), the design patterns employed there are extremely valuable.
Posted by Udi Dahan at 04:05 AM Permalink
|
|