技术派:谁说API网关只能集成REST APIs?

一、API网关对API的集成

REST APIs的特点有:

  • 数据驱动
  • 允许多种数据格式(JSON,XML,文本)
  • 使用HTTPS协议的安全性
  • 轻量级框架

API的REST不适用的场景:

  • 使用非HTTP协议
  • 有状态
  • 受限于HTTP动词太少

接下来,我来看一种非REST APIs协议--SOAP。

WebService有两种方式,一是SOAP协议方式,在这种方式下需要WSDL,UDDI等,二是REST方式,这种方式不需要WSDL,UDDI等。

SOAP(原为Simple Object Access Protocol的首字母缩写,即简单对象访问协议)是交换数据的一种协议规范,使用在计算机网络Web服务(web service)中,交换带结构信息。SOAP为了简化网页服务器(Web Server)从XML数据库中提取数据时,节省去格式化页面时间,以及不同应用程序之间按照HTTP通信协议,遵从XML格式执行资料互换,使其抽象于语言实现、平台和硬件。

用一个简单的例子来说明SOAP使用过程,一个SOAP消息可以发送到一个具有Web Service功能的Web站点,例如,一个含有房价信息的数据库,消息的参数中标明这是一个查询消息,此站点将返回一个XML格式的信息,其中包含了查询结果(价格,位置,特点,或者其他信息)。由于数据是用一种标准化的可分析的结构来传递的,所以可以直接被第三方站点所利用。

SOAP它的特点有:

  • 功能驱动
  • WS-Security
  • 调用不能被缓存
  • 重载荷
  • XML数据格式

其他类型的非REST APIs协议还有:

Apache Thrift、Apache Spark and Python、Apache Avro

其中,Apache Thrift的特点有:

  • 接口定义语言
  • 多种目标语言
  • 低级传输(套接字,管道等)
  • 多种协议(JSON,紧凑型,二进制等)
  • 示例:Facebook FBOSS API,Evernote SDK,Elasticsearch API

Evernote就是印象笔记的国际版,这个我天天在用:

在3Scale中,我们可以通过 Fuse 作为集成平台,将非REST APIs集成进来。Fuse既可以集成REST也可以集成非REST的API:

  • Camel route exposing REST/HTTP endpoint
  • Camel producer endpoint using non-REST endpoin

也就说说,对于如SOAP类的API,我们会将它和Fuse进行集成,然后再将Fuse集成到API网关上。

二、实验验证

本实验中,我们部署一个SOAP-based JEE application。

我们先看一下应用的web service定义:

<wsdl:portType name="Stores">

<wsdl:operation name="getAllStores">

<wsdl:input message="tns:getAllStoresRequest"/>

<wsdl:output message="tns:getAllStoresResponse"/>

</wsdl:operation>

<wsdl:operation name="getStore">

<wsdl:input message="tns:getStoreRequest"></wsdl:input>

<wsdl:output message="tns:getStoreResponse"></wsdl:output>

</wsdl:operation>

<wsdl:operation name="createStore">

<wsdl:input message="tns:createStoreRequest"></wsdl:input>

<wsdl:output message="tns:createStoreResponse"></wsdl:output>

</wsdl:operation>

<wsdl:operation name="deleteStore">

<wsdl:input message="tns:deleteStoreRequest"></wsdl:input>

<wsdl:output message="tns:deleteStoreResponse"></wsdl:output>

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="StoresSOAP" type="tns:Stores">

查看源码:

查看SOAP web service的实施部分(我们看到源码中的四个public class最终会在前端展现):

@WebService(endpointInterface="com.redhat.service.Stores")

public class StoresWS implements Stores {

@Inject

StoreDao storeDAO;

@Override

public String createStore(Store store) {

store = new Store(store.getStoreName(),store.getStoreLat(),store.getStoreLong());

storeDAO.createStore(store);

return "Store ID:" + store.getStoreID() + " CREATED";

}

@Override

public StringdeleteStore(int storeID) {

storeDAO.deleteStore(storeID);

return "Store ID: " + storeID + " DELETED";

}

@Override

public Store getStore(int storeID) {

return storeDAO.getStoreById(storeID);

}

@Override

public StoresType getAllStores() {

StoresType st = new StoresType();

st.store = storeDAO.getAll();

return st;

}

}

这个应用将会部署在基于Oenshift的EAP上。

接下来,部署应用。先创建一个部署应用的project:

创建一个部署应用的模板:

接下来,部署应用:

--> Deploying template "david-stores-api/stores-soap" to project david-stores-api

