微服务网关
一、网关基本概念
-
解耦 解耦能够使客户端与微服务独立扩展,服务端可随意增加而客户端无需感知。网关层可扩展的功能包括缓存和抗并发等。
-
分发 网关通过负载均衡算法将请求分发到不同实例,提升系统伸缩性。这与Nginx的理念相似,但定位不同。
二、使用网关的原因 从基本概念可知网关的作用。使用网关可解决服务管理复杂、扩展性差等问题。
- 问题背景 当服务实例数量庞大时,管理复杂度增加,服务间调用关系错综复杂,维护困难。
传统方式中,服务间的调用需手动修改负载均衡配置,违反开闭原则,降低系统可用性。
- 网关模型 网关可剥离缓存、负载均衡、鉴权、限流等功能,使微服务专注于业务处理。
两种网关模型:
- 进程外:独立服务,推荐使用
- 进程内:侵入业务,不建议使用
三、网关实现 使用Net Core和Ocelot实现进程外网关。
- 实现环境 实现步骤:
- 创建独立API服务作为网关
- 改造项目为Abp vNEXT项目
- 集成Ocelot并修改配置文件
- 创建HttpApi并引用到网关项目
- 修改网关模块类配置
基本概念:
- 上游Upstream:请求地址
- 下游Downstream:服务地址
通过Nuget安装相关包:

添加中间件:
context.Services.AddOcelot(context.Services.GetConfiguration());
app.UseOcelot().Wait();
添加服务引用:
[DependsOn(
typeof(AbpAutofacModule),
typeof(OrderHttpApiModule),
typeof(ProductHttpApiModule)
)]
public class InternalGatewayModule : AbpModule
{ }
配置appsettings.json:
"Routes": [
{
"DownstreamPathTemplate": "/api/OrderService/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44361
}
],
"UpstreamPathTemplate": "/api/OrderService/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"DownstreamPathTemplate": "/api/ProductService/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44372
}
],
"UpstreamPathTemplate": "/api/ProductService/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:44329"
},
配置Swagger:
context.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "InternalGateway.Services", Version = "v1" });
c.DocInclusionPredicate((docName,description)=>true);
c.CustomSchemaIds(t=>t.FullName);
});
- 负载均衡 Ocelot支持轮询和最小连接数两种算法。配置示例:
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
- 自定义负载均衡 实现自定义随机算法:
public class RandomLoadBalancer : ILoadBalancer
{
private readonly Func<Task<List<Service>>> _services;
private readonly object _lock = new object();
private int _last;
public RandomLoadBalancer(Func<Task<List<Service>>> services)
{
_services = services;
}
public async Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
{
var service = await _services();
lock (_lock)
{
Random random = new Random();
int randomNum = random.Next(service.Count);
var next = service[randomNum];
return new OkResponse<ServiceHostAndPort>(next.HostAndPort);
}
}
public void Release(ServiceHostAndPort hostAndPort)
{
throw new System.NotImplementedException();
}
}
- 限流 配置限流:
"RateLimitOptions": {
"ClientWhitelist": [],
"EnableRateLimiting": true,
"Period": "10s",
"PeriodTimespan": 1,
"Limit": 1
}
- 熔断 使用Polly实现熔断:
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 500,
"TimeoutValue": 5000
}
- 路由缓存 配置缓存:
"FileCacheOptions":
{
"TtlSeconds": 15,
"Region": "somename"
}