zuul网关查找默认的服务
通常,您绝对不应允许在SOA环境中直接访问服务提供商。 相反,您应该将新的虚拟服务部署到企业服务总线(ESB),该服务充当真实后端服务的代理。 引入对后端服务的控制访问点可带来许多好处。 它以其最基本的形式实现了服务使用者和服务提供者之间的松散耦合,使您可以重新定位后端服务或修改其接口,而不必影响服务使用者。 这种模式通常称为简单服务代理。 它还使您能够引入服务管理功能,例如错误处理和警报,日志记录,安全配置,流量管理,服务收费和性能评估。 这些是对简单服务代理模式的扩展。
简单服务代理模式的一个问题是,您需要为SOA中的每个后端服务实现并部署一个新的虚拟服务。 显然,随着SOA中服务数量的增长,实现此目标所需的工作可能会变得令人望而却步。 服务网关模式通过为多个后端服务提供单个访问点,并将对不同服务提供者的请求路由到适当的端点来解决此问题。 此模式还允许您为通过网关访问的所有服务引入通用的服务管理功能。
本文介绍了实现服务网关模式的示例消息流。 它在运行时从WSRR动态检索元数据,并使用它来确定如何路由服务请求。
服务网关业务场景
网关是ESB的一部分,它提供边界功能,这些边界功能适用于所有传入消息,并且与格式无关。
边界功能通常利用标准标头中的数据(在传输,SOAP甚至数据级别上)来确定要采取什么措施,但无需了解消息数据(或主体)的完整格式。 网关模式然后可以直接调用服务或调用其他模式。 这些边界功能包括:
- 请求路由
- 认证方式
- 授权书
- 审核和记录
- 协议转换
- 响应相关
网关模式的示例包括:
- 安全网关
网关模式的这个相当具体的示例从主基础结构中卸载了所有非标准安全处理,并将在调用真实目的地之前执行身份验证,授权以及可能的审核。 在此模式下,网关和ESB的其他部分之间几乎总是存在可信链接,因此可以简化ESB的其他部分所需的安全模型。 安全网关可能位于与ESB其余部分不同的安全区域中,并将提供与外部客户端的连接。 这种模式将支持各种传入的安全协议,同时简化其他ESB组件的安全性。
- 服务连接器
当网关模式作为基于面向服务原理的企业体系结构的一部分引入时,网关模式可以提供将许多现有服务连接到ESB的最简单方法。 网关在企业体系结构中引入了一个控制点,可以将一系列临时服务置于服务注册表和相关治理的控制之下,而无需为每个服务开发单独的中介流。 消息进入网关,然后被路由到最终提供者,提供者外观或进一步的中介流。
- 边界调解员
边界中介器模式通过允许将标准中介应用于所有传入(和/或传出)服务请求或消息来扩展服务连接模式。 这些标准(与内容无关)中介在网关中开发一次,可以应用于所有传入消息。 它们可以包括验证,日志记录,审计,身份验证和授权中的任何一项或全部。 可以基于网关属性,基于请求数据查找的数据或传入请求内的数据(通常在标头中)通用或选择性地应用它们。
服务网关业务场景
本文中描述的示例流程是上述Service连接器模式的实现。 它重点介绍第1部分:方案和配置中描述的Service Gateway方案,如下所示:
- 业务问题
您有几种服务要在ESB级别上应用一些通用处理。 您不想构建和部署单独的流来代理每个后端服务来实现此目的。
- 解
通过在网关模式下使用
SOAP Input
节点,将不会对该节点接收到的SOAP消息执行特定于服务的验证。 这使您可以实现单个消息流,该消息流可以处理许多后端服务的服务请求。 然后,这样的消息流可以提供应用于其处理的所有服务请求的通用功能,例如授权,日志记录等。 要将服务请求路由到后端服务,消息流必须从WSRR中检索端点。 - 好处
这种方法使您能够在一个地方实现通用处理逻辑,从而简化了对多个服务的服务请求的路由,监视,日志记录,版本控制和保护过程,从而减少了总体开发和测试工作量。 这也简化了调用目标服务的过程,因为服务使用者只需要知道一个端点即可。
服务请求中可用的信息
要将服务请求路由到正确的目标服务,消息流需要从请求中提取足够的信息,以使其能够在WSRR中找到正确的端点。 我们需要提取的两个关键信息是服务请求的名称空间和所调用操作的名称。 以下各节描述了如何提取此信息。
服务命名空间
Web服务实现的最流行的绑定样式是document/literal wrapped
。 此模式的基本特征如下:
- 输入消息只有一个部分
- 该部分是一个元素
- 元素具有与操作相同的名称
- 元素的复杂类型没有属性
结果,消息流能够通过检查请求的主体来确定服务的名称空间。 它是通过以编程方式获取对SOAP主体的子元素的引用,然后查询该元素的名称空间来实现的。
数学服务是使用document/literal wrapped
模式的Web服务的示例。 显示了Math Service的服务请求示例。 您可以从该请求中看到该服务的名称空间是http://math.pot.ibm.com 。
数学服务请求示例
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:math="http://math.pot.ibm.com">
<soapenv:Header>
<math:MathHeader>
<consumerID>CalculatorApplication</consumerID>
<contextID>CTX_1</contextID>
</math:MathHeader>
</soapenv:Header>
<soapenv:Body>
<math:add>
<augend>1</augend>
<addend>1</addend>
</math:add>
</soapenv:Body>
</soapenv:Envelope>
操作名称
IBM Integration Bus提供的SOAP Input
节点解析每个服务请求并提取其他信息。 它试图提取的信息之一是被调用的操作的名称。 这存储在节点生成的消息树中。 使用IBM Integration Toolkit中提供的调试器在消息树中显示操作名称的位置。 显示的操作名称add是从上一个列表中显示的服务请求中提取的。
调试器中显示的操作名称
服务运营
将WSDL或XSD文档加载到WSRR后,它将解析文档的内容并创建许多对象来表示该内容。 如果WSDL文档包含定义服务操作的portType
元素,则WSRR将为定义的每个操作创建一个Service Operation
对象。 服务操作包含许多属性,消息流可以使用这些属性来确定将服务请求路由到的正确端点。
服务操作属性
在此讨论的上下文中,服务操作上最重要的属性如下:
- 命名空间
- 操作名称
- 接口名称
- 接口名称空间
- 接口版本
消息流可以使用从服务请求中提取的服务名称空间和操作名称来从WSRR中检索相应的服务操作。 然后,消息流可以使用检索到的服务操作上的接口名称 , 接口名称空间和接口版本属性的值,使用“端点查找”节点来检索目标服务的端点。 描述这些属性,以及在服务操作类型上定义的其他属性。
服务操作属性
显示名称 | 物业名称 | 描述 | 类型 |
---|---|---|---|
名称 | 名称 | 服务操作的描述性名称。 | 串 |
描述 | 描述 | 服务操作的文字说明。 | 串 |
命名空间 | 命名空间 | 服务操作的XML模式名称空间。 | 串 |
版 | 版 | 服务操作的版本。 | 串 |
接口版本 | sm63_interfaceVersion | 服务接口的版本(端口类型版本)。 | 串 |
接口名称空间 | sm63_interfaceNamespace | 服务接口的名称空间(端口类型的名称空间)。 | 串 |
接口名称 | sm63_interfaceName | 服务接口的名称(端口类型名称)。 | 串 |
操作名称 | sm63_operationName | 此服务操作表示的WSDL操作的名称。 | 串 |
使用本系列文章中提供的样本数据,显示WSRR中的相关对象如何相互关联。 它显示了Math Service的四个Service Operation对象和两个SOAP Service端点 。 请注意,为清楚起见,该图上未显示某些对象。
与MathService有关的对象图。
消息流说明
网关流从服务请求中提取信息,并使用它从WSRR中检索相应的服务操作。 然后,可以使用服务操作上可用的附加信息对WSRR执行另一个查询,这一次是检索目标服务的实际端点。 确定端点后,网关流会将服务请求路由到目标服务,并将响应返回给客户端。 如果针对WSRR的任何查询均未返回结果,则SOAP错误将返回给客户端。
网关流的实现包括8个节点。 正常操作时为7,错误处理时为1。 在IBM Integration Toolkit的消息流编辑器中显示流本身。 下面详细描述此消息流中的每个节点。
服务网关流程
SOAP输入节点
网关流的SOAP Input
节点是SOAP Input
节点。 它配置为使用带有/ gateway URL后缀的HTTP传输。 关于此节点要注意的重要一点是,它已配置为以网关模式运行 。 这是在节点的属性编辑器的“ 基本”选项卡上指定的。 使用out终端将SOAP Input节点连接到网关流中的下一个节点。
网关模式
流程网关请求节点
Process Gateway Request
节点是Java Compute
节点的一个实例。 它处理从SOAP Input
节点传递给它的服务请求,提取服务请求的名称空间和操作名称,如中所述。
流程网关请求节点
以下清单中显示的代码获取对SOAP主体的第一个子元素的引用,然后检索该元素的名称空间。 这是被调用操作的名称空间。 它还通过检查消息树中的相关位置来检索正在调用的操作的名称。 当操作名称解析输入服务请求时,它由SOAP输入节点写入此位置。
Java代码读取名称空间和操作名称
MbElement bodyChildElement =
rootElement.getFirstElementByPath("SOAP/Body").getFirstChild();
String namespace = bodyChildElement.getNamespace();
String operation =
(String)rootElement.evaluateXPath("string(SOAP/Context/attribute::operation)");
检查是否已从服务请求中提取了有效的服务名称空间和操作名称后,“ Process Gateway Request
节点会将相关字段插入本地环境树中,以编程方式覆盖“注册表查找”节点上的属性。 以下清单中显示的代码将注册表查找节点配置为检索对象,这些对象具有与服务请求的名称空间匹配的Namespace
属性和与服务请求的操作名称匹配的sm63_operationName
属性。 在Governance Enablement Profile(GEP)(WSRR的默认配置概要文件)中, sm63_operationName
属性对于Service Operation
类型是唯一的,因此“注册表查找”节点应仅返回此类型的对象。 但是,为清楚起见, Process Gateway Request
节点还指定primaryType
必须与Service Operation
类型的URI匹配。 然后, Process Gateway Request
节点将消息传递到out终端,该终端连接到Registry Lookup节点。
Java代码覆盖注册表查找节点变量
private static final String OWL_URI_SERVICE_OPERATION =
"http://www.ibm.com/xmlns/prod/serviceregistry/v6r3/ServiceModel#ServiceOperation";
MbMessage environment = new MbMessage(inAssembly.getLocalEnvironment());
MbElement environmentRoot = environment.getRootElement();
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?UserProperties/?Namespace[
set-value('" + namespace + "')]");
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?UserProperties/?sm63_operationName[
set-value('" + operation + "')]");
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?UserProperties/?primaryType[
set-value('" + OWL_URI_SERVICE_OPERATION + "')]");
如果无法确定服务请求的名称空间或操作名称,那么将生成SOAP错误,并且节点会将消息传递给失败终端。 该终端直接连接到SOAP Reply
节点,该节点将SOAP故障传递回客户端。
注册表查找节点
Registry Lookup
节点的行为由上一个节点在本地环境树中以编程方式创建的条目确定。 如上所述,将返回一个或多个Service Operation
对象,其操作名称和名称空间与从服务请求中提取的值匹配。 节点将所有匹配对象的表示形式插入本地环境树的ServiceRegistry条目中,然后将消息传递到out终端。 节点的“ 匹配策略 ”设置为“ 全部”,而“ 深度策略”设置为“仅返回匹配”(深度= 0) 。 必须为Name属性指定一个伪值,以允许将消息流保存并部署到IBM Integration Bus。 该值由流中的上一个节点以编程方式清除。
注册表查找节点
如果由“ Registry Lookup
节点执行的Registry Lookup
返回任何结果,则该节点会将消息传递到NoMatch终端,该终端已连接到“ No Match Fault
节点。
流程服务操作节点
Process Service Operations
节点是Java Compute
节点的另一个实例。 它处理由先前的“ Registry Lookup
节点执行的查询结果,并使用它们将相关字段插入本地环境树中,以编程方式覆盖“端点查找”节点上的属性。
流程服务操作节点
以下示例中显示的代码获取对本地环境树的ServiceRegistry条目中包含的所有Entity条目的引用。 如果在WSRR中注册了目标服务的多个兼容版本,则查询可能返回多个结果。 在这种情况下,您可以选择实施一些逻辑来选择特定的服务操作 。 例如,您可能要确保将请求路由到该服务的最新版本的端点。 此代码假定共享相同名称空间的所有版本均兼容,这与建议的服务版本控制惯例一致。 现在,“ Process Service Operations
节点仅从列表中选择第一个服务操作。 然后, sm63_interfaceNamespace
从该对象检索sm63_interfaceName
, sm63_interfaceNamespace
和sm63_interfaceVersion
属性的值。 这些属性与目标服务的portType
上的name
, namespace
和version
属性相对应。
Java代码从服务操作中检索接口名称,名称空间和版本属性
MbElement rootElement = inAssembly.getLocalEnvironment().getRootElement();
MbElement serviceRegistry = rootElement.getFirstElementByPath("/ServiceRegistry");
List<MbElement> serviceOperations =
(List <MbElement>)serviceRegistry.evaluateXPath("Entity");
if (serviceOperations != null && !serviceOperations.isEmpty()) {
MbElement serviceOperation = serviceOperations.get(0);
String portTypeName =
(String)serviceOperation.evaluateXPath(
"string(userDefinedProperties[@name='sm63_interfaceName']/attribute::value)");
String portTypeNamespace =
(String)serviceOperation.evaluateXPath(
"string(userDefinedProperties[@name='sm63_interfaceNamespace']/attribute::value)");
String portTypeVersion =
(String)serviceOperation.evaluateXPath(
"string(userDefinedProperties[@name='sm63_interfaceVersion']/attribute::value)");
Process Service Operations
节点检查是否已从选定的服务操作中检索到有效的接口名称和名称空间版本属性。 然后,它将相关字段插入本地环境树中,以编程方式覆盖“端点查找”节点上的属性。 它将Name
, Namespace
和Version
属性的值设置为从服务操作中检索到的那些属性。 在执行此操作之前,必须删除消息流前面的“ Registry Lookup
节点所使用的本地环境树中的条目。 具体来说,它需要删除由Process Gateway Request
节点定义的UserProperty 。 中的代码显示了正在执行的这些任务。 然后, Process Service Operations
节点将消息传递到out终端,该终端连接到Endpoint Lookup节点。
端点查找节点使用的Java代码设置参数
private static final String OWL_URL_ONLINE =
"http://www.ibm.com/xmlns/prod/serviceregistry/lifecycle/v6r3/LifecycleDefinition"
+ "#Online";
if ( portTypeName != null && !portTypeName.isEmpty()
&& portTypeNamespace != null && !portTypeNamespace.isEmpty()
&& portTypeVersion != null && !portTypeVersion.isEmpty()
) {
MbMessage environment = new MbMessage(inAssembly.getLocalEnvironment());
MbElement environmentRoot = environment.getRootElement();
((List <MbElement>)environmentRoot.evaluateXPath(
"ServiceRegistry LookupProperties/UserProperties")).get(0).delete();
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?Name[set-value('" + portTypeName + "')]");
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?Namespace[set-value('"
+ portTypeNamespace + "')]");
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?Version[set-value('"
+ portTypeVersion + "')]");
environmentRoot.evaluateXPath(
"?ServiceRegistry LookupProperties/?Classification[set-value('"
+ OWL_URL_ONLINE + "')]");
如果Process Service Operations
节点无法从Process Service Operations
中检索接口名称,名称空间或版本属性之一,则将生成SOAP错误,并且该节点会将消息传递给故障终端。 该终端直接连接到SOAP Reply
节点,该节点将SOAP故障传递回客户端。
端点查找节点
Endpoint Lookup
节点的行为由上一个节点在本地环境树中以编程方式创建的条目确定。 节点的匹配策略设置为One 。 这样可以确保该节点将从查询结果中选择第一个匹配的端点,并在本地环境树中设置相关条目,以使该节点可以直接连接到SOAP Request
节点。 (可选)您可以指定“ 全部 匹配策略” ,并使用另一个Java Compute
节点选择最合适的匹配端点。 在这种情况下,您的Java Compute
节点还需要以编程方式设置SOAP Request
节点所需的本地环境树中的相关条目。 再次,为Name属性指定了一个伪值,以允许将消息流保存并部署到IBM Integration Bus。 该值由流中的前一个节点以编程方式覆盖,且名称为必需的portType
。
端点查找节点
如果由“ Endpoint Lookup
节点执行的Endpoint Lookup
返回任何结果,则该节点会将消息传递给NoMatch终端。 该端子连接到No Match Fault
节点。 否则,该流程将结果传递到连接到SOAP Request
节点的out终端。
SOAP请求和SOAP回复节点
SOAP Request
节点负责调用目标服务。 定义流时,即使在运行时Endpoint Lookup
节点会以编程方式覆盖该值,也必须为Web Service URL属性指定一个值。 结果,为此属性指定了伪值http://tempuri.org/MathServer/services/MathServer
。 要注意的另一个重要点是,必须将节点的“ 操作模式 ”设置为“ 调用通用Web服务” 。 这是在节点的属性编辑器的“ 基本”选项卡上指定的。 SOAP Request
节点使用out终端和Fault终端直接连接到SOAP Reply
节点。
SOAP请求和SOAP回复节点
顾名思义, SOAP Reply
节点只是将SOAP响应传递回服务使用者。 在成功通过该流程时,返回的响应将是来自实际目标服务的响应。 如果发生错误,则响应将是由流中的Java Compute节点之一或目标服务本身生成的SOAP错误。
无匹配故障节点
当两个Java Compute节点中发生错误时,这些节点将以编程方式生成适当的SOAP错误,并将该错误传递给其故障终端。 这些直接连接到SOAP Reply
节点。 但是,当Registry Lookup
节点或Endpoint Lookup
节点执行的Endpoint Lookup
未返回任何结果时,它们不会自动生成SOAP错误。 为此,将其NoMatch终端连接到No Match Fault
Java Compute节点,该节点以编程方式生成SOAP错误,并使用SOAP Reply
节点将其返回给服务使用者。
测试消息流
接下来的步骤描述了如何使用计算器应用程序来验证网关流是否正常运行。
- 确保您的IBM Integration Bus执行组正在运行,并且已部署并启动RegistryLookup_Gateway流。
- 如第1部分中的运行计算器应用程序中所述, 启动计算器应用程序 。
- 为运行IBM Integration Bus的服务器指定合适的主机名和端口号值。 例如,如果您在与Calculator应用程序相同的机器上运行IBM Integration Bus,并且使用缺省端口,则这些值将为localhost和7800 。
- 修改服务的路径,将其值设置为/ gateway 。 这是作为文章1的一部分部署的Registry Lookup_Gateway流的端点。 计算器应用程序应类似于以下内容:
计算器应用
- 在下拉列表中指定一些值和合适的运算符(+,-,/,*),然后单击= (等于按钮)。 计算器应用程序将服务请求发送到网关消息流,该消息流会将请求路由到实际的Math Service 。 结果最终返回到计算器应用程序,然后显示。
您还可以使用通用客户端,该客户端允许您对网关流执行HTTP POST。 这将允许您将服务请求发送到网关,以获取在WSRR中注册的其他服务,并验证路由确实是动态的。 下面显示了使用Firefox的Poster扩展来调用Math Service 版本2的示例:
使用海报
命名空间是http://math.pot.ibm.com/V2
和添加的<dummyElement/>
XML标记,这些标记使它成为有效的版本2请求。
结论
现在,您应该了解为什么要在SOA环境中使用网关。 本文介绍了示例消息流,该消息流提供了服务网关模式的实现。 该消息流从服务请求中提取信息,然后在运行时从WSRR中动态检索元数据,并使用它将请求路由到目标服务。 您还应该能够通过计算器应用程序或通用客户端(例如Poster)成功地使用示例网关流提供的功能。
致谢
作者感谢以下人员在本系列的示例消息流开发中所提供的所有帮助:
- 约翰·霍西
- 本汤普森
- 马特·高比·柯克
- 特雷弗·杜比(Trevor Dolby)
- 安德烈亚斯·马滕斯(Andreas Martens)
- 格雷厄姆·哈克斯比(Graham Haxby)
- 安德鲁·科尔曼
- 约翰·里夫
作者还感谢以下人员对本文的帮助:
- 戴维·西格
- 安娜·麦克西科维奇(Anna Maciejkowicz)
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1404_smithson6/1404_smithson6.html
zuul网关查找默认的服务