Red Hat JBoss EAP 7.0 (no https)

---------

Stores SOAP Template.

A new EAP 7 based application has been created in your project.

* With parameters:

* Application Name=stores-soap

* Custom http Route Hostname=stores-api-david.apps.na1.openshift.opentlc.com

* Git Repository URL=https://github.com/gpe-mw-training/3scale_development_labs

* Git Reference=master

* Context Directory=Stores

* Queues=

* Topics=

* A-MQ cluster password=1wWTWDuk # generated

* Github Webhook Secret=GCubd7Tr # generated

* Generic Webhook Secret=hi5Aiw2r # generated

* ImageStream Namespace=openshift

* JGroups Cluster Password=RsIIhtvr # generated

* Deploy Exploded Archives=false

* Maven mirror URL=

* ARTIFACT_DIR=

* DATABASE_SERVICE_NAME=storesdb

--> Creating resources ...

configmap "create-db" created

secret "storesdb" created

service "storesdb" created

deploymentconfig "storesdb" created

service "stores-soap" created

route "stores-soap" created

imagestream "stores-soap" created

buildconfig "stores-soap" created

deploymentconfig "stores-soap" created

--> Success

Build scheduled, use 'oc logs -f bc/stores-soap' to track its progress.

Run 'oc status' to view your app.

查看应用的部署结果:

查看应用的路由:

通过浏览器进行访问:http://stores-api-david.apps.na1.openshift.opentlc.com/StoresWS?wsdl

接下来,我们使用一个在线的web based soap客户端:

输入刚才的地址进行浏览:

可以看到应用web service定义的内容(我们看到源码中的四个public class在前端展现):

点击call function,输出结果是:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getAllStoresResponse xmlns:ns2="http://www.rhmart.com/Stores/"><Stores><store><storeID>1</storeID><storeName>Downtown
  Store</storeName><storeLat>-34.6052704</storeLat><storeLong>-58.3791766</storeLong></store><store><storeID>2</storeID><storeName>EastSide
  Store</storeName><storeLat>-34.5975668</storeLat><storeLong>-58.3710199</storeLong></store></Stores></ns2:getAllStoresResponse></soap:Body></soap:Envelope>

接下来,我们部署fuse:

oc project $OCP_PROJECT_PREFIX-stores-api

oc create -f $HOME/lab/3scale_development_labs/templates/stores-fis.json

oc new-app --template=stores-fis --param ROUTE_HOST=stores-fis-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

fis构建并部署成功。

接下来,登录Openshift web console,查看fsi pod,打开java console:

查看路由信息:

我们可以看到,fuse的route已经将soap应用的各个功能模块( createStore、deleteStore、getAllStores、getStore)集成:

在源码层,一个路由调用SOAP的方法是:

<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>

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

我们查看OCP中fuse的路由:

$ curl -k stores-fis-david.apps.na1.openshift.opentlc.com/allstores

