sTransformationMiddleware();
// 初始化下游请求管道
builder.UseDownstreamRequestInitialiser();
// 使用自定义限流管道
builder.UseRateLimiting();
//使用请求ID生成管道
builder.UseRequestIdMiddleware();
//使用自定义授权前管道
builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware);
//根据请求判断是否启用授权来使用管道
if (pipelineConfiguration.AuthenticationMiddleware == null)
{
builder.UseAuthenticationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthenticationMiddleware);
}
//添加自定义限流中间件 2018-11-18 金焰的世界
builder.UseCzarClientRateLimitMiddleware();
//添加自定义授权中间件 2018-11-15 金焰的世界
builder.UseAhphAuthenticationMiddleware();
//启用自定义的认证之前中间件
builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);
//是否使用自定义的认证中间件
if (pipelineConfiguration.AuthorisationMiddleware == null)
{
builder.UseAuthorisationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthorisationMiddleware);
}
// 使用自定义的参数构建中间件
builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);
// 使用负载均衡中间件
builder.UseLoadBalancingMiddleware();
// 使用下游地址创建中间件
builder.UseDownstreamUrlCreatorMiddleware();
// 使用缓存中间件
builder.UseOutputCacheMiddleware();
//判断下游的是否启用rpc通信,切换到RPC处理
builder.MapWhen(context => context.DownstreamReRoute.DownstreamScheme.Equals("rpc", StringComparison.OrdinalIgnoreCase), app =>
{
app.UseCzarRpcMiddleware();
});
//使用下游请求中间件
builder.UseCzaHttpRequesterMiddleware();
return builder.Build();
}
这里是在最后请求前判断使用的下游请求方式,如果DownstreamScheme
使用的rpc
,就使用rpc
中间件处理。
Rpc处理的完整逻辑是,如何从http请求中获取想要解析的参数,这里需要设置匹配的优先级,目前设计的优先级为。
1、首先提取路由参数,如果匹配上就是用路由参数名称为key,值为value,按顺序组成第一批参数。
2、提取query参数,如有有值按顺序组成第二批参数。
3、如果非Get请求,提取body内容,如果非空,组成第三批参数
4、从配置库里提取rpc路由调用的服务名称和函数名称,以及是否单向调用。
5、按照获取的数据进行rpc调用并等待返回。
看了上面的设计是不是思路很清晰了呢?
1、rpc路由表设计
CREATE TABLE AhphReRouteRpcConfig
(
RpcId int IDENTITY(1,1) NOT NULL,
ReRouteId int, //路由表主键
ServantName varchar(100) NOT NULL, //调用的服务名称
FuncName varchar(100) NOT NULL, //调用的方法名称
IsOneway bit NOT NULL //是否单向调用
)
2、提取远程调用方法
根据上游路由获取远程调用的配置项目
public interface IRpcRepository
{
/// <summary>
/// 根据模板地址获取RPC请求方法
/// </summary>
/// <param name="UpUrl">上游模板</param>
/// <returns></returns>
Task<RemoteInvokeMessage> GetRemoteMethodAsync(string UpUrl);
}
public class SqlServerRpcRepository : IRpcRepository
{
private readonly CzarOcelotConfiguration _option;
public SqlServerRpcRepository(CzarOcelotConfiguration option)
{
_option = option;
}
/// <summary>
/// 获取RPC调用方法
/// </summary>
/// <param name="UpUrl"></param>
/// <returns></returns>
public async Task<RemoteInvokeMessage> GetRemoteMethodAsync(string UpUrl)
{
using (var connection = new SqlConnection(_option.DbConnectionStrings))
{
string sql = @"select T4.* from AhphGlobalConfiguration t1 inner join AhphConfigReRoutes T2 on
T1.AhphId=t2.AhphId inner join AhphReRoute T3 on T2.ReRouteId=T3.ReRouteId
INNER JOIN AhphReRouteRpcConfig T4 ON T3.ReRouteId=T4.ReRouteId
where IsDefault=1 and T1.InfoStatus=1 AND T3.InfoStatus=1 AND UpstreamPathTemplate=@URL";
var result = await connection.QueryFirstOr