显示标签为“JBoss EAP”的博文。显示所有博文
显示标签为“JBoss EAP”的博文。显示所有博文

2016年8月24日星期三

EAP_052:默认加载了哪些 modules ?

环境:OS X EI Capitan 10.11.6 + JBoss EAP 6.4.0 + Redis 3.2.3

从上一篇文章,我们知道 JBoss EAP 默认加载了 resteasy module,从而导致了问题的出现。
那么,JBoss EAP 默认都加载了哪些 modules 呢?

修改 standalone.xml,在日志部分增加如下内容:
<logger category="org.jboss.as.server.deployment">
              <level name="DEBUG"/>
</logger>

在 server.log 中会看到类似下面的信息:
1:32:00,249 DEBUG [org.jboss.as.server.deployment] (MSC service thread 1-3) Adding dependency ModuleDependency [identifier=javax.ejb.api:main, moduleLoader=local module loader @5fa0f02a (finder: local module finder @3ef78672 (roots:

参考文献:
1. https://access.redhat.com/solutions/257633

2016年3月18日星期五

EAP_051:从 exclude org.apache.httpcomponents 不起作用说起

环境:OS X EI Capitan 10.11.6 + JBoss EAP 6.4.0 + Redis 3.2.3

问题重现步骤:
(1)启动 redis
(2)启动 jboss eap
(3)部署 cas.war

控制台抛出异常,web 应用发布不成功。
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/cas-bad]] (ServerService Thread Pool -- 102) JBWEB000287: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'logoutManager' defined in ServletContext resource [/WEB-INF/spring-configuration/applicationContext.xml]: Cannot resolve reference to bean 'noRedirectHttpClient' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'noRedirectHttpClient': FactoryBean threw exception on object creation; nested exception is java.lang.NoSuchMethodError: org.apache.http.impl.client.HttpClientBuilder.setSSLHostnameVerifier(Ljavax/net/ssl/HostnameVerifier;)Lorg/apache/http/impl/client/HttpClientBuilder;

经过检查,发现是 JBoss EAP 本身自带的 httpcomponents 版本太旧,没有方法 setSSLHostnameVerifier,于是导致异常。

于是在WEB-INF/lib 下增加高版本的 httpcomponents,并增加 WEB-INF/jboss-deployment-structure.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
 <module name="org.apache.httpcomponents"/>
<module name="org.apache.commons.logging" />
<module name="org.apache.log4j" />
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
<module name="org.jboss.stdio" />
   <module name="org.jboss.netty"/>
</exclusions>
</deployment>
</jboss-deployment-structure>

重新打成 war 包,jar -cvf cas.war META-INF/ WEB-INF/,并重新部署。

发现问题依旧,这是怎么回事?

修改 standalone.conf,增加 -verbose:class 参数
JAVA_OPTS="-Xms1303m -Xmx1303m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -verbose:class"

发现类的加载路径中,加载的是 modules 下面的httpcomponents,难道说 exclude org.apache.httpcomponents 没起作用?!

使用命令查找 modules 目录下,所有含有name="org.apache.httpcomponents" export="true"的xml文件。
grep -n -R --include="*.xml" 'name="org.apache.httpcomponents" export="true"' .
输出如下:
./system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/module.xml:47:        <module name="org.apache.httpcomponents" export="true"/>

打开 ./system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/module.xml,内容如下:
<module xmlns="urn:jboss:module:1.1" name="org.jboss.resteasy.resteasy-jaxrs">

    <resources>
        <resource-root path="async-http-servlet-3.0-2.3.10.Final-redhat-1.jar"/>
        <resource-root path="resteasy-jaxrs-2.3.10.Final-redhat-1.jar"/>
        <!-- Insert resources here -->
    </resources>

    <dependencies>
        <module name="javax.api"/>
        <module name="javax.annotation.api"/>
        <module name="javax.activation.api"/>
        <module name="javax.ws.rs.api"/>
        <module name="org.apache.commons.codec" />
        <module name="org.apache.httpcomponents" />
        <module name="org.apache.log4j"/>
        <module name="org.scannotation.scannotation" />
        <module name="org.slf4j" />
        <module name="javax.servlet.api"/>
        <module name="org.apache.commons.io"/>
        
        <!-- exported -->
        <module name="org.apache.httpcomponents" export="true"/>
        <module name="org.jboss.logging" export="true"/>
    </dependencies>
</module>

也就是说,虽然在 WEB-INF/jboss-deployment-structure.xml 中 exclude org.apache.httpcomponents,但是由于加载了 org.jboss.resteasy.resteasy-jaxrs module,而 rest easy 加载了org.apache.httpcomponents,所以最终 org.apache.httpcomponents,还是被加载了。

找到了问题根源,修改方法也简单了,
只要在 WEB-INF/jboss-deployment-structure.xml 中,再增加一行,把 rest easy 给 exclude 就好了。
<module name="org.jboss.resteasy.resteasy-jaxrs"/>

当然,你也可以把  ./system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/module.xml 中的 <module name="org.apache.httpcomponents" export="true"/> 这一行的 export="true" 改成 "false"。
但是由于 modules 下面的东西是系统自带的,在以后的升级中,可能会被改动,所以用户最好还是不要修改。

EAP_050:加载定制的 org.apache.httpcomponents module

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0

1. 为了能够看到类的加载路径,修改 standalone.conf,增加 -verbose:class 参数
JAVA_OPTS="-Xms1303m -Xmx1303m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -verbose:class"

2. 修改 index.jsp,修改后内容如下:
<html>
  <head>
    <title>JBoss Module Testing
    </title>
  </head>
  <body>

    <%
     org.apache.http.impl.client.DefaultHttpClient client = new org.apache.http.impl.client.DefaultHttpClient();
   
System.out.println("### The class of " + client + " is " + client.getClass().getName());
System.out.println("### Its classloader is " + client.getClass().getClassLoader());
out.println("### The class of " + client + " is " + client.getClass().getName());
out.println("### Its classloader is " + client.getClass().getClassLoader());
    %>
    Hi Check the Console/Log of your JBoss
  </body>
</html>

3. 有两种方式可以加载定制的org.apache.httpcomponents module

3.1. 方式一:以 module 的方式增加
(1)修改 jboss-deployment-structure.xml,修改后内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
   <deployment>
       <exclusions>
           <module name="org.apache.httpcomponents" />
       </exclusions>
       <dependencies>
           <module name="org.apache.httpcomponents" slot="4.4.1"/>
       </dependencies>
   </deployment>
</jboss-deployment-structure>
(2)在 EAP_HOME/modules/system/layers/base/org/apache/httpcomponents/ 目录下创建 4.4.1 目录,并把 httpclient-4.4.1.jar 和 httpcore-4.4.1.jar 复制到该目录下。
创建一个 module.xml 文件,内容如下:
<module xmlns="urn:jboss:module:1.1" name="org.apache.httpcomponents" slot="4.4.1">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>

    <resources>
        <resource-root path="httpclient-4.4.1.jar"/>
        <resource-root path="httpcore-4.4.1.jar"/>
        <resource-root path="httpmime-4.3.6.redhat-1.jar"/>
        <!-- Insert resources here -->
    </resources>

    <dependencies>
        <module name="javax.api"/>
        <module name="org.apache.commons.codec"/>
        <module name="org.apache.commons.logging"/>
        <module name="org.apache.james.mime4j"/>
    </dependencies>
</module>
(3)重新打包部署
cd /Users/maping/mygit/CustomModuleTest/my-webapp
mvn clean package
(4)访问 http://localhost:8080/my-webapp/index.jsp
在 Console 中会看到如下输出:
[Loaded org.apache.http.client.HttpClient from jar:file:/Users/maping/Redhat/eap/jboss-eap-6.4/modules/system/layers/base/org/apache/httpcomponents/4.4.1/httpclient-4.4.1.jar!/]
[Loaded org.apache.http.impl.client.CloseableHttpClient from jar:file:/Users/maping/Redhat/eap/jboss-eap-6.4/modules/system/layers/base/org/apache/httpcomponents/4.4.1/httpclient-4.4.1.jar!/]
[Loaded org.apache.http.impl.client.AbstractHttpClient from jar:file:/Users/maping/Redhat/eap/jboss-eap-6.4/modules/system/layers/base/org/apache/httpcomponents/4.4.1/httpclient-4.4.1.jar!/]
[Loaded org.apache.http.impl.client.DefaultHttpClient from jar:file:/Users/maping/Redhat/eap/jboss-eap-6.4/modules/system/layers/base/org/apache/httpcomponents/4.4.1/httpclient-4.4.1.jar!/]
说明是从 EAP_HOME/modules/system/layers/base/org/apache/httpcomponents/4.4.1/httpclient-4.4.1.jar 加载到 org.apache.http.client.HttpClient 等类的。

3.2. 方式二:直接添加在 WEB-INF/lib 目录下
(1)修改 jboss-deployment-structure.xml,修改后内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
   <deployment>
       <exclusions>
           <module name="org.apache.httpcomponents" />
       </exclusions>    
   </deployment>
</jboss-deployment-structure>
(2)在 WEB-INF 目录下增加 lib 目录,并把 httpclient-4.4.1.jar 和 httpcore-4.4.1.jar 复制到该目录下。
(3)重新打包部署
cd /Users/maping/mygit/CustomModuleTest/my-webapp
mvn clean package
(4)访问 http://localhost:8080/my-webapp/index.jsp
在 Console 中会看到如下输出:
[Loaded org.apache.http.client.HttpClient from vfs:/content/my-webapp.war/WEB-INF/lib/httpclient-4.4.1.jar]
[Loaded org.apache.http.impl.client.CloseableHttpClient from vfs:/content/my-webapp.war/WEB-INF/lib/httpclient-4.4.1.jar]
[Loaded org.apache.http.impl.client.AbstractHttpClient from vfs:/content/my-webapp.war/WEB-INF/lib/httpclient-4.4.1.jar]
[Loaded org.apache.http.impl.client.DefaultHttpClient from vfs:/content/my-webapp.war/WEB-INF/lib/httpclient-4.4.1.jar]
[Loaded org.apache.http.client.ClientProtocolException from vfs:/content/my-webapp.war/WEB-INF/lib/httpclient-4.4.1.jar]
说明是从 WEB-INF/lib/httpclient-4.4.1.jar 加载到 org.apache.http.client.HttpClient 等类的。

EAP_049:EAP 6 类加载机制(三)

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0

1. 为应用增加 explicit dependency
dependencies 可以使用两种不同的方法增加:

1.1. 增加 MANIFEST.MF 文件
(1)对于 .war 或 .jar 文件,在 META-INF 目录增加 MANIFEST.MF 文件。
(2)对于 .ear 文件,在 META-INF 目录增加 MANIFEST.MF 文件。
MANIFEST.MF 文件内容可以如下:
Dependencies: org.javassist, org.apache.velocity
Dependencies: org.javassist optional, org.apache.velocity
Dependencies: org.javassist, org.apache.velocity export

1.2 增加 jboss-deployment-structure.xml 文件
jboss-deployment-structure.xml 是 JBoss EAP 6 的新特性,它可以控制部署时类加载。 
(1)对于 .war 文件,在 WEB-INF 目录增加 jboss-deployment-structure.xml 文件。
(2)对于 .jar 文件,在 META-INF 目录增加 jboss-deployment-structure.xml 文件。
(3)对于 .ear 文件,在 META-INF 目录增加 jboss-deployment-structure.xml 文件。
jboss-deployment-structure.xml 文件内容可以如下:
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.javassist" optional="true"/>
      <module name="org.apache.velocity" export="true" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

2. 防止一个 module 被隐含加载
<jboss-deployment-structure>
  <deployment>
    <exclusions>
      <module name="org.javassist" />
      <module name="org.dom4j" />
    </exclusions>
  </deployment>
</jboss-deployment-structure>

3. exclude subsystem
<exclude-subsystems>
  <subsystem name="SUBSYSTEM_NAME" />
</exclude-subsystems>

4. .ear 中的 subdeployments isolated
默认情况下,<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
这表明:
(1).war subdeployment 隐含依赖 parent module 和 EJB Jar module。
(2)EJB JAR subdeployments 隐含依赖 parent module 和其它的 EJB JAR subdeployments。
注意,没有 subdeployment 隐含依赖 .war subdeployment,但是每个 subdeployment 都可以配置依赖其它的 subdeployment。
如果需要更高的隔离性,可以 <ear-subdeployments-isolated>true</ear-subdeployments-isolated>
这表明每个 subdeployment 都不隐含依赖其它 subdeployment。
(1).war subdeployment 不隐含依赖 parent module 和 EJB Jar module。
(2)EJB JAR subdeployments 不隐含依赖 parent module 和其它的 EJB JAR subdeployments。

参考文献:
1. 《JBoss_Enterprise_Application_Platform-6.4-Development_Guide-en-US.pdf》第三章 Class Loading and Modules
2. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=
3. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?start=1
4. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=&start=2
5. http://stackoverflow.com/questions/34293402/jboss-how-can-to-exclude-javax-validation-in-jboss-deployment-structure

EAP_048:EAP 6 类加载机制(二)

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0

1. 部署应用时的类加载机制

1.1 部署 .war
.war 文件被看成一个单独的 module,使用同一个类加载器加载 WEB-INF/lib 目录下的类和 WEB-INF/classes 目录下的类。

1.2 部署 .ear
.ear 由多个 module 组成,如下:
(1)根目录下的 lib/ 目录是一个单独的 module,称之为 parent module。
(2)其中的每一个 .war 是一个单独的 module。
(3)其中的每一个 EJB JAR 是一个单独的 module。

.ear 中的 .war 和 .jar 称之为 subdeployment,它们自动依赖 parent module。
但 .ear 中的 .war 和 .jar 彼此之间不会自动互相依赖,这个称之为 subdeployment isolation。
不过这个特性可以 disabled,可以为某个 .ear 设置,也可以设置在整个 EAP 上。
subdeployment 之间可以使用 explicit dependencies 定义依赖关系,就像 module 之间的依赖关系一样。

2. 类加载优先级
(1)首先加载 implicit dependencies
implicit dependencies 是 EAP 自动加载的,比如 Java EE 6 API。
(2)其次加载 explicit dependencies
explicit dependencies 可以定义在应用的 MANIFEST.MF 文件中,或者 jboss-deployment-structure.xml 文件中。
(3)接着加载应用本地的类
比如 WEB-INF/lib 目录下的类 和 WEB-INF/classes 目录下的类。
(4)最后加载 inter-deployment dependencies
这些是在 .ear 中定义的依赖,比如 依赖 .ear 中的 lib/,或者 .ear 中的 EJB jars。

3. 动态 module 的命名规则
(1).war 和 .jar 文件:deployment.DEPLOYMENT_NAME
比如 inventory.war 和 store.jar 的 module 名称是 deployment.inventory.war 和 deployment.store.jar。
(2).ear 中的 subdeployments:deployment.EAR_NAME.SUBDEPLOYMENT_NAME
比如 accounts.ear 中的 reports.war 的 module 名称是 deployment.accounts.ear.reports.war。

参考文献:
1. 《JBoss_Enterprise_Application_Platform-6.4-Development_Guide-en-US.pdf》第三章 Class Loading and Modules
2. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=
3. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?start=1
4. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=&start=2
5. http://stackoverflow.com/questions/34293402/jboss-how-can-to-exclude-javax-validation-in-jboss-deployment-structure

2016年3月17日星期四

EAP_047:EAP 6 类加载机制(一)

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0

在实际使用中,经常会遇到如下问题:
(1)开发者想使用一个新版本的类库,但 EAP 已经提供了一个旧版本的类库,如何在应用中使用指定版本的类库?
(2)如何在不同的应用中,使用不同版本的类库?

1. EAP 6 加载方式
JBoss EAP 6 使用 module class loading 方式加载类,开发者可以细粒度地控制应用需要加载的类,比如忽略 EAP 提供的类库,而使用自己的类库。
module 分两种:静态 module 与 动态 module。
静态 module 与 动态 module 只有打包方式的不同,加载方式是一样的。
module 只有在需要的时候才被加载。

1.1 静态 module
在 EAP_HOME/modules 目录下的都是静态 module,以 system/layers/base 目录开头,该目录下都是红帽提供的类库,主要是为了区分第三方的类库。
如果要加载第三方类库,请直接 EAP_HOME/modules 目录下创建在第三方类路径,不要在 system/layers/base 目录下创建。
这样的话,即使第三方类库已经在 system/layers/base 目录中有了,也会先加载第三方类库。

1.2 动态 module
指的是部署在 EAP 上的各种打包应用,比如 .jar、.war、.ear。
动态 module 由 EAP 运行时加载,module 可以配置 dependencies。

2. dependencies
dependencies 有两种: explicit dependencies 和 implicit dependencies。

2.1 explicit dependencies
静态 module 是定义在 modules.xml 文件中的,动态 module 是定义在 MANIFEST.MF 文件或 jboss-deployment-structure.xml 文件中的。
explicit dependencies 可以设置成 optional,如果该 dependency 加载失败,不影响整个 module 的加载。
但有一点要注意,如果加载 module 时,optional dependencies 加载失败,那么即使以后该 optional dependencies 可以加载了,也不会加载了。

2.2 implicit dependencies
implicit dependencies 是 EAP 自动加载的,比如 Java EE 6 API 就是 implicit dependencies。
部署时,通过在 jboss-deployment-structure.xml 文件中定义,可以配置 exclude 指定的 implicit dependencies。
比如应用不想使用某个 implicit dependency,而想使用自己的类库。

2.3 export=“true”
module A 依赖 module B,module B 依赖 module C。
module A 可以访问 module B 的类,module B 可以访问 module C 的类,但是 module A 不可以访问 module C 的类。
要想 module A 可以访问 module C 的类,其依赖的module B 中必须增加 export="true"。
<dependencies>
  <module name="moduleB" slot="1.1" export="true"/>
</dependencies>

参考文献:
1. 《JBoss_Enterprise_Application_Platform-6.4-Development_Guide-en-US.pdf》第三章 Class Loading and Modules
2. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=
3. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?start=1
4. http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-classloading?showall=&start=2
5. http://stackoverflow.com/questions/34293402/jboss-how-can-to-exclude-javax-validation-in-jboss-deployment-structure

2016年3月16日星期三

EAP_046:加载不同版本的定制化 modules (摘录+整理)

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0

1. 创建目录
(1)mkdir -p ~/mygit/CustomModuleTest
(2)cd ~/mygit/CustomModuleTest
(3)mkdir -p aaa/bbb/main aaa/bbb/1.0

2. 创建 1.0 版本的 module
(1)cd ~/mygit/CustomModuleTest/aaa/bbb/1.0
(2)vim Test.java
package aaa.bbb;

public class Test {

    static {
        System.out.println("nntaaa.bbb.Test class Loaded  [VERSION-1.0]");
    }

    public String sayHello(String name) {
        System.out.println("nntaaa.bbb.Test sayHello() called");
        return "Mr. " + name;
    }
}
(3)vim module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="aaa.bbb" slot="1.0">
    <resources>
        <resource-root path="Test1.0.jar"/>
    </resources>
</module>
(4)javac -d . Test.java
(5)jar cvf Test1.0.jar Test.java aaa/

3. 创建 1.2 版本的 module
(1)cd ~/mygit/CustomModuleTest/aaa/bbb/main
(2)vim Test.java
package aaa.bbb;

public class Test {

    static {
        System.out.println("nnt[1.2] aaa.bbb.Test class Loaded  [VERSION-1.2]");
    }

    public String sayHello(String name) {
        System.out.println("nnt[1.2] aaa.bbb.Test sayHello() called");
        return "Mr. [1.2] " + name;
    }
}
(3)vim module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="aaa.bbb">
  <resources>
    <resource-root path="Test1.2.jar"/>
  </resources>
</module>
(4)javac -d . Test.java
(5)jar cvf Test1.2.jar Test.java aaa/

4. 把两个 modules 复制到 JBOSS_HOME/modules 目录下
(1)cd ~/mygit/CustomModuleTest
(2)cp -r aaa /Users/maping/Redhat/eap/jboss-eap-6.4/modules/

5. 编写 web 应用
(1)index.jsp
<html>
  <head>
    <title>JBoss Module Testing
    </title>
  </head>
  <body>

    <%
       aaa.bbb.Test test=new aaa.bbb.Test();
       System.out.println("test.sayHello(JBossAS7) = "+test.sayHello("JBossAS7"));
       out.println("test.sayHello(JBossAS7) = "+test.sayHello("JBossAS7"));
    %>
    Hi Check the Console/Log of your JBoss
  </body>
</html>
(2)WEB-INF/web.xml
<web-app>
  <display-name>
    Module Demo JBposs AS7
  </display-name>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>
(3)WEB-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="aaa.bbb" slot="1.0"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>

6. 测试
启动 EAP
(1)打包并部署应用,访问 http://localhost:8080/my-webapp/index.jsp
会发现此时,在Console中,输出的是1.0版本的信息。
(2)修改WEB-INF/jboss-deployment-structure.xml,去掉slot="1.0",重新打包,发布,访问。
会发现此时,在Console中,输出的是1.2版本的信息。

参考文献:
1. http://middlewaremagic.com/jboss/?p=1933

2016年2月6日星期六

EAP_045:单机环境下 EAP 单节点复杂场景开箱性能指标

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0 + DayTrader 3.0

1. 首先部署DayTrader应用,请参看《JBoss_008:部署DayTrader应用》。

2. 复杂场景
访问http://localhost:8080/daytrader/scenario即可。
这个Servlet会随机访问Home、Account、Portfolio、Quotes等页面,因此只需要访问这个URL即可。

3. 测试
100 个线程,运行120秒,每个采样器调动之间休息5ms。
./bin/jmeter.sh -n -t ./test/DayTraderTestPlan-Scenario.jmx -l ./result/DayTraderTestPlan-Scenario_`date +'%y%m%d%H%M%S'`.csv


参考文献:
1. https://mojo.redhat.com/docs/DOC-970988

EAP_044:单机环境下 EAP 单节点EJB Profile开箱性能指标

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0 + DayTrader 3.0

1. 首先部署DayTrader应用,请参看《JBoss_008:部署DayTrader应用》。

2. EJB Profile 共有11个测试用例
(1)PingServlet2Session   
测试对无状态 Session EJB 的 servlet 调用的关键功能。Session EJB 执行一个简单的计算并返回结果。
(2)PingServlet2Entity   
测试对 EJB 3.0 容器托管实体的 servlet 调用的关键功能。在这个测试中,EJB 实体表示数据库表中的一行数据。
(3)PingServlet2Session2Entity   
测试 Session EJB 到 Entity EJB 路径的完整 servlet,以从数据库检索一行数据。(4)PingServlet2Session2EntityCollection   
测试通过调用一个 Session EJB 扩展前面的 EJB Entity 测试,该 Session EJB 在返回一组 Entity 对象的 Entity 上使用一个 finder 方法。所有对象由 servlet 显示。
(5)PingServlet2Session2CMROne2One   
测试通过一个 EJB 3.0 CMR 一对一关系驱动 Entity EJB 获得另一个 Entity EJB 的数据。(6)PingServlet2Session2CMROne2Many   
测试通过一个 EJB 3.0 CMR 一对多关系驱动 Entity EJB 获得另一个 Entity EJB 的数据。
(7) PingServlet2Session2JDBC   
测试 Session EJB 到 JDBC 路径的完整 servlet,从数据库检索一行数据。
(8) PingServlet2Session2JDBCCollection   
通过调用一个 Session EJB 到 JDBC 的路径(从数据库返回多个行)扩展前面的 JDBC 测试。(9)PingServlet2MDBQueue   
要求消息根据消息驱动(MDB)进行排队。每个对 servlet 的请求向队列发出一条消息。MDB 异步接收消息并每隔 100 条消息输出一次消息传递统计数据。
(10) PingServlet2MDBTopic   
将消息驱动到一个基于主体的发布/订阅 MDB。每个对 servlet 的请求向 Topic 发布一条消息。TradeStreamMDB 异步接收消息并每隔 100 条消息输出一次消息传递统计数据。该主题的其他订阅者也将接收消息。
(11)PingServlet2TwoPhase   
驱动一个 Session EJB,它将使用 findByPrimaryKey(DB 访问)调用 Entity EJB,然后通过一个 JMS 队列(消息访问)向 MDB 发布一条消息。这些操作被封装到一个全局的分两阶段的事务中并被提交。

3. 测试
100 个线程,运行120秒,每个采样器调动之间休息5ms。
 ./bin/jmeter.sh -n -t ./test/DayTraderTestPlan-EJBProfile.jmx -l ./result/DayTraderTestPlan-EJBProfile_`date +'%y%m%d%H%M%S'`.csv

EAP_043:单机环境下 EAP 单节点Web Profile开箱性能指标

环境:OS X EI Capitan 10.11.3 + JBoss EAP 6.4.0 + DayTrader 3.0

1. 首先部署DayTrader应用,请参看《JBoss_008:部署DayTrader应用》。
 (1)DayTrader 架构图
 (2)部署成功后,访问 http://localhost:8080/daytrader/

2. Web Profile 共有15个测试用例
(1)PingHtml
访问静态 HTML页面。
(2)PingServlet
通过服务器端 servlet 处理,测试基本的动态 HTML 创建。
(3)PingServletWriter
访问通过对格式化输出使用 PrintWriter(与 PingServlet 使用的输出流相对)而扩展 PingServlet。
(4)PingServlet2Include
测试响应所含内容。Servlet 1 包含 Servlet 2 的响应。
(5)PingServlet2Servlet
测试请求分发。Servlet 1 作为控制器创建一个新的 JavaBean 对象并转发请求,其中 JavaBean 被添加到 Servlet 2。Servlet 2 通过 Servlet 请求对象获得对 JavaBean 的访问,并根据 JavaBean 数据提供动态 HTML 输出。
(6)PingJSP
测试对 JSP 的直接调用,该调用通过 JSP 脚本提供服务器端动态 HTML。
(7)PingJSPEL
测试对 JSP 的直接调用,该调用通过 JSP 脚本提供服务器端动态 HTML 和新 JSP V2.0 Expression Language 的使用
(8)PingServlet2JSP
测试一个常用的设计模式,其中请求被发送给提供服务器端控制处理的 servlet。该 servlet 创建了一个具有动态设置属性的 JavaBean 对象并通过 RequestDispatcher 将 bean 转发给 JSP。JSP 获得对 JavaBean 的访问并根据 JavaBean 数据提供具有动态 HTML 输出的格式化显示。
(9)PingHTTPSession1
通过为每个单独用户创建惟一会话 ID 测试基本的 HTTP 会话功能。ID 被存储在用户会话中,并通过每一个用户请求访问和显示。
(10)PingHTTPSession2
通过每隔 5 个用户访问使 HTTP 会话失效来进一步扩展前面的测试。这可以测试 HTTPSession 的创建和销毁。
(11)PingHTTPSession3
测试HTTPSession存储大对象的能力。每个对象是个数组,每个数组元素125 bytes,可以动态设置数组大小。
(12)PingJDBCRead
测试使用JDBC DataSource(通过PrepareStatement方式)读数据能力,返回一行数据。
(13)PingJDBCWrite
测试使用JDBC DataSource(通过PrepareStatement方式)写数据能力,修改一行数据。
(14)PingServlet2JNDI
测试在Servlet中通过JNDI查找 JDBC DataSource能力。
(15)Explicit GC
强制应用服务器执行一次垃圾回收。对比垃圾回收前后的内存数据。

3. 测试
100 个线程,运行120秒,每个采样器调动之间休息5ms。
由于Explicit GC 耗时比较长,会影响其他采样器,因此不包括在测试之中。
 ./bin/jmeter.sh -n -t ./test/DayTraderTestPlan-WebProfile.jmx -l ./result/DayTraderTestPlan-WebProfile_`date +'%y%m%d%H%M%S'`.csv



参考文献:
1. http://www.ibm.com/developerworks/websphere/techjournal/1208_hare/1208_hare.html
2. https://developer.ibm.com/wasdev/docs/measuring-performance-daytrader-3-benchmark-sample/

2015年10月6日星期二

EAP_042:基于角色控制访问EAP 6控制台

环境:JBoss EAP 6.4.0

需求来自客户,假设客户有3个角色,4个用户:
(1)Andy:系统管理员,可以做任何事情。
(2)Bob:开发项目经理,负责部署应用和相关配置。
(3)Clare 和 Dave:开发人员,只能查看应用配置,不能修改。

1. 创建用户
(1)运行./add-user.sh,分别创建Andy、Bob、Clare、Dave管理型用户。
(2)cp mgmt-user.properties mgmt-group.properties myeap/configuration
(3)cp standalone.xml standalone-rbac.xml
(4)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-rbac.xml -Djboss.socket.binding.port-offset=10000
(5)访问 http://localhost:19990/,用刚创建的用户登录,发现可以做任何事情,不符合用户要求。

2. 修改standalone-rbac.xml如下

 <management>
    <access-control provider="rbac">
        <role-mapping>
            <role name="SuperUser">
                <include>
                    <user name="$local"/>
                    <user name="Andy"/>
                </include>
            </role>
            <role name="Deployer">
                <include>
                    <group alias="group-lead-devs" name="lead-developers"/>
                </include>
            </role>
            <role name="Monitor">
                <include>
                    <group alias="group-standard-devs" name="developers"/>
                </include>
            </role>
        </role-mapping>
    </access-control>
</management>

重新启动,这次发现各个用户按照各自角色行使权力。
使用andy用户登录,点击Administration->Role Assignment,可以看到所有用户和组的定义。

参考文献:
1. http://blog.c2b2.co.uk/2014/09/configuring-rbac-in-jboss-eap-and.html
2. http://blog.c2b2.co.uk/2015/01/configuring-rbac-in-jboss-eap-and.html
3. http://blog.arungupta.me/role-based-access-control-wildfly-8/
4. https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.2/html/Security_Guide/Supported_Roles.html

EAP_041:EAP 功能演示 8:负载均衡

环境:JBoss EAP 6.4.0 + RHEL 6.6 + EWS Httpd 2.1.0

安装和配置好Apache Httpd Server 和 mod_cluster后,就可以为JBoss EAP 配置负载均衡了。

1. Standalone Mode 集群下的负载均衡配置
(1)确定Apache Httpd  Server所在机器的IP 地址,比如:192.168.56.101

(2)修改node1的配置文件如下:
<subsystem xmlns="urn:jboss:domain:modcluster:1.2">
            <mod-cluster-config advertise-socket="modcluster" connector="ajp" proxy-list="192.168.56.101:80" balancer="myBalancer">
                <dynamic-load-provider>
                    <load-metric type="busyness"/>
                </dynamic-load-provider>
            </mod-cluster-config>
        </subsystem>
(3)node2的配置文件和node1做一样的修改
(4)启动node1,这里必须指定node1所在的机器的IP地址,比如:192.168.56.1
./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node1 -c standalone-ha-mod_cluster.xml -b 192.168.56.1 -bmanagement 192.168.56.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=100 -Djboss.node.name=node1
(5)启动node2,这里必须指定node2所在的机器的IP地址,比如:192.168.56.1
./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node2 -c standalone-ha-mod_cluster.xml -b 192.168.56.1 -bmanagement 192.168.56.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=200 -Djboss.node.name=node2

(6)访问http://192.168.56.1:8180/cluster_test
(7)访问http://192.168.56.1:8280/cluster_test
(8)访问http://192.168.56.101/cluster_test,做负载均衡测试。

 2. Domain Mode 集群下的负载均衡配置
(1)cp machine1/domain/configuration/domain.xml machine1/domain/configuration/domain-mod_cluster.xml
(2)修改domain-mod_cluster.xml
 <subsystem xmlns="urn:jboss:domain:modcluster:1.2">
                <mod-cluster-config advertise-socket="modcluster" connector="ajp" proxy-list="192.168.56.101:80" balancer="myBalancer">
                    <dynamic-load-provider>
                        <load-metric type="busyness"/>
                    </dynamic-load-provider>
                </mod-cluster-config>
            </subsystem>
(3)启动machine1, 这里必须指定machine1所在的机器的IP地址,比如:192.168.56.1
./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine1/domain/ --domain-config=domain-mod_cluster.xml --host-config=host-master.xml -b 192.168.56.1 -bmanagement 192.168.56.1
(4)启动machine2, 这里必须指定machine2所在的机器的IP地址,比如:192.168.56.1
./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine2/domain/ --host-config=host-slave.xml -b 192.168.56.1 -Djboss.management.native.port=19999 -Djboss.domain.master.address=192.168.56.1
(5)启动machine3, 这里必须指定machine3所在的机器的IP地址,比如:192.168.56.1
./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine3/domain/ --host-config=host-slave.xml -b 192.168.56.1 -Djboss.management.native.port=29999 -Djboss.domain.master.address=192.168.56.1
(6)访问http://192.168.56.1:8230/cluster_test
(7)访问http://192.168.56.1:9080/cluster_test
(8)访问http://192.168.56.101/cluster_test,做负载均衡测试。

2015年10月5日星期一

EAP_040:安装与配置 mod_cluster

环境:RHEL 6.6 + EWS Httpd 2.1.0

说明,这里安装的是JBoss EAP 6.4.0 自带的mod_cluster,不是从Apache 社区下载的mod_cluster。

1. 访问 access.redhat.com,找到JBoss EAP 6.4.0
(1)检查操作系统环境:
# uname -r
2.6.32-504.el6.x86_64
(2)选择对应的下载软件
点击 Red Hat JBoss Enterprise Application Platform 6.4.0 Webserver Connector Natives for RHEL 6 x86_64
下载后文件名称是:jboss-eap-native-webserver-connectors-6.4.0-RHEL6-x86_64.zip

2. 安装 mod_cluster
(1)# cd /opt/jbshome
(2)# unzip jboss-eap-native-webserver-connectors-6.4.0-RHEL6-x86_64.zip
(3)# cd jboss-eap-6.4/modules/system/layers/base/native/lib64/httpd/modules
(4)# cp *.so /opt/jbshome/jboss-ews-2.1/httpd/modules/
(5)cd /opt/jbshome/jboss-ews-2.1/httpd/modules
(6)rm mod_jk.so
(7)# cp /opt/jbshome/software/jboss-eap-6.4/modules/system/layers/base/native/etc/httpd/conf/mod_cluster.conf /opt/jbshome/jboss-ews-2.1/httpd/conf.d
(8)# vim /opt/jbshome/jboss-ews-2.1/httpd/conf.d/mod_cluster.conf
修改如下:
# mod_proxy_balancer should be disabled when mod_cluster is used
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule slotmem_module modules/mod_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule advertise_module modules/mod_advertise.so

MemManagerFile /var/cache/mod_cluster

<IfModule manager_module>
  #Listen 80
  <VirtualHost *:80>
    <Directory />
      Order deny,allow
      Allow from all
    </Directory>
    ServerAdvertise Off
    EnableMCPMReceive On
    ManagerBalancerName myBalancer
    KeepAliveTimeout 60
    MaxKeepAliveRequests 0
   <Location /mod_cluster-manager>
      SetHandler mod_cluster-manager
      Order deny,allow
      Allow from all
   </Location>
  </VirtualHost>
</IfModule>

 (9)# cd /opt/jbshome/jboss-ews-2.1
(10)# chown -R apache:apache httpd
 修改完后,运行 ls -l 检查一下是否改过来了。

3. 重启 Apache Httpd Server
(1)# cd /opt/jbshome/jboss-ews-2.1/httpd/sbin
(2)# ./apachectl restart
(3)访问 http://localhost/mod_cluster-manager

4. 为了能够让其它机器能够访问Apache Httpd Server 所在的机器,需要把防火墙关掉:
(1)iptables -F
(2)iptables -L -n
(3)临时停掉防火墙:/etc/init.d/iptables stop
(4)彻底关掉防火墙:chkconfig iptables off
(5)访问 http://<IP_ADDRESS>/mod_cluster-manager

5. 如果还不能访问http://<IP_ADDRESS>/mod_cluster-manager,关闭SELinux
 (1)vim /etc/sysconfig/selinux,内容如下:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
执行 # setenforce 0, 设置SELinux 成为permissive模式。
说明:如果执行# setenforce 1,将会把SELinux 设置成为enforcing模式。
执行# getenforce,查看确认SELinux 已经设置为permissive模式。
如果为了省事,可以直接设置SELINUX=disabled,这样重启以后,不用每次执行setenforce 0。

EAP_039:安装 Apache HTTP Server

环境:RHEL 6.6 + EWS Httpd 2.1.0

说明,这里安装的是JBoss EAP 6.4.0 自带的Apache HTTP Server,不是从Apache 社区下载的Httpd Server。
之所以使用 JBoss EAP 6.4.0 自带的Apache HTTP Server,是为了将来使用它作为负载均衡器。
当然,你使用Apache 社区下载的Httpd Server作为负载均衡器也可以,但通常推荐使用和JBoss EAP 自带的Apache HTTP Server,这样安装更绿色,更简单,更匹配。
另外比Linux自带的Apache Httpd Server管理起来也方便,所有的东西都在解压后的目录中,不用到其它地方找,而且很容易在一台机器上安装多个Apache Httpd Server。

1. 访问 access.redhat.com,找到JBoss EAP 6.4.0,
(1)检查操作系统环境:
# uname -r
2.6.32-504.el6.x86_64
(2)选择对应的下载软件
点击 Red Hat JBoss Enterprise Application Platform 6.4.0 Apache HTTP Server for RHEL 6 x86_64
下载后文件名称是:jboss-ews-httpd-2.1.0-RHEL6-x86_64.zip

2. 需要 apr-util 包的支持
  # yum install apr-util

3. 安装 Apache HTTP Server
(1)# cd /opt/jbshome
(2)# unzip jboss-ews-httpd-2.1.0-RHEL6-x86_64.zip
(3)# cd jboss-ews-2.1/httpd
(4)因为不需要用到kerberos认证,删除以下文件,以免启动的时候报错。
  # rm conf.d/auth_kerb.conf
  # rm modules/mod_auth_kerb.so
(5)./.postinstall
(6)检查有没有 apache 用户、用户组
  # id apache
  uid=48(apache) gid=48(apache) 组=48(apache)
  如果没有,需要创建
  # getent group apache >/dev/null || groupadd -g 48 -r apache
  # getent passwd apache >/dev/null || useradd -r -u 48 -g apache -s /sbin/nologin -d /opt/jbshome/httpd/www -c "Apache" apache
 修改httpd目录的owner为apache
  # chown -R apache:apache httpd
 修改完后,运行 ls -l 检查一下是否改过来了。

4. 启动与停止Apache HTTP Server
(1)# cd /opt/jbshome/jboss-ews-2.1/httpd/sbin/
(2)./apachectl start
 注意,这里apachectl 前面必须加./,否则启动的是系统自带的Apache Httpd Server。
(3)./apachectl stop
 注意,这里apachectl 前面必须加./,否则停止的是系统自带的Apache Httpd Server。
(4)检查Apache HTTP Server 是否起来了
  # netstat -anp | grep httpd
tcp        0      0 :::80                       :::*                        LISTEN      5298/httpd
(5)访问 http://localhost

EAP_038:EAP 6 功能演示 7:集群(Domain mode)

环境:JBoss EAP 6.4.0


1. 配置 Domain Mode 集群
(1)mkdir machine1
(2)cp -r ./jboss-eap-6.4/domain/ machine1/domain
(3)mkdir machine2
(4)cp -r ./jboss-eap-6.4/domain/ machine2/domain
(5)mkdir machine3
(6)cp -r ./jboss-eap-6.4/domain/ machine3/domain
(7)vim machine1/domain/configuration/domain.xml,找到full-ha profile,修改
     <subsystem xmlns="urn:jboss:domain:messaging:1.4">
        
<hornetq-server>
            <clustered>true</clustered>
            <persistence-enabled>true</persistence-enabled>
            <cluster-password>welcome@1</cluster-password>
     因为 message subsystem 使用自己的集群实现机制,不使用 JGroups 作为集群实现机制,需要增加安全认证。 
(8)./domain.sh --host-config=host-master.xml -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine1/domain/
(9)./domain.sh --host-config=host-slave.xml -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine2/domain/ -Djboss.management.native.port=19999 -Djboss.domain.master.address=127.0.0.1
或者 如果想在Shutdown domain controller的情况下,想启动/停止host controller,需要增加参数
 ./domain.sh --host-config=host-slave.xml -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine2/domain/ -Djboss.management.native.port=19999 --backup -Djboss.domain.master.address=127.0.0.1
然后
./domain.sh --host-config=host-slave.xml -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine2/domain/ -Djboss.management.native.port=19999 --cached-dc -Djboss.domain.master.address=127.0.0.1
(10)./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine3/domain/ --host-config=host-slave.xml -Djboss.management.native.port=29999 -Djboss.domain.master.address=127.0.0.1
或者 如果想在Shutdown domain controller的情况下,想启动/停止host controller,需要增加参数
./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine3/domain/ --host-config=host-slave.xml -Djboss.management.native.port=29999 --backup -Djboss.domain.master.address=127.0.0.1
然后
./domain.sh -Djboss.domain.base.dir=/Users/maping/Redhat/eap/demo/machine3/domain/ --host-config=host-slave.xml -Djboss.management.native.port=29999 --cached-dc -Djboss.domain.master.address=127.0.0.1


(11)http://localhost:9990/console/ 介绍 Domain 配置,启动/停止 Server, 部署 cluster_test.war 到 other-server-group 上。

    注意,Domain Mode 下,部署应用是发布到 Server Groups 上,而不是 Servers 上,而且不能只部署到 Server Group 中的某个Server,要部署就是部署到该 Server Group 中的所有 Servers。
(12)http://localhost:8230/
cluster_test/
(13)http://localhost:9080/
cluster_test/ 

2.
在 Domain Mode 下 Undeploy 一个应用的步骤如下:
(1)在 Server Group Deployments 中,先 disable 该应用,再 remove 该应用。
(2)在 DeploymentContent 中,将其从 Content Repository 中 remove 掉。

2015年10月1日星期四

EAP_037:EAP 6 功能演示 6:集群(Standalone mode)

环境:JBoss EAP 6.4.0

1. 集群的作用
(1)High Availability (HA) :服务的高可用性
(2)Scalability:服务的可扩展性
(3)Failover:服务的故障转移性
(4)Fault Tolerance:服务的容错性

2.  在EAP 6 中,配置好集群后,集群服务并不是一直起作用,而是按需启动和停止, 取决于应用中是否配置了 distributable 特性。
在cluster_test.war中web.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <display-name>cluster_test</display-name>
 <distributable/>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>
</web-app> 

3. 在EAP 6 中,实现集群的组件是以下三个:
(1)org.jboss.as.clustering.jgroups:提供server之间的通信、诊断、发现。
(2)org.jboss.as.clustering.infinispan:提供缓存,以及对象的复制。
(3)org.jboss.as.modcluster:负载均衡器,如果使用 Apache httpd。

4. 配置 Standalone Mode 集群
(1)mkdir node1
(2)cp -r ./jboss-eap-6.4/standalone/configuration ./jboss-eap-6.4/standalone/deployments ./jboss-eap-6.4/standalone/lib node1
(3)mkdir node2
(4)cp -r ./jboss-eap-6.4/standalone/configuration ./jboss-eap-6.4/standalone/deployments ./jboss-eap-6.4/standalone/lib node2
(5)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node1 -c standalone-ha.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=100 -Djboss.node.name=node1
或者使用 TCP 配置
./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node1 -c standalone-ha-tcp.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=100 -Djboss.node.name=node1
(6)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node2 -c standalone-ha.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=200 -Djboss.node.name=node2
或者使用 TCP 配置
./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node2 -c standalone-ha-tcp.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=200 -Djboss.node.name=node2
(7)http://localhost:10090/console/ 部署 cluster_test.war
(8)http://localhost:10190/console/ 部署 cluster_test.war
(9)http://localhost:8180/cluster_test/
(10)http://localhost:8280/cluster_test/

EAP_036:EAP 6 JVM 设置

环境:JBoss EAP 6.4.0

1. Standalone mode
在 Standalone mode 中,由于只有一个进程,即 EAP Server,其 JVM 配置在 standalone.conf中,内容如下:
if [ "x$JAVA_OPTS" = "x" ]; then
   JAVA_OPTS="-Xms1303m -Xmx1303m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true"
   JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"
   JAVA_OPTS="$JAVA_OPTS -Djboss.modules.policy-permissions=true"

2. Domain mode
在 Domain mode 中,Host Controller 负责启动和停止 EAP Server,所以 EAP Server 的 JVM 配置也由 Host Controller 负责。
domain.conf 中的 JVM 配置是 Host Controller 的 JVM 配置,不是 EAP Server 的配置,内容如下:
if [ "x$JAVA_OPTS" = "x" ]; then
   JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true"
   JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"
   JAVA_OPTS="$JAVA_OPTS -Djboss.modules.policy-permissions=true"

在 Domain mode 中的 EAP Server 的 JVM 配置由以下三个地方决定:
(1)host.xml 文件中的 <jvm> 定义
(2)domain.xml 文件中的 <server-group> 定义
(3)host.xml 文件中的 <server> 定义
从下往上,在 <server>中的 JVM 定义覆盖在 <server-group> 中的 JVM 定义,在 <server-group> 中的 JVM 定义覆盖<jvm> 中的 JVM 定义。

例1:在 host.xml 文件中的 <jvm> 定义
<jvms>
     <jvm name="small_jvm">
         <heap size="64m" max-size="128m"/>
     </jvm>
<jvm name="production_jvm">
    <heap size="2048m" max-size="2048m"/>
    <permgen size="128m" max-size="512m"/>
    <stack size="1024k"/>
    <jvm-options>
     <option value="-XX:-UseParallelGC"/>
    </jvm-options>
</jvm>
  
</jvms>

例2:<server-group> 和 <server> 定义都可以引用 jvm 定义,引用的同时,也可以覆盖其中的JVM配置。

<server-group name="groupA" profile="default">
    <jvm name="production_jvm"/>
    <socket-binding-group ref="standard-sockets"/>
</server-group>

<server-group name="groupB" profile="default">
       <jvm name="production_jvm">
           <heap size="1024m" max-size="1024m"/>
       </jvm>
       <socket-binding-group ref="standard-sockets"/>
</server-group>

<server name="test_server" group="groupB" auto-start="true">
    <socket-binding-group ref="standard-sockets" port-offset="300"/>
 <jvm name="production_jvm">
      <heap size="256m"/>
    </jvm>
</server>

3. 检查某个 EAP Server 使用内存的情况: ps -eaf | grep test_server

2015年9月30日星期三

EAP_035:EAP 功能演示 5:数据库认证

环境:JBoss EAP 6.4.0

1.  配置derby 数据源
请参考《EAP 6 功能演示2 :DataSource 部署》。


2. 创建数据库表
这里使用之前已经创建好的 derby:demoDB
(1)cd /Users/maping/Apache/db-derby/bin
        进入SQL交互 ./ij
    ij> Connect 'jdbc:derby:demoDB;user=demo;password=demo';
    ij> CREATE TABLE principles ( principal_id VARCHAR(64) primary key,password VARCHAR(64));
    ij> CREATE TABLE roles ( principal_id VARCHAR(64),user_role VARCHAR(64),role_group VARCHAR(64));
    ij>INSERT INTO principles VALUES('TestUserOne','PasswordOne');
    ij>INSERT INTO principles VALUES('TestUserTwo','PasswordTwo');
    ij>INSERT INTO roles VALUES('TestUserOne','TestRoleOne','TestUserOneGroup');
    ij>INSERT INTO roles VALUES('TestUserTwo','TestRoleTwo','TestUserTwoGroup');
(2)cd /Users/maping/Apache/db-derby/bin
    启动 ./startNetworkServer
    停止 ./stopNetworkServer

3. 修改 EAP 配置文件
(1)cp standalone.xml standalone-database-auth.xml
(2)vim standalone-database-auth.xml
<security-domain name="DBAuthTest" cache-type="default">
                    <authentication>
                        <login-module code="Database" flag="required">
                            <module-option name="dsJndiName" value="java:jboss/datasources/DemoDataSource"/>
                            <module-option name="principalsQuery" value="select password from  PRINCIPLES where principal_id=?"/>
                            <module-option name="rolesQuery" value="select user_role, 'Roles' from  ROLES where  principal_id=?"/>
                        </login-module>
                    </authentication>
                </security-domain>

如果有必要,可以输出详细的安全日志,用于调试
<category name="org.jboss.security">
   <priority value="TRACE"/>
</category>

4. 修改Web应用配置文件
(1)web.xml
    <security-constraint>
        <display-name>Constraint-0</display-name>
        <web-resource-collection>
            <web-resource-name>Constraint-0</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
   
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/jsp/login.jsp</form-login-page>
            <form-error-page>/jsp/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>
   
    <security-role>
        <role-name>TestRoleOne</role-name>
    </security-role>

(2)jboss-web.xml
    <security-domain>java:/jaas/DBAuthTest</security-domain>

5. 部署example_auth.war

6. 访问:http://localhost:18080/example_auth/
需要登录,输入用户:TestUserOne 口令:PasswordOne。

参考文献:
1. http://middlewaremagic.com/jboss/?p=387

EAP_034:EAP 6 功能演示 4:JMS

环境:JBoss  EAP 6.4

1. 概念与术语
(1)HornetQ:JBoss EAP 6 使用 HornetQ 作为 JMS Provider。
(2)HornetQ 使用 connectors 和 acceptors。其中,
connector 定义了 JMS Client 如何连接到 HornetQ server。
acceptor 定义了 HornetQ server 接受哪种类型的连接。
分别有两种类型的 connector 和 acceptor。
(1)invm: Intra Virtual Machine,client 和 server 在同一个 JVM 中。
(2)netty: client 和 server 在不同的 JVM 中。
注意,connector 和 acceptor 必须匹配使用,invm connector 只能连到 invm acceptor;netty connector 只能连接到 netty acceptor。
(3)Connection Factory:为 connector 定义了一系列的配置参数,总共有35个。
默认定义了两个 InVmConnectionFactory 和 RemoteConnectionFactory。
 (4)durable:A durable destination is one where a receiver can retrieve a message that was sent while the receiver was not active.
默认情况下, Queue是 durable的,Topic是非 durable 的。

2. 演示
(1)cp standalone-full.xml standalone-full-jms.xml
(2)vim standalone-full-jms.xml
   <jms-queue name="myQueue">
      <entry name="java:jboss/queue/myQueue"/>
      <durable>true</durable>
   </jms-queue>
   <jms-topic name="myTopic">
      <entry name="java:jboss/topic/myTopic"/>
   </jms-topic>
(3)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-full-jms.xml -Djboss.socket.binding.port-offset=10000
(4)部署 JMSTest.war
(5)访问:http://localhost:18080/JMSTest/run

Connection Factory JNDI name:   java:/ConnectionFactory
Destination JNDI name: java:jboss/queue/myQueue 或 java:jboss/topic/myTopic

这里的Connection Factory JNDI name 不能使用 java:jboss/exported/jms/RemoteConnectionFactory,这个用于远程JMS调用,需要验证。
前缀java:jboss/exported/表明这个资源可以被客户端找到,即使不在EAP这个容器中。
 
3. JMSTestServlet.java

package com.jboss.jms;

import java.io.IOException;
import java.io.PrintWriter;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class JMSTestServlet
 */

public class JMSTestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
     
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JMSTestServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Display the JMSTest HMTL form
        request.getRequestDispatcher("jms_form.html").include(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("

Results of JMSTest

");
        String factoryName = request.getParameter("factoryName");
        String  destName = request.getParameter("destName");
        Context context = null;      
        ConnectionFactory connectionFactory = null;
        Destination dest = null;
        out.println("Looking up Connection Factory: " + factoryName + "
");
        try {
            context = new InitialContext();
            connectionFactory = (ConnectionFactory) context.lookup(factoryName);
        } catch (Exception e) {
            out.println("Connection Factory lookup failed: " + e.getMessage() + "
");
            e.printStackTrace();
            return;
        }
        out.println("Successfully found Connection Factory: " + factoryName + "

");
        out.println("Looking up Destination: " + destName + "
");
        try {
            dest = (Destination) context.lookup(destName);
        } catch(Exception e) {
            out.println("Destination lookup failed: " + e.getMessage() + "
");
            e.printStackTrace();
            return;
        }
        out.println("Successfully found Destination: " + destName + "
");
        //If we get this far, both the factory and destination have been found successfully,
        //so let's send a few test messages
        int numOfTests = Integer.parseInt(request.getParameter("numOfTests"));
        if(numOfTests > 0) {
            out.println("Attempting to send " + numOfTests + " test messages to destination...
");
            try {
                Connection connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(dest);
                TextMessage message = session.createTextMessage();
                for(int i = 1; i <= numOfTests; i++) {
                    message.setText("This is test message " + i);
                    out.println("Sending test message: " + i + "
");
                    producer.send(message);
                }
            } catch(Exception e) {
                out.println("An exception occurred while sending test messages: " + e.getMessage() + "
");
            }
        }
    }

}

2015年9月29日星期二

EAP_033:EAP 6 功能演示 3:日志管理

环境:JBoss EAP 6.4

日志由 Logging Subsystem 负责管理和定义。

1. 日志的3个组件
(1)Handlers: 定义事件将在哪里以及如何被记录。
    默认情况下,定义了两个Handlers:
    CONSOLE: 记录事件到控制台窗口
    FILE: 记录事件到文件:server.log.
(2)Loggers: 日志记录器,按不同目录划分事件。
(3)Root Logger: 根日志记录器,所有日志记录器的根。

2. 日志级别
(1)FATAL: a fatal event means the service cannot continue.
(2)ERROR: a problem that may or may not cause the service to continue running.
(3)WARN: a potentially harmful event has occurred.
(4)INFO: nothing went wrong - just an informational event. 默认的日志级别
(5)DEBUG: extra information useful for debugging errors.
(6)TRACE: allows for deep probing of the JBoss server behavior.

3. 日志文件的位置 

3.1 Standalone Mode:[eap_install_dir]/standalone/log
(1)gc.log.0.current 关于这个文件的具体配置在 standalone.sh中。
(2)server.log 可以按时间或大小滚动该日志文件,关于这个文件的具体配置在standalone.xml中的logging subsystem 中。

3.2 Domain Mode
(1)domain/log/host-controller.log 记录 Host Controller(Domain Controller) 启动时的事件。
(2)domain/log/process-controller.log 记录 启动和停止本机进程时的事件。
(3)domain/servers//log/server.log 记录每个server的事件。

3.3 日志的环境变量:jboss.server.log.dir
jboss.server.log.dir 的位置相对于 jboss.server.base.dir,一般来说只需修改后者即可。


4. 内置的6个Handlers 
注意:Handler 自身不能激活,需要定义在<logger>或<root-logger>中才能激活。

(1)Console handler

写到控制台的handler,定义在 <console-handler> 中。
    <console-handler name="CONSOLE" autoflush="true">
           <level name="INFO"/>
           <formatter>
             <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
           </formatter>
    </console-handler>

(2)File handler
 
写到文件的handler,定义在 <file- handler> 中。

(3)Periodic-rotating file handler
  按时间滚动的文件handler,定义在 <periodic-rotating-file-handler> 中。
<periodic-rotating-file-handler name="FILE" autoflush="true">
    <level name="INFO"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="server.log"/>
    <suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
其中,suffix 定义多长时间滚动一次日志,yyy-MM-dd表示一天滚动一次,yyy-MM-dd.HH表示一小时滚动一次,yyy-MM表示一个月滚动一次。

(4)Size-rotating file handler

按大小滚动的文件handler,定义在 <size-rotating-file-handler> 中。
<size-rotating-file-handler name="FILE_BY_SIZE" autoflush="true">
    <level name="INFO"/>
    <encoding value="UTF-8"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="production-server.log"/>
    <rotate-size value="2048"/>
    <max-backup-index value="3"/>
</size-rotating-file-handler>
其中,滚动大小 2048K,即2M。最多保留3个备份日志,加上一个当前的日志。


(5)Async handler
异步记录handler,
它不是一个独立的handler,它只是给现有的handler添加上异步的特性。
定义在 <async-handler> 中。
<async-handler name="ASYNC">
    <level name="INFO"/>
    <queue-length value="1024"/>
    <overflow-action value="BLOCK"/>
    <subhandlers>
        <handler name="FILE"/>
    </subhandlers>
</async-handler>
在 <subhandlers></subhandlers>之间可以增加很多handler。
overflow-action 定义当日志队列满的情况下,如何处理新来的事件,BLOCK 阻止直到有了新的空间,DISCARD,丢弃。 


(6)Syslog handler
允许多个应用发送事件信息到远程日志服务器,具体怎么使用还有待实验验证。

定义在 <syslog-handler> 中。
<syslog-handler name="SYSLOG">
    <level name="INFO"/>
    <server-address value="172.25.2.9"/>
    <hostname value="student2"/>
    <port value="514"/>
    <app-name value="MY_APP"/>
</syslog-handler>
 

5. Loggers
Handlers 定义“在哪”和“如何”记录一个事件,Loggers定义“内容
(日志分类)”和“何时(日志级别)”记录一个事件。

(1)例子1
<logger category="org.jboss.seam">
    <level name="INFO"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</logger>

(2)例子2
<logger category="org.apache">
    <level name="WARN"/>
</logger>
<logger category="org.apache.naming">
    <level name="ERROR"/>
</logger>
默认情况下,在Sub Logger中发生的事件,在Parent Logger中也会记录一遍,如果不想在Parent Logger中记录的话,可以在Sub Logger中设置use-parent-handlers = false。

(3)Root Logger
默认情况下,所有的Logger定义,都继承root logger的定义。
没有被Logger定义涉及的事件,都将按照以 root logger的定义来作用。
<root-logger>
    <level name="INFO"/>
    <handlers>
        <handler name="CONSOLE"/>
        <handler name="FILE"/>
    </handlers>
</root-logger>


在生产环境中,Root Logger 建议如下设置:
<root-logger>
    <level name="ERROR"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</root-logger>
 

6. 演示

6.1 定义 

(1)cp standalone.xml standalone-logger.xml
(2)vim standalone-logger.xml

 <size-rotating-file-handler name="FILE_BY_SIZE_ROTATING" autoflush="true">
                <level name="ERROR"/>
                <file relative-to="jboss.server.log.dir" path="production-server.log"/>
                <rotate-size value="1m"/>
                <max-backup-index value="3"/>
                <append value="true"/>
  </size-rotating-file-handler>

  <logger category="com.jboss.logtest" use-parent-handlers="false" >
                <level name="INFO"/>
                <handlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </handlers>
  </logger>


  <async-handler name="ASYNC">
                <level name="INFO"/>                 
                <queue-length value="1024"/>
                <overflow-action value="block"/>
                <subhandlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </subhandlers>
 </async-handler> 


6.2. 启动EAP,部署LogTest.war

./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-logger.xml -Djboss.socket.binding.port-offset=10000
 

6.3 访问:http://localhost:18080/LogTest/run
(1) 观察Console,发现没有任何应用的日志输出
这是因为use-parent-handlers = false,如果=true,Console中也会有应用日志信息,并且是INFO级别的,因为Root Logger是INFO级别的。
(2) 观察product-server.log,发现有如下输出:
10:27:30,282 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 1
10:27:30,282 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 1
10:27:30,283 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 2
10:27:30,283 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 2
这是FILE_BY_SIZE_ROTATING handler定义的日志级别是ERROR,而com.jboss.logtest logger 使用的就是这个handler。
也就是说,为每个应用定义自己的日志文件在JBoss EAP 中非常简单。
 (3)以异步的方式写文件

6.4. LogTester.java

package com.jboss.logtest;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.logging.Logger;

/**
 * Servlet implementation class LogTester
 */
public class LogTester extends HttpServlet {
    private static final long serialVersionUID = 1L;
    //private static final Log log = LogFactory.getLog(LogTester.class);
    private static final Logger log = Logger.getLogger(LogTester.class);


    /**
     * Default constructor.
     */
    public LogTester() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("

LogTester Application Version 1.0

");
        out.write("Loading this page generates multiple log events for the com.jboss.logtest category.
");
        out.write("Simply reload this page to generate all the log events again.
");
        out.close();
        for(int i = 1; i <= 20; i++) {
            log.debug("This is debug event number " + i);
            log.fatal("This is fatal event number " + i);
            log.info("This is info event number " + i);
            log.error("This is error event number " + i);
            log.trace("This is trace event number " + i);
            log.warn("This is warn event number " + i);
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

}