Thursday, May 22, 2008

Cloud Computing

Here's a rough breakdown of what cloud computing is all about:

1. SaaS (Software-as-a-Service)
This type of cloud computing delivers a single application through the browser to thousands of customers using a multitenant architecture. On the customer side, it means no upfront investment in servers or software licensing; on the provider side, with just one app to maintain, costs are low compared to conventional hosting. Salesforce.com is by far the best-known example among enterprise applications, but SaaS is also common for HR apps and has even worked its way up the food chain to ERP, with players such as Workday. And who could have predicted the sudden rise of SaaS "desktop" applications, such as Google Apps and Zoho Office?

2. Utility computing
The idea is not new, but this form of cloud computing is getting new life from Amazon.com, Sun, IBM, and others who now offer storage and virtual servers that IT can access on demand. Early enterprise adopters mainly use utility computing for supplemental, non-mission-critical needs, but one day, they may replace parts of the datacenter. Other providers offer solutions that help IT create virtual datacenters from commodity servers, such as 3Tera's AppLogic and Cohesive Flexible Technologies' Elastic Server on Demand. Liquid Computing's LiquidQ offers similar capabilities, enabling IT to stitch together memory, I/O, storage, and computational capacity as a virtualized resource pool available over the network.

3. Web services in the cloud
Closely related to SaaS, Web service providers offer APIs that enable developers to exploit functionality over the Internet, rather than delivering full-blown applications. They range from providers offering discrete business services -- such as Strike Iron and Xignite -- to the full range of APIs offered by Google Maps, ADP payroll processing, the U.S. Postal Service, Bloomberg, and even conventional credit card processing services.

4. Platform as a service
Another SaaS variation, this form of cloud computing delivers development environments as a service. You build your own applications that run on the provider's infrastructure and are delivered to your users via the Internet from the provider's servers. Like Legos, these services are constrained by the vendor's design and capabilities, so you don't get complete freedom, but you do get predictability and pre-integration. Prime examples include Salesforce.com's Force.com, Coghead and the new Google App Engine. For extremely lightweight development, cloud-based mashup platforms abound, such as Yahoo Pipes or Dapper.net.

5. MSP (managed service providers)
One of the oldest forms of cloud computing, a managed service is basically an application exposed to IT rather than to end-users, such as a virus scanning service for e-mail or an application monitoring service (which Mercury, among others, provides). Managed security services delivered by SecureWorks, IBM, and Verizon fall into this category, as do such cloud-based anti-spam services as Postini, recently acquired by Google. Other offerings include desktop management services, such as those offered by CenterBeam or Everdream.

6. Service commerce platforms
A hybrid of SaaS and MSP, this cloud computing service offers a service hub that users interact with. They're most common in trading environments, such as expense management systems that allow users to order travel or secretarial services from a common platform that then coordinates the service delivery and pricing within the specifications set by the user. Think of it as an automated service bureau. Well-known examples include Rearden Commerce and Ariba.

7. Internet integration
The integration of cloud-based services is in its early days. OpSource, which mainly concerns itself with serving SaaS providers, recently introduced the OpSource Services Bus, which employs in-the-cloud integration technology from a little startup called Boomi. SaaS provider Workday recently acquired another player in this space, CapeClear, an ESB (enterprise service bus) provider that was edging toward b-to-b integration. Way ahead of its time, Grand Central -- which wanted to be a universal "bus in the cloud" to connect SaaS providers and provide integrated solutions to customers -- flamed out in 2005.

Thursday, May 15, 2008

Reference Objects and Garbage Collection

Unreachable objects (outside the strongly and weakly reachable areas) are not reachable from the root set.

Strongly reachable objects (inside the strongly reachable area to the lower left) are reachable through at least one path that does not go through a reference object.

Weakly reachable objects (inside the weakly reachable area shown enclosed with a dashed line to the upper-right) are not strongly reachable through any path, but reachable through at least one path that goes through a weak reference.

Weakly reachable objects are finalized some time after their weak references have been cleared. The only real difference between a soft reference and a weak reference is that the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.

Java API Package: java.lang.ref.*

Monday, March 24, 2008

JDB Example: Generating a Thread Dump

Every once in a while I run into a situation where the usual means for generating a thread dump (stack trace) does not work, making it difficult to track down pesky deadlocks. This seems somewhat more common under OSX, but I’ve seen it happen under Linux as well.

