繰り返し作成ホイールシリーズ-ベースオセロット達成同様のAlipayのゲートウェイ・インタフェース・モード
入門
繰り返し作成ホイールシリーズは、それらの通常の要約の一部です。いくつかは面白い感じのいくつかの使用を共有するホイールホイールコミュニティベースの、に依存しています。神の目にいくつかの素晴らしいアイデアや方法は、比較的低いかもしれません。しかし、現実的な問題を解決するために、私が必要としている人々も同様のソリューションを探していると信じています。ここでは新しいアイデアプランとしてカウントすることができ、読者が詳細を鑑賞するためのより良い解決策を持っていることができれば、同様の問題があります。
もしコメントエリアに原因内部葛藤や怒りや不快感だけでなく、彼らは誤解されているビブラートを感じるので、総合的なコンディショニング喜びチャンネルに切り替える必要がない人は、できる限り直接Tucaoを読んだ後。
ゲートウェイプロファイル
ゲートウェイとは何か、なぜゲートウェイはありません。これらの問題は非常に包括的に説明するために多くのオンラインの記事があります。ここでは、説明複製しません。
しかし、コンテンツのゲートウェイの背後には、少なくとも以下の2点を知っておく必要があります。
APIゲートウェイは、唯一の入口システムサーバです。
APIゲートウェイアプローチのコア要素は、統合ゲートウェイアクセスマイクロサービスを介してクライアントのすべてと消費者側は、(等モニタリング、認証、ロード・バランシングを提供する)ゲートウェイですべての非ビジネス機能を処理することです。
デフォルトの実装
vs2019を使用して、次の実証プロジェクト、Asp.Netコア2.1開発
1. ASP.NETコアAPIプロジェクトAgile.Demo1.APIを作成し、オンラインショーケースのUIとして闊歩を使用
図1に示されるプロジェクト構造
図1
公開して実行し、縦横の実行を開始するために、私は図2のバッチスクリプトを書きました
図2
ダブルクリックで実行するために、図3の開始
図3
ブラウザは、ディスプレイ4を開きます
図4
闊歩文書を直接オンラインテスト各インターフェイス通常。
2. ASP.NETコアAPIプロジェクトAgile.Demo2.APIとAgile.Demo1.API同様のプロジェクトを作成します。
3.図5に示されているオセロットベースのゲートウェイサービス、プロジェクト構造を作成
図5
オセロットゲートウェイを行う本明細書で使用される場合、オセロットミドルウェア特定の順序の束であります
次のように配置されたコンフィギュレーションocelot.json、
{ "ReRoutes": [ //API01 业务接口1 { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 9001 } ], "UpstreamPathTemplate": "/demo1/{url}", "UpstreamHttpMethod": [ "Post", "Get" ], "ReRoutesCaseSensitive": false }, //API02 业务接口2 { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 9002 } ], "UpstreamPathTemplate": "/demo2/{url}", "UpstreamHttpMethod": [ "Post", "Get" ], "ReRoutesCaseSensitive": false } ] }
这个配置比较简单,就配置了两个下游的业务接口。
把两个业务接口站点和网关站点都运行起来,如图6
图6
使用postman直接测试demo1 里面的 saveorder接口,如图7
图7
使用postman直接测试demo2 里面的 saveorder接口,如图8
图8
使用postman通过网关访问demo1,如图9
图9
能正常返回数据,说明网关的转发正常。
通过网关访问demo2也类似,这里就不截图了。下面提供demo代码可以下载自己测试下。
这里只介绍,通过网关的转发,其他网关方面的更多应用不在这里做介绍。
新的问题
有一次,我们提供接口和其他部门对接。按照惯例把接口以及网关部署好,文档提供,让他们按照文档规定的传就可以了。
结果,他们看了文档后提出了疑问,这是什么网关。每个接口请求地址还得拼接出来作为完整的请求,我们代码要做很多调整啊。能不能做成支付宝那种,就一个地址固定不变,然后公共参数,业务参数封装的模式。因为这种模式封装的东西都有现成的,这样我们就不用很大的改动就可以快速对接了。看下支付宝接口,如图10
图10
我想你这公共参数还不是动态的,相当于原来我们提供的网关地址后面加的就是对应的动态数据,道理都一样的啊,但受阿里系影响,他们接口的开发还是对接都是习惯按照支付宝这种模式来的,封装的公共参数什么的都做好了,要调整很麻烦。接口不按照他们的样子来就别扭,增加他们工作量。
当时我想这怎么办,我出接口应该按照我们的要求来啊,但没办法不够强势,还得按照他们阿里系规则来,那就想办法吧。
想到ocelot也是一系列的中间件处理 的,我想那就增加一个中间件,把请求给拦截了,重新组合数据,再下发。
这样可以保证我们内部的调用不变,对外兼容这种请求方式。说干就干,先做个demo试验下能否行得通。
增加一个中间件GatewayMiddleware,代码如下,既然要按照支付宝接口的来,那干脆把公共参数这块整体搬过来。
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class GatewayMiddleware
{
private readonly RequestDelegate _next;
public GatewayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
//支持类似支付宝的网关模式
//公共请求参数
//app_id method format charset sign_type sign timestamp version app_auth_token biz_content
//请求参数(业务),建议json格式
//trade_no out_trade_no operator_id
if (httpContext.Request.Path.ToString().ToLower() == "/gateway"|| httpContext.Request.Path.ToString().ToLower() == "/gateway.do")
{
//调用方post form提交,获取公共请求参数,处理做转发
if (httpContext.Request.Method.ToLower() == "get")
{
httpContext.Response.ContentType = "text/plain;charset=utf-8";
await httpContext.Response.WriteAsync("调试错误,请回到请求来源地,重新发起请求");
return;
}
var reqForm = httpContext.Request.Form;
if (reqForm == null || reqForm.Count == 0)
{
httpContext.Response.ContentType = "text/plain;charset=utf-8";
await httpContext.Response.WriteAsync("调试错误,请回到请求来源地,重新发起请求");
return;
}
var app_id = reqForm.ContainsKey("appid") ? reqForm["appid"].ToString() : "";
var method = reqForm.ContainsKey("method") ? reqForm["method"].ToString() : "";//接口名称(格式:模块.控制器.方法) 比如demo1.Values.SaveOrder
var format = reqForm.ContainsKey("format") ? reqForm["format"].ToString() : "json";
var charset = reqForm.ContainsKey("charset") ? reqForm["charset"].ToString() : "utf-8";
var sign_type = reqForm.ContainsKey("sign_type") ? reqForm["sign_type"].ToString() : "md5";
var sign = reqForm.ContainsKey("sign") ? reqForm["sign"].ToString() : "";
var timestamp = reqForm.ContainsKey("timestamp") ? reqForm["timestamp"].ToString() : "";
var version = reqForm.ContainsKey("version") ? reqForm["version"].ToString() : "";
var app_auth_token = reqForm.ContainsKey("app_auth_token") ? reqForm["app_auth_token"].ToString() : "";
var biz_content = reqForm.ContainsKey("biz_content") ? reqForm["biz_content"].ToString() : "";//业务接口参数 json格式
//通过method参数拆分出 模块 控制器 方法
var methods = method.Split('.');
var moduleName = method.Length > 0 ? methods[0] : "";
var controllerName = method.Length > 1 ? methods[1] : "";
var actionName = method.Length > 2 ? methods[2] : "";
//区分有版本和无版本两种情况,version不传或传空就是无版本
var nextPath = string.IsNullOrEmpty(version) ? $"/{moduleName}/api/{controllerName}/{actionName}" : $"/{moduleName}/api/v{version}/{controllerName}/{actionName}";
//下游业务接口暂时只支持post json格式的请求
byte[] postData = Encoding.GetEncoding(charset).GetBytes(biz_content);
httpContext.Request.Path = nextPath;
httpContext.Request.ContentType = "application/json";
httpContext.Request.ContentLength = postData.Length;
httpContext.Request.Body = new MemoryStream(postData);
await _next(httpContext);
}
else
{
await _next(httpContext);
}
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class GatewayMiddlewareExtensions
{
public static void UseGatewayMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<GatewayMiddleware>();
}
}
Startup.cs增加如下代码,如图11
测试拦截成功,重新组装下发。能够正常返回,测试成功。
具体的操作看代码的说明,这里就不再赘述。
这里有一点要特别说明。因为公共参数是form表单post提交,所以调用方请求过来肯定是post方式。转到下游的时候这个请求类型没有改变,所有暂时只支持下游是post的接口。不过可以增加个参数或者使用format参数值来做区分下游具体是get还是post。因为现在format是json肯定只能是支持post。
测试联调
以访问demo1为例,这里有三种方式访问demo1,使用postman测试如下
1、直接访问,如上面图7
2、通过网关转发方式1,如上面图9
3、通过网关转发方式2,如图12
图12
使用这种方式还是有优势的,比如参数签名这块就可以从业务里面独立出来,在网关处理了。
总结
说服不了,就多干活,多想方案。
由于一个文件最大10M,这里拆开上传
APIDemo1代码下载,APIDemo2代码下载,APIGateway代码下载
感谢阅读,希望这篇文章能给你带来帮助!