服务部署、运行及非功能特性详解
1. 示例部署与运行
在开始部署和运行示例之前,若尚未进行过相关操作,需编辑
examples.PROPERTIES
文件(此文件随本章代码一同下载),将其中的路径修改为与自身开发环境相匹配的路径。以下是构建整个代码库并一次性部署示例的具体步骤:
1. 切换到包含顶级
build.xml
文件的
ch16\voipservice
目录。
2. 在该目录下执行
ant
命令。
cd ch16\voipservice
ant
接着,通过执行同一文件夹中的
broker.xml
文件来启动 ServiceMix 容器。
cd ch16\voipservice
%SERVICEMIX_HOME%/bin/servicemix broker.xml
同一文件夹中提供的
Client.html
文件可用于发送消息,以此测试已部署的服务。通过查看 ServiceMix 控制台日志,能更好地理解上一节中描述的消息交换情况。
2. 消息中间件与服务聚合
消息中间件(MOM)多年来一直是创建松耦合应用程序的有力推动者。如今,MOM 为我们提供了企业应用集成(EAI)模式,不仅能无缝集成应用程序,还能集成服务和组件。在当今的企业计算中,分布式组件是常态,通过聚合和编排多个组件之间的消息流,我们在定义业务流程时获得了新的灵活性,即将各个服务拆分为多个组件,从而降低流程的整体复杂性。我们运用“分而治之”的原则,将功能拆分为多个组件和服务来管理复杂性。随后,这些分布式组件需要集成在一起,以提供聚合或复合服务,这可以在企业服务总线(ESB)层面实现。
3. 非功能特性与 QoS 概述
在使用任何框架进行编程时,都不能忽视该框架支持的各种非功能特性和服务质量(QoS)特性。接下来将探讨几个对使用 ServiceMix ESB 进行编程和部署有影响的 QoS 特性,具体如下:
- 事务处理
- 安全性
- 集群
- Java 管理扩展(JMX)
4. ServiceMix 中的跨领域关注点
与其他章节不同,本章主要探讨的编程和/或部署问题可应用于其他章节所涵盖的任何或所有绑定机制。如同在常规编程(如 Web 组件开发或服务器端业务组件开发)中一样,我们也可以为 ServiceMix 中的组件部署模型附加各种 QoS 特性。这些 QoS 特性的独特之处在于,它们并非通过代码与绑定组件(BC)或服务引擎(SE)硬编码在一起,而是以声明方式应用于组件。这样做的优点是,通过更改特定配置,这些 QoS 特性的属性可以轻松改变。
5. 事务处理
事务可确保组件之间操作(消息流)的原子性。我们知道,各种组件可以插入到 Java 业务集成(JBI)总线中参与消息交换,而事务可以与这些消息交换流相关联。这些事务的范围和同步性主要取决于我们在组件之间交换消息时使用的“发送”原语。ServiceMix JBI 提供了在容器级别设置事务的选项,以下代码展示了如何将 JBI 交换加入事务:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:sm="http://servicemix.apache.org/config/1.0">
<sm:container id="jbi"
embedded="true"
depends-on="jndi,broker"
autoEnlistInTransaction="true"
transactionManager="#transactionManager">
</sm:container>
<jencks:transactionManager id="transactionManager" />
</beans>
我们可以将 ServiceMix JBI 容器的
autoEnlistInTransaction
属性设置为
true
,这样每次发送 JBI 交换时,它都会加入当前事务。此时,我们可以使用
send
或
sendSync
来发送消息交换,根据所使用的方法不同,事务传播的语义也有所不同。
-
使用
sendSync
发送交换
:其隐含语义是事务随交换一起流动,服务提供者必须同步响应,并将任何所需资源加入事务。在 ServiceMix 中,当使用
sendSync
发送交换时,事务上下文会随交换一起传播,服务提供者需同步响应并将所需资源加入事务。
-
使用
send
发送交换
:消息的发送将加入当前事务,但消息交换处理将被延迟,并在与前一个事务分离的线程中处理。若要在异步消息交换中使用事务,必须使用 JCA 流。
以下是编程实现两种不同同步性事务消息交换的代码示例:
// 编程实现同步事务交换
TransactionManager txManager = (TransactionManager)
jbiContext.getTransactionManager();
tm.begin();
InOnly messageExchange = createInOnly();
jbiContext.getDeliveryChannel().sendSync(messageExchange);
tm.commit();
// 编程实现异步事务交换
TransactionManager txManager = (TransactionManager)
jbiContext.getTransactionManager();
tm.begin();
InOnly messageExchange = createInOnly();
jbiContext.getDeliveryChannel().send(messageExchange);
tm.commit();
6. 安全性
ServiceMix 的 HTTP 组件
servicemix-http
提供了配置安全的功能,下面介绍几种常见的安全配置方式:
-
HTTP 基本认证
:HTTP 1.1 规范定义了基本认证。当客户端尝试访问服务器上标记为受保护的资源时,服务器会提示输入用户名和密码组合。随后,浏览器会弹出用户名和密码输入表单,用户可输入相关信息并提交。若用户输入的用户名和密码通过服务器认证,将被授予访问请求资源的权限;否则,根据服务器策略,提示会重复几次(通常为三次)。HTTP 基本认证的主要缺点是密码以 base64 编码形式在网络上传输,这类似于纯文本格式,由于密码未加密,容易受到攻击。因此,作为额外的预防措施,我们可以进行加密或使用其他更强大的机制。对于
servicemix-http
组件,可按以下代码配置基本认证:
<http:endpoint service="test:httpConsumer"
endpoint="httpConsumer"
targetService="test:echo"
role="consumer"
locationURI="http://localhost:8198/Service/"
authMethod="basic"
defaultMep="http://www.w3.org/2004/08/wsdl/in-out">
</http:endpoint>
在这种情况下,在
servicemix-http
组件将请求路由到目标服务之前,服务器会发起基本认证挑战,只有当用户输入的用户名和密码与容器中配置的信息匹配时,请求才会被路由到目标服务。
-
SSL 配置
:ServiceMix 可以配置为使用 SSL 进行安全传输。
servicemix-http
组件的 HTTP 消费者角色和提供者角色都可以配置使用 SSL,以下是具体的配置代码:
<!-- HTTP 消费者角色使用 SSL 配置 -->
<http:endpoint service="test:YourConsumerService"
endpoint="yourConsumer"
role="consumer"
locationURI="https://localhost:8193/Service/"
defaultMep="http://www.w3.org/2004/08/wsdl/in-out">
<http:ssl>
<http:sslParameters keyStore="classpath:com/binildas/esb/
servicemix/security/server.keystore"
keyStorePassword="keystorepassword"/>
</http:ssl>
</http:endpoint>
<!-- HTTP 提供者角色使用 SSL 配置 -->
<http:endpoint service="test:YourProviderService"
endpoint="yourProvider"
role="provider"
locationURI="https://localhost:8193/Service/"
defaultMep="http://www.w3.org/2004/08/wsdl/in-out">
<http:ssl>
<http:sslParameters keyStore="classpath:com/binildas/esb/
servicemix/security/server.keystore"
keyStorePassword="keystorepassword"
trustStore="classpath:com/binildas/esb/
servicemix/security/client.keystore"
trustStorePassword="truststorepassword"/>
</http:ssl>
</http:endpoint>
7. 集群
在设计应用程序时,除了考虑常规的功能需求,还需关注非功能需求(NFR),以确保应用程序在正常和异常使用条件下都能安全运行。应用程序的可扩展性和可用性取决于应用程序部署栈的多个层面,以下是一些主要方面:
- 应用算法和设计模式。
- 用于缓存、会话复制和持久化等功能的应用框架。
- 提供堆限制、轻量级线程和本地线程的操作系统支持。
- 具备 32 位或 64 位字长能力的硬件基础设施。
应用程序的可用性取决于部署环境从故障中恢复的能力,即能否在最少的停机时间内恢复且不造成数据损坏。软件和硬件都容易出现故障,但不能因此向最终用户显示“应用程序不可用”的消息,否则可能导致客户不满并转向竞争对手的服务。保留现有客户与获取新客户同样(甚至更)重要。为解决软件和硬件故障问题,一种方法是利用行业领先的集群解决方案,为企业和应用服务网格环境中的应用程序提供一流的高可用性、可管理性和性能。若不想使用第三方集群服务,也可查看所选的应用程序基础设施(如 ServiceMix)是否提供自身的集群功能。
ServiceMix 集群是多个同时运行且协同工作的 ServiceMix 实例的逻辑分组,它提供了更高的可扩展性和可靠性。从客户端或消费者的角度来看,集群是透明的,即 ServiceMix 集群对客户端而言就像一个单一的 ServiceMix 容器实例。参与集群的 ServiceMix 实例可以运行在同一台机器上,也可以分布在不同的机器上。我们可以通过在现有机器上向集群添加额外的 ServiceMix 实例,或者向集群添加新机器来托管新的 ServiceMix 服务器实例,从而增加集群的容量。
在 ServiceMix 集群中,各个组件或应用程序组件需要安装到参与集群的 ServiceMix 服务器实例中。建议采用统一的安装模式,将组件均匀部署到集群中的所有 ServiceMix 服务器实例中,但这并非强制要求。ServiceMix 集群的具体拓扑和部署模式需根据每个部署组件所期望的 QoS 特性来确定。ServiceMix 集群具有以下几个主要优点:
-
可扩展性
:如果软件系统在负载增加时性能不会显著下降,则称该系统具有可扩展性。ServiceMix 集群的可扩展性可以动态增加,以满足需求。在不中断已部署服务的情况下,可以向集群添加 ServiceMix 实例,已部署的应用程序和服务将继续运行,不会影响现有消费者。
-
高可用性
:可用性定义为软件系统正常运行并可供消费者使用的时间比例。例如,一个在一年时间内可用性为 99.99% 的系统,其不可用时间为:
(1 - 0.9999) X 1 Year X 365 Days X 24 Hours per Day X 60 Minutes per Hour = 52.56 Minutes
对于许多基于 Web 的电子商务系统来说,99.99% 的可用性可能足够,但对于一些用于救生或国防目的的系统,则需要更高的可用性。在 ServiceMix 集群中,当一个服务器实例发生故障时,服务引擎(SE)和绑定组件(BC)仍可在其他服务器实例中继续运行。由于可以将应用程序组件部署到集群中的多个服务器实例,若某个组件运行所在的服务器实例出现故障,另一个部署了该组件的服务器实例可以继续处理,从而提高整个系统的可用性。
-
负载均衡
:负载均衡是指将作业和进程均匀分布在 ServiceMix 集群的计算和网络资源上。要实现负载均衡,必须有多个 ServiceMix 组件的副本能够为特定消费者提供服务,并且所有 ServiceMix 组件的位置和运行状态信息必须集中且全面可用。
要设置 ServiceMix 集群,需使用 JMS 流。JMS 流用于协作多个 ServiceMix JBI 容器实例之间的通信,每个 JBI 端点使用一个消息队列,这样部署在集群中不同 ServiceMix 实例中的同名组件的多个实例可以实现请求的负载均衡。在 ServiceMix 集群中,部署方式与普通的 ServiceMix JBI 容器相同(包括 POJO 和存档组件部署),但集群中的所有 ServiceMix 容器实例都会收到部署通知。底层的 JMS 流将自动处理不同 ServiceMix 容器实例之间的消息交换的路由、负载均衡和故障转移。在集群模式下,参与集群的所有 ServiceMix 实例在整个集群中必须具有唯一的名称。以下是一个示例配置,假设我们有三个 ServiceMix 容器实例,其中一个实例还管理 JMS 连接代理,我们将其命名为 “admin”:
<beans xmlns:sm="http://servicemix.apache.org/config/1.0">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.
PropertyPlaceholderConfigurer">
<bean id="jndi"
class="org.apache.xbean.spring.jndi.
SpringInitialContextFactory"
factory-method="makeInitialContext" singleton="true" />
<sm:container id="jbi"
name="admin"
flowName="jms?jmsURL=tcp://localhost:61616"
useMBeanServer="true"
createMBeanServer="true"
rmiPort="1111">
<sm:activationSpecs>
<!-- other code -->
</sm:activationSpecs>
</sm:container>
<bean id="broker"
class="org.apache.activemq.xbean.BrokerFactoryBean">
<property name="config" value="classpath:activemq.xml"/>
</bean>
<bean id="jmsFactory"
class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="connectionFactory">
<ref bean="connectionFactory"/>
</property>
</bean>
<bean id="connectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</beans>
需要注意的是,首先要将
flowName
设置为 JMS 类型,并将
jmsURL
指向 JMS 代理监听的位置。然后,只需将其他 ServiceMix 实例指向同一个 JMS 代理,即可将它们添加到集群中。以下是另外两个 ServiceMix 实例 “managed1” 和 “managed2” 的配置示例:
<!-- managed1 配置 -->
<beans xmlns:sm="http://servicemix.apache.org/config/1.0" >
<bean id="jndi"
class="org.apache.xbean.spring.jndi.
SpringInitialContextFactory"
factory-method="makeInitialContext" singleton="true" />
<sm:container id="jbi"
name="managed1"
flowName="jms?jmsURL=tcp://localhost:61616"
useMBeanServer="true"
createMBeanServer="true">
<sm:activationSpecs>
<!-- other code -->
</sm:activationSpecs>
</sm:container>
</beans>
<!-- managed2 配置 -->
<beans xmlns:sm="http://servicemix.apache.org/config/1.0" >
<bean id="jndi"
class="org.apache.xbean.spring.jndi.
SpringInitialContextFactory"
factory-method="makeInitialContext" singleton="true" />
<sm:container id="jbi"
name="managed2"
flowName="jms?jmsURL=tcp://localhost:61616"
useMBeanServer="true"
createMBeanServer="true">
<sm:activationSpecs>
<!-- other code -->
</sm:activationSpecs>
</sm:container>
</beans>
8. Java 管理扩展(JMX)
JMX 技术提供了用于构建分布式、基于 Web、模块化和动态解决方案的 API 和工具,可用于管理和监控设备、应用程序和服务驱动的网络。从 Java 2 标准版(J2SE)平台 5.0 开始,JMX 技术被包含在 Java SE 平台中。ServiceMix 的 JBI 容器通过 JMX 公开内部服务和组件。可以将 JBI 容器作为 JMX Bean 服务器传递,也可以配置为在不存在时创建一个。以下代码展示了如何创建一个到 JBI 容器的远程 JMX 连接器:
String jndiPath = "jmxrmi";
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://127.0.0.1:1099/" + jndiPath) ;
JMXConnector connector = JMXConnectorFactory.connect(url);
在 ServiceMix 中配置 JMX 是在
conf
目录下的
jmx.xml
文件中完成的,以下是配置示例:
<sm:jmxConnector objectName="connector:name=rmi"
serviceUrl="${jmx.url}"
threaded="true"
daemon="true"
depends-on="rmiRegistry, jndi"
environment="#jmxConnectorEnvironment" />
jmx.url
的默认值在 ServiceMix 3.x 版本中为
service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
,在 2.x 版本中为
service:jmx:rmi:///jndi/rmi://localhost:1099/defaultJBIJMX
。当 ServiceMix 启动并运行后,就可以使用任何与 JMX 兼容的控制台工具连接到 ServiceMix 容器。
9. 事务配置示例
接下来将演示如何以异步模式为消息交换配置事务。通过上述对 ServiceMix 的事务处理、安全性、集群和 JMX 等非功能特性的介绍,我们可以看到 ServiceMix 提供了丰富的功能和灵活的配置选项,帮助我们构建高可用、可扩展和安全的应用程序。在实际应用中,根据具体需求合理配置这些特性,能够充分发挥 ServiceMix 的优势,提升应用程序的性能和可靠性。
服务部署、运行及非功能特性详解
10. 异步消息交换事务配置示例
以下是一个具体示例,展示如何在异步模式下为消息交换配置事务。假设我们有一个简单的消息交换场景,需要确保消息处理的原子性。
首先,我们需要获取事务管理器的引用,并开始一个事务:
TransactionManager txManager = (TransactionManager) jbiContext.getTransactionManager();
txManager.begin();
然后,创建一个
InOnly
类型的消息交换对象,该对象用于发送只包含输入消息的交换:
InOnly messageExchange = createInOnly();
接下来,使用
send
方法异步发送消息交换。这里使用
send
而不是
sendSync
是因为我们要实现异步事务处理:
jbiContext.getDeliveryChannel().send(messageExchange);
最后,提交事务以确保消息处理的原子性:
txManager.commit();
整个异步消息交换事务配置的代码示例如下:
TransactionManager txManager = (TransactionManager) jbiContext.getTransactionManager();
txManager.begin();
InOnly messageExchange = createInOnly();
jbiContext.getDeliveryChannel().send(messageExchange);
txManager.commit();
在这个示例中,我们通过事务管理器确保了消息交换的原子性。即使在异步处理过程中出现异常,事务也能保证操作的一致性。
11. 各特性总结与对比
为了更好地理解 ServiceMix 中的事务处理、安全性、集群和 JMX 这些非功能特性,我们对它们进行一个总结和对比,如下表所示:
| 特性 | 作用 | 配置方式 | 优点 |
| — | — | — | — |
| 事务处理 | 保证组件间操作(消息流)的原子性 | 在容器级别设置,通过
autoEnlistInTransaction
属性和不同的
send
原语控制 | 确保消息交换的一致性,可根据需求选择同步或异步模式 |
| 安全性 | 提供 HTTP 基本认证和 SSL 配置,保护资源访问 | 配置
servicemix - http
组件的端点,设置认证方法和 SSL 参数 | 防止未经授权的访问,SSL 提供安全传输 |
| 集群 | 提高系统的可扩展性和可用性 | 使用 JMS 流,配置每个 ServiceMix 实例的名称和 JMS URL | 动态扩展系统容量,在故障时保证服务的连续性 |
| JMX | 用于管理和监控 ServiceMix 容器 | 在
jmx.xml
文件中配置 JMX 连接器 | 方便对 ServiceMix 内部服务和组件进行管理和监控 |
12. 综合应用流程
在实际应用中,我们可能需要综合使用这些特性来构建一个健壮的系统。以下是一个简单的 mermaid 流程图,展示了一个综合应用的流程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A([开始]):::startend --> B(部署服务):::process
B --> C(配置事务):::process
C --> D(配置安全):::process
D --> E(设置集群):::process
E --> F(配置 JMX):::process
F --> G(启动服务):::process
G --> H(测试服务):::process
H --> I([结束]):::startend
该流程图展示了一个典型的应用部署和配置流程,从服务部署开始,依次进行事务、安全、集群和 JMX 的配置,最后启动并测试服务。
13. 注意事项和建议
在使用 ServiceMix 的这些非功能特性时,有一些注意事项和建议:
-
事务处理
:
- 注意不同
send
原语对事务传播的影响,根据实际需求选择合适的方式。
- 在处理异常时,要正确回滚事务,避免数据不一致。
-
安全性
:
- HTTP 基本认证存在密码明文传输的风险,建议结合 SSL 使用。
- 定期更新 SSL 证书,确保安全传输的有效性。
-
集群
:
- 确保每个 ServiceMix 实例在集群中有唯一的名称。
- 监控集群的负载情况,及时调整实例数量以保证性能。
-
JMX
:
- 配置 JMX 时,注意不同版本的
jmx.url
设置差异。
- 使用 JMX 控制台工具时,确保网络连接正常。
14. 总结
通过对 ServiceMix 的示例部署与运行,以及事务处理、安全性、集群和 JMX 等非功能特性的详细介绍,我们了解到 ServiceMix 为构建企业级应用提供了强大的支持。在实际开发中,根据应用的具体需求,合理配置和使用这些特性,能够显著提升应用的性能、可靠性和安全性。同时,遵循相关的注意事项和建议,可以避免一些常见的问题,确保系统的稳定运行。无论是小型项目还是大型企业级应用,ServiceMix 都能成为一个可靠的选择,帮助开发者构建出高质量的应用程序。
超级会员免费看
7743

被折叠的 条评论
为什么被折叠?