Typically you can type Control-&backslash; (Control-Break on Windows), or send a process the QUIT signal (e.g., kill -QUIT ) to dump a trace of all active threads in the Java VM. Intermittently, however, I have found that this does not work for java processes that are launched via a shell script. The Control-&backslash; is sometimes simply ignored, while the QUIT signal appears to kill the script, but without dumping a stack trace or killing the java process. (This suggests that in either case, the script is probably just intercepting the signal. There’s probably a fix for that, but I haven’t explored it.)

The jdb debugger utility, included as part of the JDK, provides an alternate way to get a stack trace. First, you must pass two additional arguments to the java vm to tell it to listen for connections from the java debugger. On OSX, Linux, or UNIX, this looks like:

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n class 

This will cause the VM to listen for debugger connections on port 8000. You may use any usued port number that the account in which the program is running may listen. For non-priviledged accounts, this typically means any port number over 1024. For security reasons you might not want to include these options on a production system, but for testing and debugging they impose no measurable performance penalty.

As an example, here is a simple DeadlockDemo class that will produce a deadlock at some indeterminate point. It creates three threads, each of which will repeatedly try to randomly acquire two locks. When a thread successfully gets both locks, it will update a counter. Eventually two threads will try to acquire the same two locks in the opposite order, resulting in a deadlock. Deadlock situations are, of couse, not the only cases where stack traces are useful, but are probably the most common:

import java.awt.*;
import javax.swing.*;

/**
* Demo program that should (eventually) produce a deadlock
*/
public class DeadlockDemo extends JFrame implements Runnable {
/**
* Label with counter of iterations before deadlock
*/
private JLabel text = null;

/**
* Counter of number of updates
*/
private int count = 0;

/**
* Set of objects to randomly synchronize on
*/
private Object[] locks = null;

public DeadlockDemo() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
text = new JLabel("Starting up...", JLabel.CENTER);
setLayout(new BorderLayout());
add(text, BorderLayout.CENTER);

locks = new Object[] { new Object(), new Object(), new Object() };
}

public void startSomeThreads() {
for (int i = 0; i < 3; i++) {
Thread runner = new Thread(this);
runner.setName("Runner Thread " + i);
runner.start();
}
}

public void run() {
while (true) {
// Pick two locks at random to synchronize on. Eventually
// two threads will try to acquire the same two locks in
// the opposite order, resulting in a deadlock.
synchronized(locks[(int) (Math.random() * locks.length)]) {
synchronized(locks[(int) (Math.random() * locks.length)]) {
count++;
synchronized(text) {
text.setText("Counter: " + count);
}
}
}
}
}

public static void main(String[] args) {
DeadlockDemo demo = new DeadlockDemo();
demo.setSize(200, 200);
demo.setVisible(true);
demo.startSomeThreads();
}
}


Figure 1. DeadlockDemo, a program that (eventually) deadlocks.

You can run this class from the command line thusly:

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n DeadlockDemo

To get a thread dump, you first need to attach the debugger. In another terminal window, type:

jdb -attach 8000

Note that the port number (8000, in this example) must match the port number that you provided when you launched the virtual machine. You will see:

Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
>

At the jdb prompt, enter “suspend” to temporarily suspend all running threads in the VM. Your program will become unresponsive after you do this. Next, enter “where all” to generate the thread dump. Here is a complete example:

Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
> suspend
All threads suspended.
> where all
DestroyJavaVM:
Runner Thread 2:
[1] DeadlockDemo.run (DeadlockDemo.java:47)
[2] java.lang.Thread.run (Thread.java:613)
Runner Thread 1:
[1] DeadlockDemo.run (DeadlockDemo.java:47)
[2] java.lang.Thread.run (Thread.java:613)
Runner Thread 0:
[1] DeadlockDemo.run (DeadlockDemo.java:47)
[2] java.lang.Thread.run (Thread.java:613)
AWT-EventQueue-0:
[1] java.lang.Object.wait (native method)
[2] java.lang.Object.wait (Object.java:474)
[3] java.awt.EventQueue.getNextEvent (EventQueue.java:345)
[4] java.awt.EventDispatchThread.pumpOneEventForHierarchy (EventDispatchThread.java:216)
[5] java.awt.EventDispatchThread.pumpEventsForHierarchy (EventDispatchThread.java:190)
[6] java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:184)
[7] java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:176)
[8] java.awt.EventDispatchThread.run (EventDispatchThread.java:110)
Java2D Disposer:
[1] java.lang.Object.wait (native method)
[2] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116)
[3] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132)
[4] sun.java2d.Disposer.run (Disposer.java:123)
[5] java.lang.Thread.run (Thread.java:613)
AWT-Shutdown:
[1] java.lang.Object.wait (native method)
[2] java.lang.Object.wait (Object.java:474)
[3] sun.awt.AWTAutoShutdown.run (AWTAutoShutdown.java:259)
[4] java.lang.Thread.run (Thread.java:613)
AWT-AppKit:
Signal Dispatcher:
Finalizer:
[1] java.lang.Object.wait (native method)
[2] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116)
[3] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132)
[4] java.lang.ref.Finalizer$FinalizerThread.run (Finalizer.java:159)
Reference Handler:
[1] java.lang.Object.wait (native method)
[2] java.lang.Object.wait (Object.java:474)
[3] java.lang.ref.Reference$ReferenceHandler.run (Reference.java:116)


