前面讲到了JMX的体系,下面从Tomcat源代码启动过程分析MBeans组件注册到MBeanServer的过程 。
(org.apache.catalina.startup.Bootstrap.main(String))
public static void main(String args[]) {
…
if (daemon == null) {
daemon = new Bootstrap();
try {
daemon.init(); ★1
} catch (Throwable t) {
t.printStackTrace();
return;
}
}
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
if (command.equals("startd")) {
args[0] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[0] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args); ★2
// Catalina的start方法被调用
daemon.start(); ★3
} else if (command.equals("stop")) {
daemon.stopServer(args);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
★1
daemon.init()会调用Bootstrap#createClassLoader方法,该方法会将对象名为StandardClassloader的MBean注册并返回Classloader。
(org.apache.catalina.startup.Bootstrap.createClassLoader(String, ClassLoader))
private ClassLoader createClassLoader(String name, ClassLoader parent)
throws Exception {
……
ClassLoader classLoader = ClassLoaderFactory.createClassLoader
(unpacked, packed, urls, parent);
// Retrieving MBean server
MBeanServer mBeanServer = null;
if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
mBeanServer =
(MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);
} else {
mBeanServer = MBeanServerFactory.createMBeanServer();
}
//注册Server类加载器MBeans
ObjectName objectName =
new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
mBeanServer.registerMBean(classLoader, objectName);
return classLoader;
}
common、server、shared三个classloader会被依序生成,并被注册到mBeanServer中去。这三个Classloader都是StandardClassloader,并且实现了StandardClassloaderMBean接口。因为StandardClassloaderMBean接口没有暴露任何的属性和方法,所以在Jconsole窗口中将看不到StandardClassloader的属性和方法显示。
★2
daemon.load(args)是Catalina载入的过程,standardServer、StandardService、Connector将会被依次初始化并完成Mbean的注册。
1) StandardServer初始化注册。
(org.apache.catalina.core.StandardServer.initialize())
public void initialize()
throws LifecycleException
{
if (initialized) {
log.info(sm.getString("standardServer.initialize.initialized"));
return;
}
initialized = true;
if( oname==null ) {
try {
//注册StandardServer的MBeans
oname=new ObjectName( "Catalina:type=Server");
Registry.getRegistry(null, null)
.registerComponent(this, oname, null );
} catch (Exception e) {
log.error("Error registering ",e);
}
}
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services.initialize();
}
}
2) StandardServer被注册后,它向外暴露了它的属性和await()和storeConfig()两个方法。
StandardService初始化并注册
(org.apache.catalina.core.StandardService.initialize())
public void initialize()
throws LifecycleException
{
if (initialized) {
log.info(sm.getString("standardService.initialize.initialized"));
return;
}
initialized = true;
if( oname==null ) {
try {
// StandardService的MBeans被注册
Container engine=this.getContainer();
domain=engine.getName();
oname=new ObjectName(domain + ":type=Service,serviceName="+name);
this.controller=oname;
Registry.getRegistry(null, null)
.registerComponent(this, oname, null);
} catch (Exception e) {
log.error("Error registering ",e);
} }
}
if( server==null ) {
ServerFactory.getServer().addService(this);
}
//初始化我们定义的连接
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
connectors.initialize();
}
}
StandardService被注册后,它向外暴露了它的属性和stop()和start()两个方法。在Jconsole中可以对这两个方法进行操作。
3) 对象名为“Catalina:type=Connector port=8080”、“Catalina:type=Connector port=8009”的Connector被注册。
(org.apache.catalina.connector.Connector.initialize())
public void initialize()
throws LifecycleException
{
if (initialized) {
log.info(sm.getString("coyoteConnector.alreadyInitialized"));
return;
}
this.initialized = true;
if( oname == null && (container instanceof StandardEngine)) {
try {
// we are loaded directly, via API - and no name was given to us
StandardEngine cb=(StandardEngine)container;
String encodedAddr = null;
if (getAddress() != null) {
encodedAddr = URLEncoder.encode(getAddress());
}
String addSuffix=(getAddress()==null) ?"": ",address=" + encodedAddr;
oname=new ObjectName(cb.getName() + ":type=Connector,port="+
getPort() + addSuffix);
Registry.getRegistry(null, null)
.registerComponent(this, oname, null);
controller=oname;
} catch (Exception e) {
log.error( "Error registering connector ", e);
}
log.debug("Creating name for connector " + oname);
}
ConnectorMbean暴露了它的属性和Start、stop、pause、resume、init、destroy等方法。可以在Jconsole中对这些方法进行操作。
★ 3
daemon.start()Catalina.start()StandardServer.start()
下面是Catalina.start()代码片段。
(org.apache.catalina.core.StandardServer.start())
public void start() throws LifecycleException {
if (started) {
log.debug(sm.getString("standardServer.start.started"));
return;
}
//唤醒相关的生命周期监听者
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
//启动我们定义的服务
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services instanceof Lifecycle)
((Lifecycle) services).start();
}
}
//唤醒相关的生命周期监听者
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
Tomcat的配置文件Server.xml中的Server元素中定义了Listener元素,如下所示:
<Server port="8005" shutdown="SHUTDOWN" debug="0">
...
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"
debug="0"/>
...
它将给org.apache.catalina.core.StandardServer添加一个org.apache.catalina.mbeans.ServerLifecycleListener类型的监听器,当StandardServer实例启动的时候,会触发一个START_EVENT事件,如StandardServer类中定义的那样:
public void start() throws LifecycleException {
...
lifecycle.fireLifecycleEvent(START_EVENT, null);
...
}
StandardServer对象停止的时候,会触发STOP_EVENT事件,如stop方法中定义的那样:
public void stop() throws LifecycleException {
...
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
...
}
这些事件会导致ServerLifecycleListener中的lifecycleEvent方法被提交。下面展示了lifecycleEvent方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.lifecycleEvent())
public void lifecycleEvent(LifecycleEvent event) {
Lifecycle lifecycle = event.getLifecycle();
if (Lifecycle.START_EVENT.equals(event.getType())) {
if (lifecycle instanceof Server) {
createMBeans();
...
}
...
else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
try {
if (lifecycle instanceof Server) {
destroyMBeans((Server)lifecycle);
}
if (lifecycle instanceof Service) {
destroyMBeans((Service)lifecycle);
}
}
从上面的代码可以看出当lifecycleEvent被调用时,由于START_EVENT事件被触发,createMBeans方法被调用,Catalina中所有MBeans将会生成。当StandardServer关闭时,STOP_EVENT事件被触发,destroyMBeans方法被调用,所有的MBeans将被销毁。
1) START_EVENT事件被触发,lifecycleEvent(START_EVENT)被调用,它会调用createMBeans方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans())
protected void createMBeans() {
try {
MBeanFactory factory = new MBeanFactory();
createMBeans(factory);※1
createMBeans(ServerFactory.getServer());※2
} catch (MBeanException t) {
Exception e = t.getTargetException();
if (e == null)
e = t;
log.error("createMBeans: MBeanException", e);
} catch (Throwable t) {
log.error("createMBeans: Throwable", t);
}
}
※1
该方法使用MBeanUtil类给MBeanFactory创建一个ObjectName并将其向MBean服务器注册。
protected void createMBeans(MBeanFactory factory) throws Exception {
// Create the MBean for the MBeanFactory
if (log.isDebugEnabled())
log.debug("Creating MBean for MBeanFactory " + factory);
MBeanUtils.createMBean(factory);
}
※2
该方法会将org.apache.catalina.Server对象创建模型MBean,使用for循环来迭代StandardServer实例中的所有Service对象。
protected void createMBeans(Server server) throws Exception {
//为Server自身创建MBean
if (log.isDebugEnabled())
log.debug("Creating MBean for Server " + server);
//MBeanUtils.createMBean(server);
if (server instanceof StandardServer) {
((StandardServer) server).addPropertyChangeListener(this);
}
// 为global NamingResources创建MBean(如果有的话)
NamingResources resources = server.getGlobalNamingResources();
if (resources != null) {
createMBeans(resources);
}
//为每个子服务创建MBeans
Service services[] = server.findServices();
for (int i = 0; i < services.length; i++) {
// FIXME - Warp object hierarchy not currently supported
if (services.getContainer().getClass().getName().equals
("org.apache.catalina.connector.warp.WarpEngine")) {
if (log.isDebugEnabled()) {
log.debug("Skipping MBean for Service " + services);
}
continue;
}
createMBeans(services);
}
}
4) createMBeans(Service service) 创建一个MBean实例并调用createMBeans方法来为该服务所有的连接器和引擎创建MBean对象
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Service))
protected void createMBeans(Service service) throws Exception {
//为Service自身创建MBean
if (log.isDebugEnabled())
log.debug("Creating MBean for Service " + service);
//MBeanUtils.createMBean(service);
if (service instanceof StandardService) {
((StandardService) service).addPropertyChangeListener(this);
}
// 为对应的连接器创建MBeans(8080,8009两个端口)
Connector connectors[] = service.findConnectors();
for (int j = 0; j < connectors.length; j++) {
createMBeans(connectors[j]);
}
// 为关联的Engine创建MBean
Engine engine = (Engine) service.getContainer();
if (engine != null) {
createMBeans(engine);
}
}
5) createMBeans(engine)(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Engine))
protected void createMBeans(Engine engine) throws Exception {
//为Engine自身创建MBean
if (log.isDebugEnabled()) {
log.debug("Creating MBean for Engine " + engine);
}
//MBeanUtils.createMBean(engine);
engine.addContainerListener(this);
if (engine instanceof StandardEngine) {
((StandardEngine) engine).addPropertyChangeListener(this);
}
//为关联的嵌套组件创建MBean
Realm eRealm = engine.getRealm();
if (eRealm != null) {
if (log.isDebugEnabled())
log.debug("Creating MBean for Realm " + eRealm);
//MBeanUtils.createMBean(eRealm);
}
// 为每个子Host创建MBeans
Container hosts[] = engine.findChildren();
for (int j = 0; j < hosts.length; j++) {
createMBeans((Host) hosts[j]);
}
6) createMBeans(host) ((org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Host))
protected void createMBeans(Host host) throws Exception {
//为Host自身创建MBeans
if (log.isDebugEnabled()) {
log.debug("Creating MBean for Host " + host);
}
//MBeanUtils.createMBean(host);
host.addContainerListener(this);
if (host instanceof StandardHost) {
((StandardHost) host).addPropertyChangeListener(this);
}
//为关联的嵌套组件创建MBean
Realm eRealm = host.getParent().getRealm();
Realm hRealm = host.getRealm();
if ((hRealm != null) && (hRealm != eRealm)) {
if (log.isDebugEnabled())
log.debug("Creating MBean for Realm " + hRealm);
//MBeanUtils.createMBean(hRealm);
}
//为每个子Context创建MBeans
Container contexts[] = host.findChildren();
for (int k = 0; k < contexts.length; k++) {
createMBeans((Context) contexts[k]);
}
}
lifecycleEvent(START_EVENT)方法调用结束。调用会逐级返回, ((Lifecycle) services).start()被调用。Deployer、GlobalRequestProcessor、JkHander、JkMain、JkWorkerEnv、Mapper、ThreadPool、Valve、ProtocolHandle等将会被注册。至此,Tomcat启动结束。JMX注册也完毕。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com