6.2 部署
-
单机
Auany,GlobalId,Switcher以及应用提供的Provider可以运行在同一台机器上,一般来说开发环境即使如此。
-
小规模
Auany,GlobalId可以合并在同一机器上运行。
应用负荷不太重, 连接数量不太多的情况下可以将Switcher配置文件中的Manager, Switcher节点直接拷贝到Provider配置文件中, 并且将Provider节点下的Manager节点的remoteIp设置为127.0.0.1。这种情况下直接启动Provider时, Switcher服务将被启动到同一java虚拟机中, Switcher服务与Provider服务之间除控制协议外的数据传输将被旁路, 提高运行效率。
-
大规模
分立运行Auany。
运行多个Switcher服务器。
配置Provider,连接多个Switcher服务器,支持大量Endpoint接入。
-
注意事项
-
正确分配PVID
同一运营环境下PVID必须正确分配。一个Provider对应一个唯一的PVID。整个环境允许分配2^24个PVID。
Endpoint的设计决定了一个完整的应用允许由多个Provider提供服务,大规模应用可以使用垂直划分的设计,解决负载问题。
框架决定了,运行环境可以设计并提供公共的Provider解决方案,交由各应用集成。建议这样的解决方案提供Variant模式或者脚本模式的实现,便于集成。
-
GlobalId
GlobalId原则上应该一个应用一个,如果多个应用之间可以约定一个组名的分配规范,那么可以共享一个。
-
底层数据库
如果一个应用的所有Provider中,只需要一个Provider提供zdb服务,使用edb底层数据库是合适的,可以提供比较高的存储效率。如果一个应用需要在多个Provider上提供zdb服务,应该考虑各个zdb连接同一mysql服务器,或者mysql集群,便于维护。
-
日志系统
Trace用于记录系统日志,不适合重负荷日志记录,建议应用使用log4j记录应用自己的日志。
-
6.3 运行状态监视
系统使用JMX提供运行状态监视的能力。
其中分为独立服务的监视,与服务器组数据搜集。
-
独立服务监视
以switcher服务器为例:
启动switcher服务器
运行jdk的bin目录内的jconsole程序,新建连接,大致出现如下内容:
连接limax.swticher.Main服务,切换到MBean TAB页
可以看到这样一系列limax相关的mbean信息
在这里,可以查看运行中的各类相关数据。
这里建立的是本地连接,如果需要使用远程连接方式,需要配置相应服务器的JmxServer参数,制定serverPort和rmiPort。switcher的服务配置中:
<JmxServer rmiPort="10002" serverPort="10003"/>
对应了使用连接url:
service:jmx:rmi://localhost:10003/jndi/rmi://localhost:10002/jmxrmi.
Jconsole使用图形UI直观表现了mbean数据,但是不利于记录分析。如果需要,可以通过limax.jar提供的简单工具来获取数据文本。例如, 为了获取前一个图中最后项threadpoolsize的数据, 可以运行命令:
java -jar limax.jar jmxtool attrs -c "service:jmx:rmi://localhost:10003/jndi/rmi://localhost:10002/jmxrmi" -b "limax.xmlconfig:type=XmlConfigs,name=threadpoolsize"
将获得如下结果:
4 ProtocolSchedulers
16 ApplicationExecutors
1 NioCpus
4 NetProcessors
这与Jconsole中查看到的数据一致:
java –jar limax.jar jmxtool的查询子命令
domains: 获取注册到服务器的JMX Domain
mbeans: 查询注册到服务器的所有mbean Name
attrs: 查询mbean属性,见上面的例子
-
通用服务器组数据收集
使用jmxtool的monitor子命令, 提供一个实现了limax.util.monitor.Collector的接口的类作为参数, monitor运行时, 创建该类的对象, 通过limax.util.monitor.CollectorController接口与之交互, 实现收集。
-
示例
demo目录下提供了一个testmonitor应用作为例子,AuanyCheckPointMonitor.java收集auany服务器的Zdb的Checkpoint相关数据,首先运行auany服务器,ant run即可运行收集。例子作周期为30s的收集,收集1分钟,大致结果如下:
[java] Sat May 09 02:59:24 CST 2015 localauany limax.zdb:type=Zdb,name=Checkpoint
[java] CountMarshalN 174
[java] TimeOfNextFlush 2015-05-09 00:04:40.691
[java] TotalTimeFlush 7391194
[java] PeriodCheckpoint 60000
[java] TotalTimeMarshalN 16099374
[java] TotalTimeCheckpoint 0
[java] TimeOfNextCheckpoint 2015-05-09 02:59:49.095
[java] CountMarshal0 0
[java] CountSnapshot 0
[java] CountFlush 0
[java] CountCheckpoint 174
[java] TotalTimeSnapshot 14960553
[java] Sat May 09 02:59:54 CST 2015 localauany limax.zdb:type=Zdb,name=Checkpoint
[java] CountMarshalN 175
[java] TimeOfNextFlush 2015-05-09 00:04:40.691
[java] TotalTimeFlush 7408422
[java] PeriodCheckpoint 60000
[java] TotalTimeMarshalN 16151422
[java] TotalTimeCheckpoint 0
[java] TimeOfNextCheckpoint 2015-05-09 03:00:49.145
[java] CountMarshal0 0
[java] CountSnapshot 0
[java] CountFlush 0
[java] CountCheckpoint 175
[java] TotalTimeSnapshot 14986577
[java] Sat May 09 03:00:24 CST 2015 localauany limax.zdb:type=Zdb,name=Checkpoint
[java] CountMarshalN 175
[java] TimeOfNextFlush 2015-05-09 00:04:40.691
[java] TotalTimeFlush 7408422
[java] PeriodCheckpoint 60000
[java] TotalTimeMarshalN 16151422
[java] TotalTimeCheckpoint 0
[java] TimeOfNextCheckpoint 2015-05-09 03:00:49.145
[java] CountMarshal0 0
[java] CountSnapshot 0
[java] CountFlush 0
[java] CountCheckpoint 175
[java] TotalTimeSnapshot 14986577
BUILD SUCCESSFUL
Total time: 1 minute 1 second
-
开发接口
Collector接口:(收集应用必须实现该接口)
-
void onController(CollectorController controller) throws Exception;
收集对象被创建出来之后,该方法被调用,收集对象获得收集控制器,controller的使用见下文。
-
void onRecord(String host, ObjectName objname, Map
item); Monitor收集到Jmx数据后调用该方法,区分主机名,Mbean和Mbean下的属性数据。该方法是收集的关键方法,数据内容可以存储到数据库,提供给后续分析使用。Monitor收集执行过程中,一个主机的一轮收集被分配给一个线程,该方法可能被并行调用,收集应用应该自行考虑同步问题。
-
default void onException(String host, Exception e){}
某一主机的收集过程中如果出现异常,则该方法被调用,将异常通告给收集应用。注意,这种情况下收集不会停止,例如出现了网络故障,导致某一主机的一次收集失败,故障恢复之后,后续的收集任务仍将正常进行。该方法可能被并行调用。
CollectorController接口:(收集应用用来管理收集行为)
-
Runnable addHost(String host, String url, String username, String password) throws MalformedURLException;
添加主机配置,username为null表示无须认证。返回的Runnable对象上调用run,该主机配置被删除,该主机上的所有收集被取消。
-
Runnable addCollector(String host, String pattern, long period) throws MalformedObjectNameException;
为一个主机添加一个收集,调用该方法之前必须确保host已经通过addHost成功加入,并且没有被取消, pattern按照ObjectName的模板格式, 使用通配符, 匹配多个实际的ObjectName,period单位毫秒,决定了收集频率。返回的Runnable对象上调用run,该收集配置被取消。
-
void stop();
同步停止整个收集过程,返回之后Collector接口的任何方法都不再被调用,可以安全清理收集器。
-
-
-
应用相关的服务器组数据收集
应用相关收集是通用收集的特化形式,与应用描述xml中定义的monitorset相联系,生成了相应的收集代码,可以更加精确地进行收集编程。
limax.util.monitor.MonitorCollecotor,实现了前面提及的CollectorController接口,内建Collector接口对象,将Collector.onRecord采集到的Jmx相关数据, 分发到经由MonitorCollector.addCollectorInstance添加到收集器内的收集对象。
通过addCollectorInstance加入的对象,必须实现应用xml定义的monitorset生成代码中的Collector接口。
例如:auany.xml定义了名为AuthProvider的monitorset,在生成代码中可以找到AuthProvider.Collector这样一个接口定义, 该接口定义的onRecord按照收集主机名, monitoset定义的key, monitorset定义的counter的顺序,精确还原了参数类型。
通过
mc.addCollectorInstance((AuthProvider.Collector) (host, platflag, pvid, _newaccount, _auth) -> { System.out.println("host = " + host + " platflag = " + platflag + " pvid = " + pvid + " newaccount = " + _newaccount + " auth = " + _auth); });
的方式,加入收集对象实例,即可实现类型化的收集。
具体使用,可以参考,testmonitor中的例子AuanyAuthMonitorAPI.java。
-
收集数据直接入库
某些运行环境下,需要将收集数据直接入库,事后分析。
通过limax.util.monitor.MonitorCollector.addSQLExecutor方法支持。具体使用可以参考testmonitor中的例子AuanyAuthMonitorDB.java。
构造带有onexception参数的MonitorCollector,即可通过onexception收集采集过程中发生的所有异常。
查看生成的AuthProvider.Collector代码,注意到接口内部提供了两个静态方法getCreateTableString和createInsertStatement,采集应用启动后,首次插入数据前会根据getCreateTableString返回的SQL语句在数据库中试图创建表格,忽略创建错误。这就是说,如果有必要可以根据特定需求预先建表,表的名字和基本字段描述出现在createInsertStatement方法中,用户定义的表格只要确保上述表名和基本描述字段存在即可,这些名字除了host,其它均来源于monitorset的描述,名字前面全部加上下划线, 避免与数据库保留字冲突。此外, getCreateTableString返回了符合Mysql规范的CREATE TABLE语句, 如果使用别的数据库, 也请仿照样式预先建表, createInsertStatement使用的INSERT语句是标准的, 不存在数据库兼容性问题。