Figure 2. A stack trace produced within jdb.

Here we see that our three “Runner Thread n” threads are all stuck at line 47 in the run method, each waiting for a lock that one of its siblings is holding. The user interface is not blocked, as the event dispatch thread (”AWT-EventQueue-0“) is waiting for another input event. The other threads are handling various background tasks in the VM.

To exit jdb, type “quit“. Your program, with the exception of any deadlocked threads, will become responsive again. If you do not wish to exit out of jdb, you can type “resume” instead of “quit” to undo the effects of “suspend“. Note that you can only generate a thread dump when threads are suspended.

Windows

On Windows, a slightly different mechanism is used for communication between the Java virtual machine and JDB. Rather than specifying a port for the connection, you tell the VM to use shared memory. Here’s what the command would look like for the DeadlockDemo example on Windows:

java -Xdebug -Xrunjdwp:transport=dt_shmem,server=y,suspend=n DeadlockDemo

To connect jdb to the virtual machine, enter:

jdb -attach jdbconn

Once connected, the commands used within jdb (suspend, where all, and quit) are the same as on OSX and Linux.

Another Alternative:

On Windows the 'standard', ie. default, connector uses the shared memory transport.

To connect to a socket, you need to tell jdb to use the socket attaching connector, ie

jdb -connect com.sun.jdi.SocketAttach:port=9000

It is hard to remember the names and params of all the connectors. You can do
jdb -listconnectors

Thursday, March 13, 2008

Comments from Grady Booch on SOA

Grady Booch, a father of UML and now an IBM fellow, made this comment about SOA in his blog in March 2006:

"My take on the whole SOA scene is a bit edgier than most that I’ve seen. Too much of the press about SOA makes it look like it’s the best thing since punched cards. SOA will apparently not only transform your organization and make you more agile and innovative, but your teenagers will start talking to you and you’ll become a better lover. Or a better shot if your name happens to be Dick. Furthermore, if you follow many of these pitches, it appears that you can do so with hardly any pain: just scrape your existing assets, plant services here, there, and younder [sic], wire them together and suddenly you’ll be virtualized, automatized, and servicized.

What rubbish."

Booch is right. The important thing is that SOA is a strategy that requires time and effort. SOA is a multi-year journey. You need some experience to understand what SOA really is about, and where and how it helps.

And, in IT, each system is different. As a consequence, you will have to build your specific SOA—you can’t buy it. To craft it, you’ll need time and an incremental and iterative approach.

进化论与SOA

"It is not the strongest of the species that survive, nor the most intelligent, but the ones most responsive to change."

The key is flexibility. SOA makes enterprises more responsive to changes.

SOA Design Fundamentals

  • A design principle is an accepted design guideline or practice that, when applied, results in the realization of specific design characteristics.
  • A design paradigm represents a set of complementary design principles that are collectively applied in support of common goals.
  • A design pattern identifies a common problem and provides a recommended solution.
  • A design standard is a convention internal and specific to an enterprise that may or may not be derived from a design principle or pattern.

Wednesday, March 12, 2008

Lessons Learned in SOA

  • Start Governance early: SOA Integration and SOA Governance need to work together to give you the benefits of agility, cost-reduction, and reduced risk.
  • Don't do SOA in an IT vacuum: With SOA and BPM ensure that business processes are optimized to realize the benefit of SOA for the entire organization.
  • Start small, but think holistically: Small projects are a great starting point, but services quickly develop into composite services. These composite services need to be managed, designed, and deployed centrally, as well as, work together with the SOA Integration solution.