前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >API管理对SOAP的集成&自定义开发者门户 | API Management学习第五篇

API管理对SOAP的集成&自定义开发者门户 | API Management学习第五篇

作者头像
魏新宇
发布2018-07-30 14:49:41
3K0
发布2018-07-30 14:49:41
举报

前言

本文仅代表作者的个人观点;

本文的内容仅限于技术探讨,不能作为指导生产环境的素材;

本文素材是红帽公司产品技术和手册;

本文分为系列文章,将会有多篇,初步预计将会有26篇。

一、API管理对SOAP集成的两种方法

通常情况下,API管理对web API的集成,除了RESTful Web服务之外,还需要管理基于SOAP的Web服务。

SOAP请求包含带有XML有效负载的HTTP POST请求和一些其他特定于SOAP的标头。 这些SOAP请求可以发送到3scale的APIcast网关,转发到后端SOAP服务,并在没有任何自定义的情况下报告给3scale AMP。

但是,如果还需要收集对后端SOAP服务公开的特定操作的请求,进行一定度量和控制(监控、计费等)则需要进行一些额外的设置。

3 Scale对SOAP的两种集成的方法如下:

  • 创建对Lua和NGINX配置文件的自定义修改,以自动将REST请求映射到SOAP后端
  • 通过OpenShift应用程序上的Fuse进行REST到XML的转换。此时,Fuse应用程序充当后端SOAP服务的RESTful代理,并在SOAP和REST之间进行转换。

二、将SOAP服务部署到OpenShift

在本实验中,我将在与3scale AMP相同的,OpenShift集群中的JBoss企业应用程序平台(EAP)容器上,运行现有的基于SOAP的Java EE应用程序。