{"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}]}

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

创建应用到apicast-staging and apicast-production的路由:

接下来,我们到3scale上对应用进行集成.

创建应用:

创建app plan:

发布plan:

创建应用,选择刚才创建的app plan:

接下来,对应用进行API集成:

http://stores-fis-david.apps.na1.openshift.opentlc.com:80

https://stores-staging-apicast-david.apps.na1.openshift.opentlc.com:443

https://stores-production-apicast-david.apps.na1.openshift.opentlc.com:443

测试集成成功:

Prompt应用到生产:

接下来,我们分别访问两个环境中的引用:

Staging Environment

https://stores-staging-apicast-david.apps.na1.openshift.opentlc.com:443

Production Environment

https://stores-production-apicast-david.apps.na1.openshift.opentlc.com:443

$ curl -k "https://stores-staging-apicast-david.apps.na1.openshift.opentlc.com:443/allstores?user_key=d2a880ba1428dd8a505acae61349108f"

{"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}]}

$ curl -k "https://stores-production-apicast-david.apps.na1.openshift.opentlc.com:443/allstores?user_key=d2a880ba1428dd8a505acae61349108f"

{"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}]}

测试成功!

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

创建stock API business service applications:

将将stock-api模板导入OpenShift环境:

oc create -f $HOME/lab/3scale_development_labs/templates/stock-api.json

将数据源环境变量security添加到项目中:

oc secret new datavirt-app-config $HOME/lab/3scale_development_labs/Stock/datasources.env

创建SA:

jboss@rhtapimgmt / $ oc create serviceaccount datavirt-service-account

serviceaccount "datavirt-service-account" created

jboss@rhtapimgmt / $ oc policy add-role-to-user view system:serviceaccount:stock-api:datavirt-service-account

role "view" added: "system:serviceaccount:stock-api:datavirt-service-account"

接下来,部署应用:

oc new-app --template=stock-api --param HOSTNAME_HTTP=stock-api-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

创建成功以后:

一旦API和数据库窗格正在运行,通过向端点发出请求来测试odata服务:

{"@odata.context":"$metadata#stock","value":[{"productid":1,"amount":20.0,"storeid":1},{"productid":1,"amount":30.0,"storeid":2},{"productid":2,"amount":30.0,"storeid":1},{"productid":2,"amount":14.0,"storeid":2},{"productid":3,"amount":1.0,"storeid":1},{"productid":3,"amount":40.0,"storeid":2},{"productid":4,"amount":14.0,"storeid":1},{"productid":4,"amount":100.0,"storeid":2},{"productid":5,"amount":22.0,"storeid":1},{"productid":5,"amount":2.0,"storeid":2},{"productid":6,"amount":880.0,"storeid":1},{"productid":6,"amount":10.0,"storeid":2},{"productid":7,"amount":1200.0,"storeid":1},{"productid":7,"amount":32.0,"storeid":2},{"productid":8,"amount":532.0,"storeid":1},{"productid":8,"amount":1.0,"storeid":2},{"productid":9,"amount":10.0,"storeid":1},{"productid":9,"amount":123.0,"storeid":2},{"productid":10,"amount":1.0,"storeid":1},{"productid":10,"amount":730.0,"storeid":2}]}

接下来,我们可以创建路由,将stock-api和APIcast gateway关联:

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

然后再将应用集成到API网关上,这次集成的时候,mapping规则增加:

API Client选择:

然后就可以通过API网关的理由访问API了。

由于操作步骤与之前类似,这里不再详细赘述。

魏新宇

  • "大魏分享"运营者、红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2018-05-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

rman中三个不完全恢复场景(r6笔记第16天)

rman在数据的备份恢复中还是发挥了重大的作用,把冷备,热备这种手工备份方式做了集成化的管理,可以基于这个工具集完成相对复杂额备份恢复工作。 当然了rman相对...

2765
来自专栏大魏分享(微信公众号:david-share)

如何配置微服务的健康检查? | 微服务系列第九篇

随着环境中运行的微服务数量的增加,主动监控微服务的所有实例的运行状况变得更加重要。使用像OpenShift这样的容器管理技术,可以利用运行状况检查,来自动决定是...

852
来自专栏求索之路

从零开始仿写一个抖音App——日志和埋点以及后端初步架构本项目的 github 地址:MyTikTok

拿 Java 来说:比如我们有两个服务 A、B 在两个服务器上,此时我们要在 A 上调用 B 的服务获取其上的数据 Foo。那么在 A 中可以写成 Foo f ...

1535
来自专栏张善友的专栏

Advanced Logging For IIS

Advanced Logging 是一个挂在 IIS 核心功能中的模块,它可以接收来自于服务器(server)以及网站(site)中各式各样的记录,并且再经过由...

1846
来自专栏ThoughtWorks

登录工程:传统 Web 应用中的身份验证技术|洞见

标题中的 “传统Web应用” 这一说法并没有什么官方定义,只是为了与“现代化Web应用”做比较而自拟的一个概念。 所谓“现代化Web应用”指的是那些基于分布式架...

3595
来自专栏企鹅号快讯

SEO×静态、动态、伪静态URL的特性

1、静态页面 优点:相比其他两种页面,速度最快。不仅仅是秒杀秒客网加载速度最快,而且不需要从数据库里面提取数据,速度快的同时,也不会对服务器产生压力。 缺点:由...

1968
来自专栏about云

OpenStack计费Billing功能前瞻(一)

问题导读: 1.openstack现阶段计费项目情况? 2.需要怎样的环境实现? 3.在没有cloudkitty的情况下如何实现? 4.最终的流程图是什么? ...

3986
来自专栏阿杜的世界

Java Web技术经验总结(二)

673
来自专栏技术专栏

MapReduce学习笔记

wordcount: 统计文件中每个单词出现的次数需求:1) 文件内容小:shell2)文件内容很大:TB GB ??? 如何解决大数据量的统计分析==> ur...

772
来自专栏吴伟祥

logging总结 - log4j2使用流程[归档存储]

<web-app> 2.5 以前要多个依赖 log4j-web,还需要在web.xml配置listener、filter

1322

扫码关注云+社区