I really like this model and explanation and wonder just how soon we
can make it a reality.
Last fall I thought we needed the ability to add gbeans to running
configurations so you could add datasources, queues, etc to the server
while you were getting ready to deploy an app, using an admin console
(in fact an earlier version of the one just donated by IBM).
However, I think there's a better way to do this, namely, instead of
adding bits to the app server to make the environment ready for the
app, add bits of app server to the application so it brings what it
needs along with itself. Right now we can do this with plain gbeans
in all components (such as for security, corba, and web connectors),
and resource adapters in app clients. I'm planning the ability to add
at least entire resource adapter configurations into other module
types, and considering adding the ability to deploy additional complete
j2ee modules just using the vendor plan.
I can imagine a bit of a ui that analyzes the configurations present in
a server (i.e. a bunch of deployed configurations) and your application
and shows you what is unresolved in the application, and guides you
through either adding more prebuild configs to your server or adding
additional stuff into your application so everything is pre-resolved
before you try to deploy for the first time.
I think with this point of view and possibly with such tools most of
the need to add gbeans to running configurations goes away. As for the
question of changing and saving gbean attributes in a running
configuration, I'm not sure what to think. It seems like an
interpreted vs compiled language debate. Right now our "compiler" is
decidedly inconvenient for a rapid change cycle: I'm not sure how much
faster it would need to get before it seemed like a more reasonable
alternative to live changes.
thanks
david jencks
On Jul 25, 2005, at 7:09 PM, Jeremy Boynes wrote:
I'd ask you to set aside traditional thinking and try this out for a
bit.
When you write code, you edit a couple of source files, compile it,
fix the typos, build a jar, test it, decide its good enough and commit
the change. After doing this a few times you decide its good enough
and do a release, taking the jar file you built and saving for
posterity. You then do it all over again.
If you're doing this with Maven, it spells out the difference between
the jar you are working with (a SNAPSHOT) and the jar you release
(something with a version number).
Sound familiar?
In a large production environment you do the same kind of thing with
system configurations. You set up a system the way you want, check
that it works, beat the snot out of it (aka stress testing or
benchmarking), see how/when it falls over, tweak the config and repeat
until it you're happy, then document it, have someone else try the
change in your staging environment, check it still works, then beg the
change control board to let you move it to production at 3AM on a
Sunday morning. You then cross your fingers and hope it really works.
A bit different from changing things on a desktop machine or the box
that runs the family website, but not unrealistic and the problem the
architecture was trying to simplify.
[[ to avoid a disgression, is Geronimo ready for this? Who knows; in
the end the people doing such things factor in the risks associated
with any software no matter how mature and they will make up their own
minds ]]
The idea behind the configuration bundles is that they are pre-wired
sets of closely coupled components that co-ordinate to perform a
specific task. A single bundle is *not* meant to represent the entire
system assembly - the current o/a/g/Server is an abberation caused by
problems in the classloader model (described elsewhere) not example of
"best practice."
The purpose of a bundle is to allow a knowledgable person to, for
example, pre-wire a web container in a way that allows other people to
use it just by defining a few characteristics. So, for example,
someone can go to a repository and find, for example, a pre-wired
version of a Jetty bundle pre-configured for 100 concurrent users at
95% static content with a typical dynamic reponse time of 500ms when
running on an Acme-4000 Linux machine.
So why does this need to be immutable? Because if you are pulling
these things from a catalog then you need to know that you're going to
get what you expect and not some version that someone happened to
tweak but just forgot to change the name.
It would be like having several jar files out there called
log4j-1.2.8.jar that were actually different - a recipe for chaos. BTW
one reason bundles are JAR files is because it's dead easy to sign
them so that you can tell if they have been tweaked.
Now, just as in the code development example I gave at the top, these
kind of pre-packaged bundles are also going to go through a
development process. One reason we didn't version stamp the configIds
in the current assembly is that until now all our configurations have
really been in development and it didn't make sense to be dealing with
new versions all the time. It probably would have been clearer to id
them as e.g. o/a/g/Server/1.0-SNAPSHOT but I guess that's water under
the bridge now.
So, in an ideal world, your user below would just pick a suitable
pre-built bundle out of some repo and be happy with what it does. If
it doesn't quite do what they want or nothing suitable can be found,
they start by building and tweaking my/web/Container/1.0-SNAPSHOT,
iterate it a few times and then finalize on my/web/Container/1.0.
The problem is identical to a developer not filling up their Maven
repo with trivially different versions of a jar they are working on
(which is why Maven has SNAPSHOTs in the first place).
To pick a bad analogy, we're trying to do with server configuration
what Maven did for builds. No, I don't mean trying to make it slow and
take forever to start. We're trying to simplify the administration
process by allowing a admin to choose from a re-usable set of
pre-optimized bundles rather than having to do it all by hand, in the
same way Maven uses plugins to replace manually created ant scripts.
It's different. It's unusual. It takes some getting used to.
But it might just work.
--
Jeremy
Aaron Mulder wrote:
For my part, I'm not convinced that it makes sense for
configurations to be immutable. I think the export/import feature
would be nice -- "I finally got my web container configured 'just
right', now let me export it and load it into my cluster of 30
boxes". I wouldn't even mind giving each configuration a unique hash
or something such that we could eventually down the road add a
feature where you export two related configurations, and one refers
to that specific build of the other. Or even having an immutable
flag on a configuration such that once you've marked one as immutable
it refuses to change in the future.
But to tell me that properties of a configuration shouldn't ever
be changed, or that GBeans shouldn't be added or removed at runtime
and we
should create new child configurations instead... unless I'm
misunderstanding you, that just doesn't work for me. I can't imagine
someone customizing their web container and then after a few revs
they try
to load or unload or export it and discover that they now have
configurations "Server", "Server HTTP v1..v5" "Server HTTPS v1..v3"
"Server AJP v1 & v2" "Server Keystore v1..v4" "Server accept thread
pool
v1" "Server JSP Compiler v1..v3" "Server request log v1..v5", and so
on. Much better IMHO to let them alter the "Server" configuration to
their
heart's content, then let them export it or flag it as locked if they
want
to preserve a snapshot of that state.
Thanks,
Aaron
On Mon, 25 Jul 2005, Jeremy Boynes wrote:
Configuration bundles are meant to be immutable so you shouldn't be
adding things to them at runtime. Think of them as being similar to
library jars or other maven artifacts - things would get very
confusing if you started adding classes into them as part of a
build. This allows the configuration to be identified by its ID in
the same way the artifact id identifies a dependency to maven.
Configuration bundles have attributes (currently modeled by exposing
the GBeans they contain which is problematic) which pertain to the
location in which they are being used. The *default* values for
those attributes are contained inside the bundle; the instance value
is set by the environment.
There are some implementation issues in Geronimo today (short cuts
taken for expediency) which obscure some of the subtleties of this
model. Some of these relate to classloading (the issues on the
packaging thread), others relate to GBean persistence.
I'll give a couple of examples which I hope highlight a couple of
the issues.
The first anti-pattern is that configuration ids are not unique - we
reuse them for different configurations. For example, although
Tomcat and Jetty based servers are quite different we use the same
"unique" id (org/apache/geronimo/Server) for both. We also reuse ids
across versions so it is impossible to tell if an application
deployed against org/apache/geronimo/Server was built using M1, M2,
M3 or HEAD. It is like only ever compiling against SNAPSHOT
dependencies.
Secondly, if configurations are immutable then you should not be
able to add GBeans to them at runtime (that would be mutating them).
So how do you add a network connector? The simplest model is to
separate the web container from its connectors and build them as
separate bundles (one for the container, one for each of the
connectors); if you want to add a new connector you add a new
instance of e.g. the HTTPS bundle.
Finally, there is the issue of instance properties - things in the
environment of where a configuration is being used that need to
override the default properties that is has. For example, the
default for the HTTP connector bundle might be to listen on port
8080 but on this server here it needs to be changed to be 8888.
Right now we do this by mutating the configuration installed in the
store which is problematic. Instead it would be better to associate
the state with the runtime and, after the bundle was loaded but
before it was started, inject those local values into it.
There's a fine line between when you want to override values on a
per instance basis and when you want to define a new configuration
for with those values as defaults. There's no right solution to that
but I think the type of installation plays into it:
* for a desktop development environment or single server installation
then you are better just overriding properties as needed
* for a clustered environment or large scale deployment then you are
better defining reusable bundles that can be easily moved
where/when
they are required
As Geronimo starts being considered for larger installations let's
not forget what the original config system was designed to do.
--
Jeremy