前面幾篇講了微服務的諸多介紹以及一些開源的網關,開源雖好,但有時跟團隊用的技術棧和平臺不一樣,而且有些開源的網關功能太多,學習成本太高,遠遠高於自研的成本,因為有時,我們僅僅需要網關某幾個的功能,比如路由轉發、接口鑑權等等。今天,小編就來結合Asp.Net mvc webapi技術分享下微服務網關中路由轉發功能的實現。
首先來張網關的總體架構或說是設計圖:
nginx+asp.net webapi+redis+sqlserver+mongodb
nginx作為反向代理服務器,將比如http://www.xxx.com/apigateway/後面的地址統一轉發給api網關站點。
然後到了api網關這裡,由於api網關用的是webapi,在這個站點後面的路由就是asp.net webapi的路由機制了(還是利用asp.net mvc的路由機制,在用當下webapi技術來套一層皮吐出restful風格的api接口)。
那大家會問,那這麼多接口,難道來一個接口就要修改下路由配置文件然後在發佈嗎?
答案肯定不是這樣的。從上圖中,有個MSSQL,這個就是我們把mvc中的路由映射關係持久化存儲在MSSQL數據庫中,但是每次請求都去關係型數據庫MSSQL查接口,性能也是不理想,所以,我們可以把接口緩存到像Redis這種內存數據庫中。然後請求的跟蹤日誌存儲在MongoDB中,方便網關集群分佈式部署時,好查日誌。
當時,原理是這樣,這裡比較關鍵的一點是,那麼nginx到底該轉發到webapi中的哪個接口呢?
我們是這樣設計的,所有經過nginx的請求(當時路徑前綴是http://www.xxx.com/apigateway/)統一轉發到webapi中ApigatewayController/Reroute方法中,關鍵是這部該如何實現了。這裡用到兩個過濾器:
public class NotFoundControllerSelector : DefaultHttpControllerSelector
{
public NotFoundControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
HttpControllerDescriptor decriptor = null;
try
{
decriptor = base.SelectController(request);
}
catch (HttpResponseException ex)
{
var code = ex.Response.StatusCode;
if (code != HttpStatusCode.NotFound)
throw;
var routeValues = request.GetRouteData().Values;
routeValues["controller"] = "ApiGateway";
routeValues["action"] = "ReRoute";
decriptor = base.SelectController(request);
}
return decriptor;
}
}
public class NotFoundActionSelector : ApiControllerActionSelector
{
public NotFoundActionSelector()
{
}
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
HttpActionDescriptor decriptor = null;
try
{
decriptor = base.SelectAction(controllerContext);
}
catch (HttpResponseException ex)
{
var code = ex.Response.StatusCode;
if (code != HttpStatusCode.NotFound && code != HttpStatusCode.MethodNotAllowed)
throw;
var routeData = controllerContext.RouteData;
routeData.Values["action"] = "ReRoute";
IHttpController httpController = new CoreController();
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "ApiGatway", httpController.GetType());
decriptor = base.SelectAction(controllerContext);
}
return decriptor;
}
}
經過上面兩個過濾器,就會將http://www.xxx.com/apigateway/api/後面的所有請求轉發到http://www.xxx.com/apigateway/api/apigatway/reroute/
在reroute這個action你就可以實現網關的所有功能了,比如查Redis(MSSQL)、找到對應接口。。。
當然,做得優雅一點,可以用流水線的方式:
當然,這只是C#語言實現的一部分,你也可以用java或Go或Node.js去實現,思想都是一樣的,技術實現不同而已。
如果覺得有用,大家可以關注我,也可以下方留言互動一起探討。
閱讀更多 墨漂碼農 的文章