Brian Stansberry [
https://community.jboss.org/people/brian.stansberry] modified the
document:
"AS 7 Internal Architecture Overview"
To view the document, visit:
https://community.jboss.org/docs/DOC-47970
--------------------------------------------------------------
h2. High Level Overview
At a coarse level, AS 7 consists of two main elements:
* A core manageable service container based on modular classloading
* Extensions to that core that provide the kind of functionality most users associate with
an application server, like handling HTTP requests and managing transactions
The AS distribution also includes two clients for the management interfaces it exposes (a
CLI tool and a web-based admin console). The AS codebase also produces implementations of
the SPIs published by the Arquillian project, allowing AS7 servers to run Arquillian-based
tests.
h3. AS Core
The core of the AS consists of the following primary elements:
* A modular classloading system provided by the jboss-modules library
* A fast, highly scalable service container framework provided by the jboss-msc library
* An extensible management layer that is meant to mediate access to the service container
by logic that wants to add, remove and modify services. The management layer also provides
a consistent, persistent, configuration model for the AS. The management layer involves*
core elements, via the jboss-dmr library and the AS codebase's own controller,
controller-client, deployment-repository, domain-management and network modules as well as
parts of the server module
* remote management capability via the protocol and domain-http modules
* multi-server managed domains via the process-controller and host-controller modules
* miscellaneous elements provided via the managment-client-content and platform-mbean
modules
* A deployment framework for coordinating installation of deployment content into the
runtime. This is one of the things provided by the server module.
h3. AS Extensions
Most of the functionality that end users associate with an application server is provided
AS extensions. Most of the modules in the AS7 codebase are extension implementations, with
each extension providing a coherent set of functionality. Many extensions provide support
for some aspect of the Java EE specifications.
Extensions implement an interface (org.jboss.as.controller.Extension) that allows
integration with the core AS management layer. Via that mechanism, extensions are able to
* participate in the parsing and marshalling of the AS's configuration documents
* register resources and operations to be exposed via the AS's management API
* install services into the AS's service container
* register deployment unit processors with the AS's deployment framework
See the "
https://docs.jboss.org/author/display/AS72/Extending+JBoss+AS+7 Extending
JBoss AS 7" document for more on extensions. See also
https://community.jboss.org/docs/DOC-25627 https://community.jboss.org/docs/DOC-25627 for
more on how extending AS 7 differs from extending previous versions of JBoss AS.
h2. AS7 Boot Process
To better illustrate the AS 7 architecture, let's walk through the boot process for a
standalone server.
h3. Primordial Boot
When you run bin/standalone.sh from the root of the AS 7 distribution, the final effect is
to launch a JVM using the following essential command
java -jar jboss-modules.jar -mp modules org.jboss.as.standalone
If you start the AS and use the ps command to see the actual JVM launch command,
you'll see a lot of JVM settings (-Xmx and the like) and a lot of system property
settings, but the above bits are the key information. Let's break that down a bit:
java -jar jboss-modules.jar
We can see from this that the actual main class the VM will invoke isn't in a JBoss AS
library at all; it's in jboss-modules.jar (specifically, the org.jboss.modules.Main
class.) So, when you start the AS the first thing you are doing is setting up a modular
classloading environment.
-mp modules
These are arguments passed to org.jboss.modules.Main.main(). The -mp is short for
"module path" and the value is a path somewhat analogous to the value of an OS
$PATH environment variable. Each item in the path is a location under which jboss-modules
will look for a module when needed. If there is more than one item in the path, the items
are searched in order, with the search ending as soon as the module is found. In this case
there is only one item in the path -- the modules/ dir under the AS distribution root.
org.jboss.as.standalone
This is the name of a module located on the module path. This module will be loaded by
jboss-modules. If you look in the modules/org/jboss/as/standalone/main/module.xml file in
the AS distribution, you will see it includes this element:
<main-class name="org.jboss.as.server.Main"/>
When jboss-modules sees that element in the module.xml for the module passed to its main()
method, it knows to load the specified class and to pass any remaining command line
arguments into +its+ main() method. So, now we have a modular classloading enviroment set
up, and the org.jboss.as.server.Main.main() method (found in the AS codebase's server
module) has been invoked.
The org.jboss.as.server.Main.main() method does a number of things, but two are most
relevant for people who wish to understand how to develop the AS:
* Any remaining command line arguments are processed and an instance of the
ServerEnvironment is created. This object encapsulates environmental information available
via the command line or system properties; things like where the root of the AS dist is;
where the root of the server instance is; where the configuration file is, etc. Later this
information is made available to all services in the system via the
ServerEnvironmentService.
* An object implementing the Bootstrap interface (specifically, the
org.jboss.as.server.BootstrapImpl class) is created and configured and its bootstrap()
method is invoked.
h3. Service-based Boot
The most important thing BootstrapImpl does is create an instance of the JBoss MSC
library's ServiceContainer interface. A service container manages a set of running
services. A service is simply a thing that can be started and stopped, with start and stop
performed via methods specified in the JBoss MSC Service interface. A service also exposes
a value of some type T via the Service interface's public T getValue() method. The
value type T specified by the service is used by default by consumers of the service, and
should represent the public interface of the service. It may or may not be the same as the
implementing type of the service.
The ServiceContainer provides an API for managing services -- configuring and installing
them, removing them, triggering start and stop, looking up already installed services,
etc. Configuring a service can involve expressing the dependencies the service has on
other services and asking that the service container inject the value of depended-upon
services into the service before starting it. If a service depends upon another service,
that other service must be successfully started before the service container will invoke
the dependent service's start method. If for some reason the depended-upon service
needs to be stopped, the service container will invoke the dependent service's stop
method first.
The ServiceContainer maintains an internal thread pool. In order to achieve highly
performant management of large numbers of inter-related services, activities related to
starting and stopping services are performed as a series of concisely scoped tasks, with
the threads in the thread pool used to execute those tasks. For example, executing a
service's start method would be a task performed by a thread in the
ServiceContainer's thread pool. Because of this fact, +it is important to recognize
that any activity related to starting and stopping services will be highly multi-threaded.
For example, you can never assume that the thread that asks the service container to
install a service will be the thread that calls its start method.+
So, at this point in our boot, we have in place two of the four main architectural
elements discussed in the "AS Core" section of the "High Level
Overview" above: a modular classloading environment provided by the jboss-modules
library, and a service container framework provided by the jboss-msc library.
Up to this point in the AS boot, all activity has been on a single thread, the JVM's
main thread. In the BootstrapImpl.bootstrap() method, things get more interesting, since
much of the remaining boot work involves installing services, with the
ServiceContainer's thread pool threads doing the most of that work.
BootstrapImpl.bootstrap() installs two services:
* ControlledProcessStateService. This service provides access to a simple enum value
showing the current running state of the server (STARTING, STOPPING, RUNNING,
RESTART_REQUIRED, RELOAD_REQUIRED). This is the only service that once started should not
be stopped until the VM is being shut down.
* ApplicationServerService. This is the root service for the application server; all other
services in one way or another depend upon it. When you use the CLI to perform the :reload
operation, the server handles that request by telling the service container to stop this
service, which has the effect of stopping all other services that depend upon it. Then
once it is stopped, the service container is told to start the service again.
The ApplicationServerService starts a number of other services in its start method. The
most significant of these is the ServerService.
h3. The ServerService and the Controller Boot Thread
ServerService brings in the 3rd and 4th of the four primary components of the core AS
listed in the "High Level Overview" above -- the extensible management layer and
the deployment framework. For those of you familiar with the "
https://docs.jboss.org/author/display/AS72/Extending+JBoss+AS+7 Extending JBoss AS 7"
document, ServerService performs many of the same kinds of activities an Extension
implementation performs in its initialize(ExtensionContext context) method, but for the
core AS management model:
* registers resource definitions, attribute definitions and OperationStepHandlers for the
core AS managed resources
* registers core DeploymentUnitProcessors
ServerService implements Service<ModelController>. A ModelController is the central
execution point for management operations in a managed AS process (i.e. a server or a
HostController in a managed domain.)
In its start method, ServerService spawns a separate thread, the "Controller Boot
Thread", which is responsible for coordinating the remainder of the boot. It does the
following primary tasks
* Triggers the parsing of the server configuration file (e.g. standalone.xml) into a list
of management operations that should be executed by the ModelController to bring the
server's running configuration in line with the xml configuration
* Passes those management operations into the ModelController's execute method. The
ModelController uses the Controller Boot Thread to handle execution of many of the steps
involved in handling those operations.
* Blocks until all services added into the runtime as part of handling those management
ops have either started or failed to start.
* Logs the completion of boot.
The tasks of the Controller Boot Thread are spelled out in further detail below.
h4. XML Parsing, Extension Loading, Extension Parsing Initialization
The task of an XML parser for an AS7 configuration document (e.g. standalone.xml,
domain.xml, host.xml) is to populate a list of management operations that should be
executed by the ModelController to bring the process' running configuration in line
with the xml. Each of those management operations has the same format as would be read off
the wire if the CLI had sent an operation request to the server to invoke an equivalent
operation.
The parser for the core AS xml namespace has some special behavior when it comes to
parsing an <extension> element in the xml:
* The name attribute of the element is the name of a JBoss Modules module that contains an
implementation of the org.jboss.as.controller.Extension interface
* Once the name is parsed, the parser asks JBoss Modules to load the module
* Once the module is loaded, the java.lang.ServiceLoader mechanism is used to load the
module's implementation of the Extension interface.
* The initializeParsers(ExtensionParsingContext context) method on that Extension
implementation is invoked. That allows the extension to register XML parsers for the XML
namespaces supported by the subsystem(s) the extension provides.
* When the core AS xml parser subsequently encounters a <subsystem> element in the
configuration document, the xml namespace of the element is determined, and the
appropriate parser registered by some Extension is used to parse that portion of the
document.
h4. Execution of Boot Management Operations, Extension Initialization
Once xml parsing is complete, a list of management operations is ready for execution by
the ModelController. Each operation has the same format (address, operation name,
parameters) as would be read off the wire if the CLI had sent an operation request to the
server to invoke an equivalent operation after boot. The Controller Boot Thread asks the
ModelController to execute the operations as a unit, with each individual operation acting
as a step in the overall unit of work. Execution proceeds in 3 stages, with all steps in
the overall unit completing a stage before execution on the next stage begins. (This
execution pattern applies whenever any operation or atomic list of operations is invoked,
not just during boot.)
* Stage MODEL -- the OperationStepHandler registered for each operation makes necessary
updates to the server's internal configuration model, and, if necessary, registers a
handler for the same operation for Stage RUNTIME.
* Stage RUNTIME -- any OperationStepHandler registered in Stage MODEL for an operation
accesses the JBoss MSC ServiceContainer and installs/removes/updates any relevant
services. The ServiceContainer has its own thread pool and uses it to perform the
necessary tasks to start and stop services. The thread executing the OperationStepHandler
does not do this directly, and the handler implementation needs to recognize that service
start/stop will be asynchronous.
* Stage VERIFY -- A Stage.MODEL or Stage.RUNTIME handler can register a Stage.VERIFY
handler that will only run once the ServiceContainer had completed all service
modifications made in stage RUNTIME. A VERIFY handler can check that the runtime service
changes completed successfully.
Before the list of boot operations is passed into the ModelController, a check is done for
operations that add extension resources (for example, using CLI syntax,
/extension=org.foo.extension:add.) When one is found, the relevant Extension
implementation's initialize(ExtensionContext context) method is invoked. This gives
the Extension a chance to register its resource and attribute definitions and its
OperationStepHandlers with the core AS management layer before the boot operations are
executed.
h4. Wait for Service Container Stability and Boot Completion
The final steps in the AS 7 boot are to wait while the JBoss MSC ServiceContainer
processes the installation and start of all the services added by the handlers for the
boot operations. As discussed in the introduction to the ServiceContainer above, the start
of services is performed by threads in the ServiceContainer's internal thread pool.
Services are not started by the Controller Boot Thread. However, the ServerService
attaches a listener to the controller object for each service; using this the
ServerService is able to track when all services have reached a stable state. The
Controller Boot Thread uses this facility to block until the ServiceContainer has
stabilized. At that point, all services are either started or failed, and boot is nearly
complete. The Controller Boot Thread switches the state of the ControlledProcessState
service from STARTING to RUNNING, writes a log message reporting that the boot is
complete, and boot is finished.
h2. Deployment Processing
When you trigger deployment of some content, one of the management operations supported by
the core AS management layer is invoked. The logic responsible for handling that operation
will extract relevant information from the operation request (e.g. the name of the
deployment) and will then install services into the AS's service container:
* A Service<VirtualFile> implementation that provides an org.jboss.vfs.VirtualFile
that represents the deployment content.
* A Service<DeploymentUnit> (in this case RootDeploymentUnitService) that provides a
DeploymentUnit for the deployment. A DeploymentUnit retains data which is persistent for
the life of the deployment, and will later be passed into the various
DeploymentUnitProcessor implementations that perform various actions to install the
runtime services needed by the deployment.
The RootDeploymentUnitService has injected into it a reference to all the
DeploymentUnitProcessor (DUP) implementations that were registered by the core
ServerService at boot or that have been registered by subsystems. The DUP implementations
are grouped by the Phase of the deployment process in which they execute, and are
numerically ordered within that phase. DeploymentUnitProcessors are organized in a chain
fashion, with each DUP performing a limited set of tasks to help take a deployment from
being a bunch of bits to being a set of useful services.
Deployment proceeds in phases. See the
https://github.com/jbossas/jboss-as/blob/master/server/src/main/java/org/...
Phase enum for a listing of the phases. For each phase, a DeploymentUnitPhaseService
representing that phase that is installed into the service container. Each phase service
(save the first) depends on the phase service for the previous phase, and each phase
service (save the last) in its start method installs the phase service for the next phase.
The RootDeploymentUnitService in its start method installs the first phase service, which
in turn depends on it the RootDeploymentUnitService. The effect of all this is if the
RootDeploymentUnitService is stopped (e.g. by the undeploy management operation), this
will trigger a requirement for the service container to first stop the first phase
service, which will in turn trigger a requirement to first stop the next phase service,
and so on all the way to the final phase service. The effect is the phase services will be
stopped in reverse order from how they were started.
The primary thing the phase services do in their start and stop methods is invoke the
deploy and undeploy methods of each DeploymentUnitProcessor registered for their phase.
The deploy method is invoked in phase service start and the undeploy method is invoked in
stop. For each deploy/undeploy call the DUP is provided with a DeploymentPhaseContext that
provides context to the call and gives the DUP access to the service container, allowing
it to install or remove services.
h3. Deployment Processing and Modules
One of the tasks performed by the DeploymentUnitProcessors is to set up the modular
classloading enviroment for the deployment. Each top-level deployment has its own
dynamically generated module. For deployment types that include known subdeployments (e.g.
an ear can include wars, ejb jars, etc) then in addition those subdeployments also get
their own dynamically generated module. What other modules these deployment modules have
visibility to depends on the requirements determined by the deployment framework when it
analyzes the deployment content (e.g. by parsing deployment descriptors, reading
manifests, or scanning annotations.)
The key actor in this process is the
org.jboss.as.server.deployment.module.ModuleSpecProcessor, which is a
DeploymentUnitProcessor. The ModuleSpecProcessor configures and installs an MSC service
that interacts with jboss-modules to dynamically generate the deployment's module.
Other DeploymentUnitProcessors that execute prior to ModuleSpecProcessor analyze the
content of the deployment and add contextual information to the DeploymentUnit that is
used by ModuleSpecProcessor to establish what other modules the deployment's module
can access. So, for example, a DUP registered by the JPA subsystem might recognize that
the deployment requires JPA support (e.g. by detecting the presence of a persistence.xml
file) and record that visibility to the modules that provide the JPA APIs should be added.
The effect of all this is the deployment's classes have access to an appropriate set
of classes located in the AS's own modules or in other deployments, but do not have
access to classes located in other modules.
--------------------------------------------------------------
Comment by going to Community
[
https://community.jboss.org/docs/DOC-47970]
Create a new document in JBoss AS 7 Development at Community
[
https://community.jboss.org/choose-container!input.jspa?contentType=102&a...]