SOAP的wsdl文件内容如下: / Stores / src / main / resources / wsdl`。

此WSDL遵循SOAP 1.1规范。

SOAP 1.1规范定义了以下命名空间:http://schemas.xmlsoap.org/wsdl/soap/

SOAP 1.2规范定义了以下命名空间:http://schemas.xmlsoap.org/wsdl/soap12/

SOAP规范的两个版本要求使用不同的机制来调用其WSDL中定义的SOAP操作。 在本实验的后期,在使用3scale管理SOAP服务的上下文中,这两个规范的后果将变得明显。

打开源码 Stores / src / main / java / com / redhat / service / StoresWS.java。

检查SOAP Web服务实现:

为Stores API业务服务应用程序创建一个新项目:

创建模板,通过模板部署应用:

部署成功:

在命令行中,查看Stores服务公开的WSDL:执行以下命令以确定新Stores SOAP服务的WSDL的URL:

通过浏览器访问URL:

在新的浏览器选项卡或窗口中,打开URL“http://wsdlbrowser.com”。

提供Stores WSDL的URL,然后单击Browse。

检查WSDL是否已成功导入,以及页面上是否显示了功能列表:

点击getStore---request是xml

查看result,返回值也是xml

截止到目前,SOAP的应用部署成功,并且能被访问。

三、创建APIcast登台和生产路线

创建从OCP router到 API caststaging和production APIcast的、SOAP应用的路由:

在3scale API中配置

创建新服务:

创建application plan

在RHBank账户中创建app:

集成API:

创建method:

创建metris,以便3 scale进行监控:

配置映射关系:

这样,每次向后端Stores服务的任何SOAP操作发出SOAP请求时,POST请求的映射都将增加StoresWS方法的命中。GET请求的映射将增加对诸如Stores服务的WSDL之类的资源的命中。

设置API测试GET请求:

API测试GET请求:/ StoresWS?wsdl

测试API托管SOAP服务

我们能够使用HTTP客户端通过APIcast网关将SOAP请求发送到后端SOAP服务。

通过APIcast登台URL向Stores服务的WSDL发出curl请求来测试API:

curl -k "https://`oc get route stores-soap-policy-staging-route -o template --template {{.spec.host}} -n $OCP_PROJECT_PREFIX-3scale-amp`/StoresWS?wsdl&user_key=$STORES_SOAP_API_KEY"

对Stores Web Service的getAllStores操作发出POST请求: curl -v -k -X POST --header "Content-Type: application/soap+xml" --header "Accept: application/soap+xml" --header "SOAPAction: http://www.rhmart.com/Stores/getAllStores" -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stor="http://www.rhmart.com/Stores/"><soapenv:Header/><soapenv:Body><stor:getAllStores/></soapenv:Body></soapenv:Envelope>' "https://stores-soap-staging-apicast-user11.apps.02bb.openshift.opentlc.com:443/StoresWS?wsdl&user_key=5dac3071cd7ec27c65531882cbfb4fca"

继续使用SOAP 1.1 Web服务,并继续在对该SOAP Web服务的请求中使用名为SOAPAction的HTTP头(上面标黄部分)。

现在,APIcast将使用这些SOAPAction标头字段(: http://www.rhmart.com/Stores/getAllStores)来更新相应的API指标。

选择SOAP,最后结果如下:

单击SOAP策略以展开它。

输入以下映射规则:

四、数据统计 Analytics(分析)

Apicast正确捕获了为每个操作设置的指标。 可以看到endpoint请求的每个SOAPAction对应的命中数。

SOAP 1.2 Web Service的管理类似于您在此处管理SOAP 1.1 Stores Web Service的方法。

不同的地方是:

  • 不要在HTTP请求中设置SOAPAction标头。
  • 在HTTP请求上使用Content-Type标头,并为其action参数设置一个值
  • application / soap + xml Content-Type标头的action参数在SOAP标准的v1.2中指定

使用curl实用程序的示例如下:--header application/soap+xml;charset=UTF-8;action="http://www.rhmart.com/Stores/getAllStores".

五、在OpenShift上使用Fuse进行SOAP转换

在上面的实验中,我们解了3scale如何管理SOAP服务。 在APIcast网关中引入了SOAP策略,以便基于SOAP操作收集指标。

集成SOAP的第二种方法,是使用一个中间层,用于公开REST并转换为SOAP。 JBoss Fuse是实现此目的的理想工具。

接下来,我会部署一个camel,用来公开REST端点并路由到之前部署的SOAP服务。

将Fuse应用程序存储到OpenShift。

过一会,pod创建成功:

检查Fuse中间层:

使用您的登录凭据从Web浏览器登录OpenShift管理控制台。

单击Stores-FIS pod,然后单击Open Java Console:

单击Route Diagram。

期望看到定义的所有Camel路线:

或者,单击“源”并查看Camel路径:

公开REST路由以为Stores API提供的不同SOAP操作提供HTTP方法和URL:

注意getStore和getAllStores的两个GET方法,postStore的POST方法和deleteStore操作的DELETE方法。

每个直接路由对应于REST服务中定义的四个操作:

代码语言:javascript
复制
   <route customId="true" id="createStore">
        <from customId="true" id="_from1" uri="direct:createStore"/>
        <setBody customId="true" id="_setBody1">
            <simple>${body.getStore()}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader1">
            <constant>createStore</constant>
        </setHeader>
        <to customId="true" id="_to1" uri="direct:soap"/>
    </route>
    <route customId="true" id="deleteStore">
        <from customId="true" id="_from2" uri="direct:deleteStore"/>
        <setBody customId="true" id="_setBody2">
            <simple resultType="int">${header.storeID}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader2">
            <constant>deleteStore</constant>
        </setHeader>
        <to customId="true" id="_to2" uri="direct:soap"/>
    </route>
    <route customId="true" id="getStore">
        <from customId="true" id="_from3" uri="direct:getStore"/>
        <setBody customId="true" id="_setBody3">
            <simple resultType="int">${header.storeID}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader3">
            <constant>getStore</constant>
        </setHeader>
        <to customId="true" id="_to3" uri="direct:soap"/>
    </route>
    <route customId="true" id="getAllStores">
        <from customId="true" id="_from4" uri="direct:getAllStores"/>
        <setBody customId="true" id="_setBody4">
            <mvel>new Object[0]</mvel>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader4">
            <constant>getAllStores</constant>
        </setHeader>
        <to customId="true" id="_to4" uri="direct:soap"/>
    </route>

上面的每个路由都获取请求,构造CXF请求消息对象,并将标头更新到右侧soapMethod以调用SOAP Web服务。

调用SOAP端点的路由:

代码语言:javascript
复制
    <route customId="true" id="soapRoute">
        <from customId="true" id="_from5" uri="direct:soap"/>
        <toD customId="true" id="tod" uri="cxf:bean:wsStores?defaultOperationName=${header.soapMethod}&amp;exchangePattern=InOut"/>
        <setBody customId="true" id="_setBodySoap">
            <simple>${body[0]}</simple>
        </setBody>
        <setHeader customId="true" headerName="Content-Type" id="_setHeaderContextType">
            <constant>application/json</constant>
        </setHeader>
    </route>

在虚拟机中,我们查看FUSE的源代码:

检查项目的application.properties文件中找到的属性:定义了一个名为cxf.endpoint.soap的属性:

jboss@rhtapimgmt ~/lab/3scale_development_labs/StoresFIS (master) $ cat src/main/resources/application.properties

#spring.main.sources=org.mycompany

logging.config=classpath:logback.xml

# the options from org.apache.camel.spring.boot.CamelConfigurationProperties can be configured here

camel.springboot.name=MyCamel

# lets listen on all ports to ensure we can be invoked from the pod IP

server.address=0.0.0.0

management.address=0.0.0.0

# lets use a different management port in case you need to listen to HTTP requests on 8080

management.port=8081

# disable all management endpoints except health

endpoints.enabled = false

endpoints.health.enabled = true

# cxf endpoint address

cxf.endpoint.soap = http://stores-soap:8080

测试Camel REST路由:

将curl请求发送到stores-fis路由以调用REST Web服务,并检查是否已调用SOAP Web服务并将响应转换为application / json:

curl http://`oc get route stores-fis -o template --template {{.spec.host}} -n $OCP_PROJECT_PREFIX-stores-api`/allstores

输出结果是json:

现在可以正确部署REST-SOAP Camel代理,我们可以开始配置APIcast网关以使用此REST端点与SOAP Web服务进行通信。

创建SOAP从router到Stores API staging和production APIcast的路由。:

$ oc create route edge stores-soap-transformation-staging-route \ --service=apicast-staging \ --hostname=stores-staging-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

$ oc create route edge stores-soap-transformation-production-route \ --service=apicast-production \ --hostname=stores-production-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

接下来,在3 scale中配置。

创建service:

创建application plan并publish:

在“开发人员”选项卡中,选择RHBank帐户。

单击Applications,然后单击Create Application。

接下来集成JBoss Fuse Camel REST

对路由发起curl请求,输出结果是Json格式。

jboss@rhtapimgmt / $ curl -k https://stores-staging-apicast-user11.apps.02bb.openshift.opentlc.com:443/allstores?user_key=1f5ad4d8206ff559fe1a6ae0f715b9a4

{"store":[{"storeID":1,"storeName":"Downtown\n Store","storeLat":-34.6052704,"storeLong":-58.3791766},{"storeID":2,"storeName":"EastSide\n Store","storeLat":-34.5975668,"storeLong":-58.3710199},{"storeID":3,"storeName":"?","storeLat":0.0,"storeLong":0.0},{"storeID":4,"storeName":"?","storeLat":0.0,"storeLong":0.0}]}jboss@rhtapimgmt / $

六、OData Service Management

在本节中,我们将部署OData(开放数据协议)服务。 OData是一种标准,它定义了一组用于构建和使用RESTful API的最佳实践。 我们部署的服务基于JBoss Data Virtualization for OpenShift Container Platform虚拟数据库(VDB)。 此VDB具有一个虚拟视图,可从两个数据库表(MySQL和PostgreSQL)中检索数据,并将它们显示为单个SQL ANSI表。 然后,开箱即用,该视图在JBoss Data Virtualization中作为OData REST服务公开。

将Stock API项目部署到OpenShift

在本节中,我们将Stock API部署到在OpenShift上运行的JBoss EAP容器中。 库存数据存在于两个数据库中:MySQL和PostgreSQL。 JBoss Data Virtualization用于提供数据虚拟化,并将组合数据视图显示为OData REST服务。

部署mysql和PostgreSQL(篇幅有限,步骤省略)

对应用发起curl,可以得到正常返回结果。

curl -k http://stock-api-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN/odata4/Stock-API/FederatedStock/stock?$format=JSON

REST odata服务现在已正确部署,现在可以开始配置APIcast网关以使用此REST端点与服务进行通信。

创建APIcast Staging和Production Routes

oc create route edge stock-staging-route \

--service=apicast-staging \

--hostname=stock-staging-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

oc create route edge stock-production-route \

--service=apicast-production \

--hostname=stock-production-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

登录3scale,进行配置。

创建app plan并publish:

在“开发人员”选项卡中,单击“RHBank”。

单击Applications,然后单击Create Application:

创建应用:

七、API开发人员注册流程制定:单个应用注册

接下来,我们创建自定义注册流程,以管理通过3scale管理的API的开发人员注册。 涵盖的一些方案是单个应用程序,多个应用程序注册,组成员流程。

达成的目标是:

  • 为Products API应用程序创建API文档
  • 将API文档与3scale API Management集成
  • 创建自定义开发门户
  • 创建客户端应用程序以调用Products API

在3scale内容管理系统(CMS)中找到的开箱即用的主页包含一个嵌入其中的非常简单的注册流程。

在本实验的这一部分中,我们将提取该嵌入式注册流并将其另存为“Partial”。 然后,在您的主页中引用该新Partial。实验中,我们只是将原始注册流逻辑从隐藏在主页中转移到被引用的部分,所以不会改变Developer Portal的外观。

在本实验的后续部分中,我们实现更复杂的注册流程,这些注册流程也实现为部分流程。 只需将引用更改为所需的Partial,即可轻松地将所有注册流程交换到Developer Portal主页中。

在3scale管理员门户中,单击顶部工具栏中的Developer Portal链接以导航到CMS。观察Developer Portal主页的默认外观。在CMS的顶部,单击:访问Developer Portal

导航至:My→Root→homepage:

拷贝代码119 - 182行。

然后新建Partial

修改homepage:

发布两个变更

通过这种方式创建的主业,默认只有两个application plan:

我们要做的是,让主业可以看到所有的application plan:

代码如下:

查看文件:

jboss@rhtapimgmt ~/lab/3scale_development_labs/DevPortal (master) $ cat _single_app_signup_form.html.liquid

<div class="container">

<h1>Pick your plan</h1>

<br/>

{% for service in provider.services %}

<h2> {{ service.name }} </h2>

<div class="row">

{% for plan in service.application_plans%}

<div class="col-md-4">

<article class="panel panel-default">

<div class="panel-heading">

<strong>{{ plan.name }}</strong>

</div>

<div class="panel-body">

<div class="row">

{% if plan.features == present %}

<div class="col-md-6">

<h5>Features</h5>

<ul class="features list-unstyled">

{% for feature in plan.features %}

<li>

<i class="fa fa-check"></i> {{ feature.name }}

</li>

{% endfor %}

</ul>

</div>

{% endif %}

<div class="col-md-6">

<h5>Limits</h5>

<ul class="limits list-unstyled">

{% if plan.usage_limits == present %} {% for limit in plan.usage_limits %}

<li>

<i class="fa fa-signal"></i> {{ limit.metric.name }} &ndash; {{ limit.value }} {{ limit.metric.unit }}s per {{ limit.period }}

</li>

{% endfor %} {% else %}

<li>

<i class="fa fa-signal"></i> No limits

</li>

{% endif %}

</ul>

</div>

</div>

</div>

<div class="panel-footer">

<div class="row">

<div class="col-md-12">

<a class="btn btn-cta-secondary pull-right" href="{{ urls.signup }}?{{ plan | to_param }}&{{ service.service_plans.first | to_param }}">Signup to plan {{ plan.name }}</a>

</div>

</div>

</div>

</article>

</div>

{% endfor %}

</div>

{% endfor %}

</div>

将此partial添加到开发人员门户。

编辑主页:

在第120行附近,将original_app_signup_form替换为single_app_signup_form。

现在点击访问开发者门户,此时可以看到所有的application plan:

八、API开发人员注册流程制定:单个应用注册

多应用程序注册流程允许用户同时注册多个服务(以及相关的application paln)。它通过提供在Developer Portal中呈现多选复选框HTML表单的部分来实现。

确保“多个应用程序”功能被启用

参照源码:

$ cat _multiple_app_signup_form.html.liquid

<form action="{{ urls.signup }}" method="get">

<div class="container">

<h1>Pick your plan</h1>

<br/>

{% for service in provider.services %}

<h2> {{ service.name }} </h2>

<div class="row">

{% for plan in service.application_plans%}

<div class="col-md-4">

<article class="panel panel-default">

<div class="panel-heading">

<strong>{{ plan.name }}</strong>

</div>

<div class="panel-body">

<div class="row">

{% if plan.features == present %}

<div class="col-md-6">

<h5>Features</h5>

<ul class="features list-unstyled">

{% for feature in plan.features %}

<li>

<i class="fa fa-check"></i> {{ feature.name }}

</li>

{% endfor %}

</ul>

</div>

{% endif %}

<div class="col-md-6">

<h5>Limits</h5>

<ul class="limits list-unstyled">

{% if plan.usage_limits == present %} {% for limit in plan.usage_limits %}

<li>

<i class="fa fa-signal"></i> {{ limit.metric.name }} &ndash; {{ limit.value }} {{ limit.metric.unit }}s per {{ limit.period }}

</li>

{% endfor %} {% else %}

<li>

<i class="fa fa-signal"></i> No limits

</li>

{% endif %}

</ul>

</div>

</div>

</div>

<div class="panel-footer">

<div class="row">

<div class="col-md-12">

<div class="row">

<div class="col-md-12">

<input type="checkbox" name="plan_ids[]" value="{{ plan.id }}">Signup to {{ plan.name }}</input>

<input type="hidden" name="plan_ids[]" value="{{ service.service_plans.first.id }}"></input>

</div>

</div>

</div>

</div>

</div>

</article>

</div>

{% endfor %}

</div>

{% endfor %}

<div class="container text-center">

<button type="submit" class="btn btn-cta-primary">Signup</a>

</div>

</div>

</form>

创建:multi_app_signup_form partial。

修改homepage:

修改成:

发布变更后,登录开发者界面,可以看到application plan的复选框:

我们选择两个app plan,API Unlimited 和ProductsBasicPlan,注册账户:

然后到admin门户激活:

然后用新建的账户登录开发者界面,可以看到两个应用。

魏新宇

  • 红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大魏分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档