`
tian_cookie
  • 浏览: 44285 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

webMethods IS源代码分析——启动类

阅读更多
webMethods IS中负责服务器启动的类有四个:执行入口类com.wm.app.b2b.server.Main、服务器初始化类com.wm.app.b2b.server.Server、以及两个辅助类com.wm.util.UniqueApp、com.wm.util.AppRegistry。

让我们先来看看Main的main以及注释:
public static void main(String argv[])
    {
        int port = 0;
        String serviceName = null;
        //处理在启动脚本中传入的几个参数
        for(int i = 0; i < argv.length; i++)
        {
            if(argv[i].equals("-port") && i < argv.length - 1)
                port = Integer.valueOf(argv[1 + i++]).intValue();
            if(argv[i].equals("-home") && i < argv.length - 1)
                Config.setProperty("watt.server.homeDir", argv[1 + i++]);
            if(argv[i].equals("-service") && i < argv.length - 1)
                serviceName = argv[1 + i++];
        }
        
        if(port != 0)
            Config.setProperty("watt.server.port", Integer.toString(port));
        UniqueApp ua = null;
        int uaport = 4321;
        //获得一个叫uaport的端口参数,默认是4321
    String uapstr = System.getProperty("watt.server.uaport");
        if(uapstr != null)
            try
            {
                uaport = Integer.parseInt(uapstr);
            }
            catch(NumberFormatException _ex) { }

        //用这个uaport创建一个app
        ua = new UniqueApp(uaport);
        try
        {
            ua.start();
            //调用Server这个类的start方法初始化IS
            Server.start(argv);
            ua.quit();
            if(Server.restart())
            {
                try
                {
                    if(serviceName != null)
                    {
                        String homepath = System.getProperty("watt.server.homeDir", ".");
                        String cmd = homepath + File.separator + "bin" + File.separator + "RestartService.exe " + serviceName;
                        Runtime.getRuntime().exec(cmd);
                    }
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
                System.exit(42);
            } else
            {
                System.exit(0);
            }
        }
        catch(com.wm.util.UniqueApp.DeniedException _ex)
        {
            System.out.println("Server cannot execute. A server with this configuration is already running.");
            System.exit(0);
        }
    }

看到这里大家可能会产生疑问,这个UniqueApp的实例的ua到底有什么用呢,为什么要在Server初始化之前先start它,初始化之后又quit呢?要解答这些问题让我们先看看这个UniqueApp究竟做了什么事:

UniqueApp类的start方法、send方法和runRegistry方法:
public void start()
        throws DeniedException
    {
        if(port_ > lastPort_)
            debugPrint("UNQ  ERROR: port_ (" + port_ + ") > lastPort_ (" + lastPort_ + ")");
        for(; port_ <= lastPort_; port_++)
        {
            debugPrint("UNQ  attempting connection on port " + port_);
            try
            {
                debugPrint("UNQ  " + iden_ + " sending initial message");
                String response = send("init");
                debugPrint("UNQ  " + iden_ + " got response " + response);
                if(response == null)
                {
                    debugPrint("UNQ  connected on port " + port_ + ", but no response");
                    continue;
                }
                if(response.equals("DENIED"))
                    throw new DeniedException();
                if(response.equals("OK"))
                {
                    runHeartbeat();
                    break;
                }
                debugPrint("UNQ  connected on port " + port_ + ", but incomprehensible response");
                continue;
            }
            catch(IOException ioe)
            {
                if(DEBUG)
                    ioe.printStackTrace(System.out);
                runRegistry();
            }
            break;
        }

    }

public String send(String type)
        throws IOException
    {
        Socket socket = new Socket("localhost", port_);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        String msg = type + ": " + iden_;
        out.println(msg);
        out.flush();
        return in.readLine();
    }

public void runRegistry()
    {
        debugPrint("UNQ  " + iden_ + " starting registry on port " + port_);
        registry_ = new AppRegistry(iden_, port_);
    }


这里可以很清楚的看到,UniqueApp是一个socket的client端,它的作用就是用一些特定的原语连接localhost上的uaport端口,如果这个端口没有响应或者响应的不对,它就“new AppRegistry(iden_, port_)”。
AppRegistry是一个实现了Runnable接口的类,它又做了什么呢?请看:

AppRegistry类的构造方法、run方法、openSocket方法以及解析原语的processLineReceived方法:

public AppRegistry(String iden, int port)
    {
        info_ = new HashMap();
        out_ = null;
        socket_ = null;
        info_.put(iden, new Long(0x7fffffffffffffffL));
        port_ = port;
        Thread t = new Thread(this);
        t.setDaemon(true);
        t.start();
    }

public void run()
    {
        debugPrint("REG  running");
        openSocket();
        if(socket_ == null)
            debugPrint("REG  no socket");
        else
            while(socket_ != null) 
                processConnection();
        debugPrint("REG  stopped");
    }

protected void openSocket()
    {
        try
        {
            debugPrint("REG  running socket server on port " + port_);
            socket_ = new ServerSocket(port_);
            socket_.setSoTimeout(3000);
        }
        catch(IOException ioe)
        {
            if(DEBUG)
                ioe.printStackTrace(System.out);
            debugPrint("REG  failed to open socket");
            socket_ = null;
        }
    }

protected void processLineReceived(String line)
    {
        debugPrint("REG  processLineReceived(" + line + ")");
        int pos = line != null ? line.indexOf(": ") : -1;
        if(pos != -1)
        {
            String type = line.substring(0, pos);
            String identifier = line.substring(pos + 2);
            if(type.equals("init"))
                handleInit(identifier);
            else
            if(type.equals("update"))
                update(identifier);
            else
            if(type.equals("quit"))
                quit(identifier);
            else
                debugPrint("REG  unknown type: '" + type + "' in line: '" + line + "'");
        }
    }


由此看出AppRegistry是一个单线程的Socket Server。虽然到了这里我们都知道了UniqueApp和AppRegistry的作用,但是疑惑仍然没有解答,为什么要在服务器启动之前先连接或者启动一个Socket Server呢?

要得到答案,让我们来看看Server初化始化的时候究竟做了些什么:

Server类的start方法:

public static void start(String args[])
    {
        gServer = new Server(args);
        gServer.start();
        try
        {
            gServer.join();
        }
        catch(Exception _ex) { }
    }


这里要说明的是Server类是Thread类的子类,它的run方法如下:
public void run()
    {
        try
        {
            long start = System.currentTimeMillis();
            com.wm.util.Config.setProperty("watt.server", "true");
            gRestart = false;
            gInShutdown = false;
            gListeners = new Values();
            gResources = new Resources(System.getProperty("watt.server.homeDir", "."), true);
            gConfFile = gResources.getConfigFile("server.cnf");
            gResources.getLogJobsInDir();
            gResources.getLogJobsOutDir();
            gResources.getDatastoreDir();
            loadConfiguration();
            Scheduler.init();
            String tmp = com.wm.util.Config.getProperty("false", "watt.server.control.runMemorySensor");
            if(Boolean.valueOf(tmp).booleanValue())
                MemorySensor.init(ServerController.getInstance());
            ThreadPoolSensor.init(ServerController.getInstance());
            checkProperties();
            com.wm.util.Config.processCmdLine(args);
            setupLogging();
            JournalLog.init(args);
            JournalLogger.init(JournalLog.newProducer(), JournalLog.getHandler());
            JournalLogger.logCritical(1, 25, Build.getVersion(), Build.getBuild());
            if(!LicenseManager.init())
            {
                JournalLogger.logCritical(1, 14);
                return;
            }
            RepositoryManager.init();
            JDBCConnectionManager.init();
            AuditLogManager.init();
            setupIPRules();
            UserManager.init();
            ACLManager.init();
            ThreadManager.init();
            StateManager.init();
            ListenerAdmin.init();
            ServiceManager.init();
            InvokeManager.init();
            Statistics.init();
            NetURLConnection.init();
            ContentManager.init();
            CacheManager.init();
            EventManager.init();
            boolean dispatcherCorrectlyInit = false;
            try
            {
                DispatchFacade.init();
                dispatcherCorrectlyInit = true;
            }
            catch(Exception e)
            {
                JournalLogger.logCritical(31, 25, e);
            }
            WebContainer.init();
            ISMonEvtMgr.create();
            PackageManager.init();
            DependencyManager dm = NSDependencyManager.current();
            if(dm == null || !dm.isEnabled())
                JournalLogger.logDebugPlus(3, 15, 25);
            else
                JournalLogger.logDebugPlus(3, 14, 25);
            try
            {
                if(dispatcherCorrectlyInit)
                    DispatchFacade.start();
            }
            catch(Exception ce)
            {
                JournalLogger.logError(35, 25, ce);
            }
            PortManager.init();
            MimeTypes.init();
            HTTPDispatch.init();
            ProxyHTTPDispatch.init();
            LBHTTPDispatch.init();
            CacheManager.startSweeper();
            Document.setHostServices(new ServerXmlHostServices());
            try
            {
                ClusterManager.init();
            }
            catch(Exception e)
            {
                JournalLogger.logDebug(103, 33, e.getMessage());
            }
            try
            {
                String jobDir = com.wm.util.Config.getProperty("logs/jobsout", "watt.tx.jobdir");
                TContext.init(jobDir);
            }
            catch(ServiceException e)
            {
                JournalLogger.logDebugPlus(3, 9998, 36, e);
            }
            if(Config.isSSLPresent())
                try
                {
                    Class c = Class.forName("com.wm.app.b2b.server.ServerTrustDeciderManager");
                    TrustDeciderManager tdm = (TrustDeciderManager)c.newInstance();
                    TrustManager.setManager(tdm);
                }
                catch(Throwable _ex) { }
            if(!ListenerAdmin.isReady() && !gCanListen)
            {
                JournalLogger.logCritical(4, 14);
                return;
            }
            Scheduler.scheduleTask("Key Update", new KeyUpdate(), 0L, 0x5265c00L);
            String sc = com.wm.util.Config.getProperty("true", "watt.server.saveConfigFiles");
            if((new Boolean(sc)).booleanValue())
                saveConfigFiles();
            if(Configurator.isBrokerConfigured())
                SyncManager.init();
            gRunning = true;
            long startTimeSeconds = (System.currentTimeMillis() - start) / 1000L;
            JournalLogger.logCritical(2, 14, Long.toString(startTimeSeconds));
            synchronized(this)
            {
                try
                {
                    wait();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        JournalLog.unInit();
    }


上面的代码不用多解释,大家可以看到IS启动做了哪些事情,IS分为哪些模块,以及这些模块的加载顺序。
IS启动的操作很多,启动时间也比较长,而且有“PortManager.init()”、“saveConfigFiles()”这样需要独占运行的端口占用和文件操作,如果是在同一个JVM上我们可以用Synchronized,如果是不到的JVM呢?答案揭晓了,UniqueApp的作用是使用端口占用的方式在IS启动阶段实现互斥,即对于同一个启动文件夹下的配置一台机器只能有一个IS在启动,否则会报出“Server cannot execute. A server with this configuration is already running.”的错误。
分享到:
评论
1 楼 galaxystar 2006-11-08  
不错,虽然没用过webmethods的产品!

相关推荐

    webMethods 912 IS管理手册

    This guide is for the administrator of a webMethods Integration Server. It provides an overview of how the server operates and explains common administrative tasks such as starting and stopping the ...

    webMethods8.0 IS

    ### webMethods 8.0 Integration Server (IS) 相关知识点 #### 一、概述 - **产品背景**:webMethods 8.0 IS(Integration Server)是Software AG推出的一款集成解决方案平台,主要应用于企业级应用程序集成(EAI...

    webMethods中文文档

    每次登录前需检查服务器是否已连接,webMethods服务是否已启动。登录界面包括服务器地址和端口号输入,输入正确信息后进入平台。 【webMethods工作界面】 webMethods的主要工作界面通常分为三个部分:左侧栏显示...

    webMethods8.0 Administering Broker

    webMethods Broker is the primary component in what is referred to as the “message backbone” in a webMethods integration environment. Along with other webMethods components, webMethods Broker ...

    webMethods Developer Guide

    webMethods Developer is a graphical development tool that you use to build edit and test integration logic It provides an integrated development environment in which you can develop the logic and ...

    WebMethods 入门使用文档

    - webMethods Developer:是集成开发环境,提供可视化建模、代码编写和部署工具。 - webMethods Glue:用于快速集成遗留系统、Web服务和业务流程。 - webMethods Fabric:是一个集成云服务和内部部署应用程序的平台...

    webmethods SAP Integration best practices

    在IT行业的深度探索中,"webmethods SAP Integration best practices"这一主题揭示了在SAP环境下,如何通过webMethods实现高效、稳定的企业级集成的最佳实践。本文将深入剖析这些最佳实践,帮助读者理解如何优化SAP...

    webMethods Adapter Development Kit Installation Guide

    ### webMethods Adapter Development Kit 安装指南知识点解析 #### 一、概述 《webMethods Adapter Development Kit Installation Guide》是一份详尽的文档,主要针对webMethods Adapter Development Kit 6.5版本...

    webmethods 6.5 安装手册 英文

    6. **服务启动与停止**:手册会解释如何启动和停止WebMethods的各种服务,包括Integration Server、Broker服务等,这些操作通常通过命令行或管理界面完成。 7. **故障排查**:安装过程中可能会遇到问题,手册将提供...

    WebMethods Developer UsersGuide用户入门操作手册.pdf

    1. **WebMethods各个组件的介绍和功能**:手册中提及了webMethods软件套件中的多个组件,如webMethods Administrator(管理员)、webMethods Broker(经纪人)、webMethods Dashboard(仪表盘)、webMethods ...

    WebMethods Flat File user guide

    在WebMethods的产品线中,包括了WebMethods Access、WebMethods Administrator、WebMethods Broker、WebMethods Dashboard、WebMethods Developer、WebMethods Fabric、WebMethods Glue、WebMethods Installer、...

    webMethods Developer Users Guide

    《webMethods Developer Users Guide》是针对webMethods Developer这一强大集成开发环境的一份详细用户指南。webMethods Developer是一款用于构建、测试和部署企业级业务流程集成解决方案的重要工具。它集成了多种...

    webMethods公司简介.doc

    1. 为企业决策者提供全面、正确、实时的业务信息:webMethods 的业务整合平台,可以轻易的从企业和合作伙伴的不同应用系统中采集丰富、有效、统一、实时的交易信息,通过提供对这些信息的处理,分析,可以为企业决策...

    EDI webmethods user Guide

    EDI webmethods user Guide Electronic Data Interchange,電子數據交換﹐是一種電子傳輸數據的方法﹐使用這種方法﹐將商業或行政事務處理中的報文數據按照公認的標准﹐形成結構化的報文數據格式﹐進而將這些結構化...

    WebMethods Integration Server Ver集成组件.pdf

    4. 文档中提及的webMethods Administrator、webMethods Broker等,可能是指WebMethods Integration Server中的不同模块或组件,各自承担不同的任务,比如管理、消息传递、用户界面展示等。 5. 文档提到的多个注册...

    webMethods8.0 TN Concepts

    webMethods Trading Networks also referred to as Trading Networks is a component that runs on the webMethods Integration Server Trading Networks enables your enterprise to link with other companies ...

    webMethods 9.0 _ Mediator 详解

    webMethods 9.0 Mediator是软件AG旗下webMethods开发平台中的一个关键组件,用于实现服务集成和管理。通过本文,我们将详细介绍webMethods Mediator的功能和作用。 首先,webMethods Mediator是什么?webMethods ...

    webMethods Integration Server8.2

    此外,管理员需要熟悉如何在系统启动时改变类路径信息,因为类加载器是根据类路径来定位和加载Java类的。 接下来,webMethods Integration Server 8.2服务器的角色和架构是其核心组成部分。服务器主要负责服务的...

    webMethods学习笔记

    ### webMethods基础知识与应用 #### 一、webMethods概述 - **定义**:webMethods是一种企业服务总线(ESB)技术,它提供了一系列工具和服务,用于集成不同的应用程序和服务。这些工具包括集成服务器、业务流程管理...

Global site tag (gtag.js) - Google Analytics