370 likes | 499 Views
Building Distributed Systems with Brazil (Project Firebird). Rob Englander President and Principal Engineer MindStream Software, Inc. rob@mindstrm.com www.mindstrm.com. O’Reilly Conference on Enterprise Java – Westin Hotel, Santa Clara, CA. Brazil Overview. Small, efficient HTTP stack
E N D
Building Distributed Systems with Brazil(Project Firebird) Rob Englander President and Principal Engineer MindStream Software, Inc. rob@mindstrm.com www.mindstrm.com O’Reilly Conference on Enterprise Java – Westin Hotel, Santa Clara, CA
Brazil Overview • Small, efficient HTTP stack • Extensible architecture using dynamically loaded Java classes • Conforms to existing standards and protocols • Uses familiar URL syntax for requests • Allows HTTP to be added to applications, rather than applications being added to an HTTP server. Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Moving Toward Services • Today content is king • Tomorrow services will reign • Major strategies and technologies include • Microsoft’s .NET • Sun’s ONE • SOAP, UDDI, WSDL • Applications will be aggregations of services from a wide distribution of providers Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Process Flow • There are many ways to organize processes • Individual, unrelated services • Chains of services, as is used by the Brazil Chain Handler • Process trees, where each node passes the flow to 0..n child nodes. • We use the tree, as it subsumes the others and provides an opportunity for parallelism Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Forming a Process Tree • Trees can be represented using a variety of programmatic data structures • this is the realm of software developers • Trees can be created in a visual, or graphical, environment • this is the realm of integrators Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Using Drawing Tools • A familiar paradigm • Maps easily to the • underlying structure • Usable by non-programmers • Rapid development Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Services • A service is a named function available on a given server • Services are responsible for performing some defined process, computation, etc. • Services are designed to fit into the context of a service processing tree Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Service Models, a.k.a Service Trees • Each node represents a service at a specified address • The model begins with a single root node • Child nodes may be processed in parallel, in no particular order • Child nodes are not aware of sibling nodes or the data resulting from sibling node processing Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Service Models, cont. • Results of processing a node are not returned until the results of all child nodes are obtained and included in the result • Each node in the model can point to a different address, or nodes can point to common addresses, or any combination Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Services Using Brazil • The service model requires a new set of Brazil handlers to: • Provide meta data to describe the Services available on a server • Process the Service Model Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Java Service Classes • Implemented in standard Java • Service names are mapped to Java classes resident on the server • Service mappings are defined in the Brazil server configuration file • Services are loaded dynamically Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
A Brazil Server Configuration File log=0 handler=serviceModel serviceModel.class=com.mindstream.firebird.serviceModelHandler Empty.class=com.mindstream.firebird.emptyServiceHandler Quote.class=com.mindstream.firebird.quoteServiceHandler News.class=com.mindstream.firebird.newsServiceHandler Analytic.class=com.mindstream.firebird.analyticServiceHandler Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
An Example Service Model Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
The Request URL • We’ll pass the stock symbol IBM • The request URL with the stock symbol and the tree is http://firebirdServer:8901/serviceModel&symbol=IBM&root=Empty& Empty.address=firebirdServer:8901&Empty.children=Quote,News& Quote.address=quotesRus.com:8901&Quote.children=Analytic& Analytic.address=www.cruncher.com&News.address=worldnews.com:8080 Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
The Service Model Handler • Puts the data to be processed into a Property list • Creates a tree of service nodes • Each node contains a service name, address, and list of child service nodes • Passes the data and the tree to an instance of a node processor class Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Model Handler code package com.mindstream.firebird; import sunlabs.brazil.server.*; import java.util.*; public class serviceModelHandler implements Handler { Server _server = null; public serviceModelHandler() { } public boolean init (Server server, String prefix) { _server = server; return true; } public boolean respond (Request request) { try { if (!request.url.equals("/serviceModel")) return false; Hashtable ht = (Hashtable)request.getQueryData(); Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Model Handler code // set up the result properties and put the symbol // into the collection Properties resultProps = new Properties(); resultProps.setProperty("symbol", (String)ht.get("symbol")); // build a process tree String name = (String)ht.get("root"); ProcessNode tree = BuildNode(name, ht); // now process the tree NodeProcessor np = new NodeProcessor(_server); np.process(tree, resultProps); request.sendResponse(BuildResponse(resultProps)); } catch (java.io.IOException e) { } return true; } } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Model Handler code public ProcessNode BuildNode(String name, Hashtable ht) { ProcessNode node = new ProcessNode(name); node._address = (String)ht.get(name + ".address"); Vector v = GetChildren(name, ht); int cnt = v.size(); for (int i = 0; i < cnt; i++) { node._children.add(BuildNode((String)v.elementAt(i), ht)); } return node; } public Vector GetChildren(String name, Hashtable ht) { String kids = (String)ht.get(name + ".children"); Vector v = new Vector(); if (kids != null) { StringTokenizer tk = new StringTokenizer(kids, ","); while (tk.hasMoreTokens()) { v.add(tk.nextToken()); } } return v; } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
The Node Processor • For local services • Loads an instance of the service class • Passes the data and the tree node to the service object for processing • Child node processing is invoked by the service itself via a method provided by a common service base class Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Node Processor Code package com.mindstream.firebird; import sunlabs.brazil.server.*; import java.util.*; import java.net.*; import java.io.*; public class NodeProcessor { Server _server = null; public NodeProcessor(Server server) { _server = server; } public void process(ProcessNode node, Properties props) { String serverName = (String)_server.props.get("serverName"); serverName += ":"; serverName += _server.listen.getLocalPort(); if (!serverName.equals(node._address)) { remoteCall(node, props); } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
The Node Processor, cont. • For remote services • Treats the current node as the root of a tree • Unpacks its tree and data into a URL • Uses the URL in an http request to the remote Brazil server Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Node Processor Code else { try { String className = (String)_server.props.get(node._name + ".class"); Class c = Class.forName(className); serviceHandler s = (serviceHandler)c.newInstance(); s.setServer(_server); s.service(node, props); } catch (Exception e) { } } } public void remoteCall(ProcessNode node, Properties props) { try { URL u = new URL("http://" + node._address + "/serviceModel"); HttpURLConnection c = (HttpURLConnection)u.openConnection(); c.setRequestMethod("POST"); Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Node Processor Code c.setDoInput(true); c.setDoOutput(true); c.setUseCaches(false); c.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); String request = ""; String delim = ""; Enumeration e = props.keys(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); String value = props.getProperty(name); request += delim + name + "=" + value; delim = "&"; } request += "&root=" + node._name; request = addTreeNode(request, node); DataOutputStream dos = new DataOutputStream(c.getOutputStream()); dos.writeBytes(request); dos.flush(); dos.close(); Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Node Processor Code props.load(c.getInputStream()); } catch (Exception e) { } } String addTreeNode(String request, ProcessNode node) { request += "&" + node._name + ".address=" + node._address; int cnt = node._children.size(); String children = ""; for (int i = 0; i < cnt; i++) { if (i > 0) children += ","; children += ((ProcessNode)node._children.elementAt(i))._name; } if (cnt > 0) request += "&" + node._name + ".children=" + children; for (int i = 0; i < cnt; i++) request = addTreeNode(request, (ProcessNode)node._children.elementAt(i)); return request; } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Service Processing • A Service is asked to perform its function by invoking its service() method call • When a Service completes its processing, it is responsible for invoking its child nodes Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Code package com.mindstream.firebird; import sunlabs.brazil.server.*; import java.util.*; public class quoteServiceHandler extends serviceHandler { public quoteServiceHandler() { } public void service(ProcessNode node, Properties props) { // perform quote processing here . . . // service any child nodes serviceChildren(node, props); } } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Child Node Processing • Provided by the serviceHandler base class • Each child node is processed on its own thread using a copy of the current state of the result data • When all child nodes are complete, the resulting data is aggregated and returned • Node processing is recursive; each node is visited using the same techniques as before Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Handler Base Class Code package com.mindstream.firebird; import sunlabs.brazil.server.*; import java.util.*; public abstract class serviceHandler { Server _server = null; Vector _childThreads = new Vector(); Vector _resultList = new Vector(); Object _monitor = new Object(); public abstract void service(ProcessNode node, Properties props); public void setServer(Server server) { _server = server; } public serviceHandler() { } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Handler Base Class Code public Object getMonitorObject() { return _monitor; } public void serviceChildren(ProcessNode node, Properties props) { int cnt = node._children.size(); if (cnt == 0) return; for (int i = 0; i < cnt; i++) { Properties p = (Properties)props.clone(); serviceThread st = new serviceThread(this, (ProcessNode)node._children.elementAt(i), p, _server); _childThreads.add(st); st.start(); } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Handler Base Class Code while (true) { if (_childThreads.size() == 0) break; try { synchronized (_monitor) { _monitor.wait(); } } catch (Exception e) { } } // collect the results from the children and incorporate int l = _resultList.size(); for (int i = 0; i < l; i++) { Properties pp = (Properties)_resultList.elementAt(i); Enumeration e = pp.keys(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); String value = pp.getProperty(name); props.setProperty(name, value); } } } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Handler Base Class Code public void childComplete(serviceThread c) { _childThreads.remove(c); _resultList.add(c.getResults()); synchronized (_monitor) { _monitor.notifyAll(); } } } class serviceThread extends Thread { serviceHandler _notifyTarget = null; ProcessNode _pnode = null; Properties _props = null; Server _server = null; Properties _results = null; public serviceThread(serviceHandler target, ProcessNode pnode, Properties props, Server server) { _notifyTarget = target; _pnode = pnode; _props = props; _server = server; } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Handler Base Class Code public Properties getResults() { return _results; } public void run() { NodeProcessor np = new NodeProcessor(_server); np.process(_pnode, _props); _results = _props; _notifyTarget.childComplete(this); } } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Returning the Results • When the entire tree has been processed, the initial call to the node processor returns to the main serviceModelHandler • The result data is packaged and sent back as the response to the initial request Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Some Service Model Handler code public String BuildResponse(Properties p) { StringBuffer res = new StringBuffer(); Enumeration e = p.propertyNames(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); String value = (String)p.getProperty(name); res.append(name + "=" + value + "\n"); } return res.toString(); } Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
An Interesting Alternative • The client application is itself a Brazil server • Client resident services are coupled with visual display elements, and data is displayed as part of the service processing • Other client resident services can be used to add functionality not otherwise available Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Integrating Other Technologies • The Brazil handler used for this model, as well as the services themselves, are free to employ any technology necessary to complete their processing • JDBC, EJB, XML, JMS, etc • This does not interfere in any way with the service model presented Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.
Summary • Brazil can serve as a solid foundation for providing a distributed services mechanism • The aggregation of services can be modeled as a processing tree • The development of applications can be aided by a visual environment for defining the processing tree • Emerging technologies such as SOAP, UDDI, WSDL, and XMLP may prove useful in building similar systems Building Distributed Systems with Brazil - Rob Englander, MindStream Software, Inc.