前言
情绪的尽头是沉默
1.微服务概念
1.1微服务发展
分布式解决性能问题,微服务解决维护性、扩展性、灵活性。
1.2微服务概念
微服务(或称微服务架构),是一种现代化的软件架构方法,它将一个应用程序分解为多个小型、独立的服务单元,每个服务都负责特定的业务功能,并且可以独立开发、测试、部署和扩展。
这些服务通常是松散耦合的,使用不同的技术栈和开发语言,并通过轻量级通信机制(如Rest API、消息传递 进行交互。微服务架构的核心在于提高应用程序的可维护性、可扩展性和灵活性,同时允许团队成员使用最适合其需求的技术和开发语言。与传统的大型单体应用架构相比,微服务架构能够更好地应对复杂系统和高速变化的技术环境。
特点:
- 一组小的服务
- 独立的进程
- 轻量级的通信
- 基于业务能力(DDD)
- 独立部署:迭代速度快
- 无集中式管理:无须统一技术栈,可以根据不同的服务或者团队进行灵活选择。
1.3微服务架构
微服务架构实施需要从业务领域、服务拆分、服务通信、数据管理、服务治理、自动化部署、监控与日志、测试策略等多个方面进行规划和设计。
1.4微服务技术栈
微服务架构实施需要从业务领域、服务拆分、服务通信、数据管理、服务治理、自动化部署、监控与日志、测试策略等多个方面进行规划和设计。
2.Nginx负载均衡
基于Net8创建一个WebApi服务:Peng.Microservice.ServiceA
在Peng.Microservice.ServiceA下cmd运行服务
dotnet run --urls=http://*:5000 --port=5000
dotnet run --urls=http://*:5001 --port=5001
配置Nginx
同一个服务可以启动多个进程进行访问。
3.Consul服务注册
基本使用概念之前写过:https://www.cnblogs.com/pengboke/p/16118746.html
3.1安装
补充到之前的博客了
https://www.cnblogs.com/pengboke/p/18156610
3.2服务注册
引入包
<PackageReference Include="Consul" Version="1.7.14.3" />
使用
// Consul
builder.Services.ConsulRegister(option => {
var consulConfig = configuration.GetSection("ConsulConfig").Get<ConsulConfig>();
option.Config(consulConfig);
});
app.UseConsul(builder.Services.BuildServiceProvider(), app.Lifetime, configuration);
启动
dotnet run --urls=http://*:5001 --port=5001
dotnet run --urls=http://*:5002 --port=5002
Peng.Microservice.ServiceA启动2个实例
查看Consul
3.3服务发现
创建控制台客户端获取ConsulClient注册实例并调用
3.4服务权重
添加权重命令
dotnet run --urls=http://*:5001 --port=5001 --weight=1
dotnet run --urls=http://*:5002 --port=5002 --weight=2
根据权重获取服务实例
因为5002权重大些,调用的几率会高
3.5健康检测
添加健康检测接口,并配置AgentServiceRegistration
Consul显示正常
4.Ocelot网关
4.1概念
常用网关:Kong、Spring Cloud Gateway、Bumblebee、Ocelot
基本概念之前写过,这里不过多赘述:https://www.cnblogs.com/pengboke/p/16118726.html
安装包
<ItemGroup>
<PackageReference Include="Ocelot" Version="23.2.2" />
<PackageReference Include="Ocelot.Provider.Consul" Version="23.2.2" />
<PackageReference Include="Ocelot.Provider.Polly" Version="23.2.2" />
</ItemGroup>
4.2Ocelot直连服务
注入服务
配置路由ocelot.json
"Type": "RoundRobin"意思时轮询,每个服务实例都访问一次
{
"Routes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": "5001"
},
{
"Host": "localhost",
"Port": "5002"
}
],
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS"
],
"UpstreamPathTemplate": "/ServiceA/{url}", //httn://localhost:端口号/ServiceA/Home/Get
"LoadBalancerOptions": {
"Type": "RoundRobin",
"LeastConnection": "RoundRobin" //"LeastComnection" //少连接数的服务器 "NoLoadBalance”//不负载均衡 /"CookieStickySessions” //会话粘滞 //
}
}
]
}
运行
dotnet run --urls=http://*:9000 --port=9000
循环10次,每1s一次,每个服务轮流调用
4.3Ocelot连接Consul
如果Ocelot直连服务实例,当某一个服务实例故障后,程序会无法连接。
所以需要连接Consul,故障后直接下机。
注入AddConsul
修改配置文件
//consul+ocelot
{
//服务中心信息
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
},
"Routes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceA/{url}", //httn://localhost:端口号/ServiceA/Home/Get
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS"
],
"UseServiceDiscovery": true, //使用服务发现
"ServiceName": "Peng.Microservice.ServiceA", //服务名称
"LoadBalancerOptions": {
"Type": "RoundRobin",
"LeastConnection": "RoundRobin" //"LeastComnection" //少连接数的服务器 "NoLoadBalance”//不负载均衡 /"CookieStickySessions” //会话粘滞 //
}
}
]
}
当断掉5001,使5001故障,Ocelot不会在来连接5001,一直使用可用的5002。
4.4Ocelot缓存
修改配置,增加FileCacheOptions节点
//consul+ocelot(缓存)
{
//服务中心信息
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
},
"Routes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceA/{url}", //httn://localhost:端口号/ServiceA/Home/Get
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS"
],
"UseServiceDiscovery": true, //使用服务发现
"ServiceName": "Peng.Microservice.ServiceA", //服务名称
"LoadBalancerOptions": {
"Type": "RoundRobin",
"LeastConnection": "RoundRobin" //"LeastComnection" //少连接数的服务器 "NoLoadBalance”//不负载均衡 /"CookieStickySessions” //会话粘滞 //
},
//缓存
"FileCacheOptions": {
"TtlSeconds": 10, //缓存时间
"Region": "ServiceA" //缓存区
}
}
]
}
循环20次,每2s一次,10s过期会重新请求。
4.5Ocelot自定义缓存
实现 IOcelotCache
注入IOcelotCache服务
改小过期时间,方便测试
测试调用,输出自定义缓存日志
4.6故障场景
1、重试策略(Retry):当服务调用失败时,Polly可以自动进行重试,这有助于 处理那些可能因为暂时性问题导致的服务不可用情况。
2、断路器(Circuit Breaker):当检测到服务连续不可用时,断路器策略会介入,快速返回错误响应,避免对下游服务的持续请求,从而预防服务雪崩现象。
3、超时策略(Timeout):为服务调用设置一个最大执行时间,超过这个时间的服务调用将被认为失败,可以采取预设的应对措施。
4、舱壁隔离(Bulkhead Isolation):通过限制对服务的并发调用数量,防止因某个服务的问题影响到整个系统的稳定性。
5、缓存策略(Cache):提供一种机制,可以在服务调用的结果不变的情况下直接使用缓存结果,减少不必要的服务调用。
6、降级策略(Fallback):当服务调用失败时,可以提供一个备用的逻辑或者数据作为响应,提高用户体验。
7、策略组合(PolicyWrap) : Polly针对不同的故障有不同的策略,我们可以灵活的组合策略,上述的六种策略可以灵活组合使用。
4.7Ocelot限流
配置限流,这里的策略为了方便测试配置策略5分钟最多访问3次。
{
//服务中心信息
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
},
"RateLimitOptions": {
"QuotaExceededMessage": "Too many requests!Please wait a moment!", // 当请求过载被截断时返回的消息,中文会出现乱码
"HttpStatusCode": 503 // 当请求过载被截断时返回的http status
}
},
"Routes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceA/{url}", //httn://localhost:端口号/ServiceA/Home/Get
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS"
],
"UseServiceDiscovery": true, //使用服务发现
"ServiceName": "Peng.Microservice.ServiceA", //服务名称
"LoadBalancerOptions": {
"Type": "RoundRobin",
"LeastConnection": "RoundRobin" //"LeastComnection" //少连接数的服务器 "NoLoadBalance”//不负载均衡 /"CookieStickySessions” //会话粘滞 //
},
//缓存
"FileCacheOptions": {
"TtlSeconds": 5, //缓存时间
"Region": "ServiceA" //缓存区
},
//限流
"RateLimitOptions": { //限流,限制了单位时间内的访问量
"ClientWhitelist": [], //白名单
"EnableRateLimiting": true,
"Period": "5m", //1s, 5m, 1h, 1d
"PeriodTimespan": 5, //多少秒之后客户端可以重试
"Limit": 3 //统计时间段内允许的最大请求数量
}
}
]
}
5分钟最多访问3次,第4次的时候直接返回503,然后5s之后可以再重新请求。
4.8Ocelot+Polly熔断
修改配置文件,需要配置网关IP端口
熔断策略:5s内允许三次错误,5s后可重新请求
//consul+ocelot+polly熔断
{
//服务中心信息
"GlobalConfiguration": {
"BaseUrl": "http://localhost:9000",
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
},
"RateLimitOptions": {
"QuotaExceededMessage": "Too many requests!Please wait a moment!", // 当请求过载被截断时返回的消息,中文会出现乱码
"HttpStatusCode": 503 // 当请求过载被截断时返回的http status
}
},
"Routes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceA/{url}", //httn://localhost:端口号/ServiceA/Home/Get
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS"
],
"UseServiceDiscovery": true, //使用服务发现
"ServiceName": "Peng.Microservice.ServiceA", //服务名称
"LoadBalancerOptions": {
"Type": "RoundRobin",
"LeastConnection": "RoundRobin" //"LeastComnection" //少连接数的服务器 "NoLoadBalance”//不负载均衡 /"CookieStickySessions” //会话粘滞 //
},
////缓存
//"FileCacheOptions": {
// "TtlSeconds": 5, //缓存时间
// "Region": "ServiceA" //缓存区
//},
//限流
"RateLimitOptions": { //限流,限制了单位时间内的访问量
"ClientWhitelist": [], //白名单
"EnableRateLimiting": true,
"Period": "1s", //1s, 5m, 1h, 1d
"PeriodTimespan": 5, //多少秒之后客户端可以重试
"Limit": 1000 //统计时间段内允许的最大请求数量
},
//熔断设置
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
"DurationOfBreak": 5000, // 熔断的时间5s,单位为ms
"TimeoutValue": 5000 //单位ms,如果下游请求的处理时间超过多少则自动将请求设置为超时 默认90秒
}
}
]
}
Peng.Microservice.ServiceA添加一个主动抛出异常的接口
注入Polly
5s内出现3次异常,第4次503,5s内都是503,然后5s过后可以重新请求。
4.9Polly服务降级
安装包
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
\Peng.Microservice.ServiceA添加接口GetExceptionByPolly,使用Policy进行降级,模拟当调用别的服务异常时返回Server Error
客户端调用
5.认证授权
5.1概念
以前简单的写过一些IdentityServer4:
https://www.cnblogs.com/pengboke/p/15738842.html
客户端模式:客户端模式只对客户端进行授权,不涉及到用户信息。如果你的api需要提供到第三方应用,第三方应用自己做用户授权,不需要用到你的用户资源,就可以用客户端模式,只对客户端进行授权访问api资源。
密码模式:需要客户端提供用户名和密码,密码模式相较于客户端凭证模式。通过User的用户名和密码向Identity Server申请访问令牌。
**(简化 没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。
授权码模式:授权码模式隐藏码模式最大不同是授权码模式不直接返回token,而是先返回一个授权码,然后再根据这个授权码去请求token。这比隐藏模式更为安全。从应用场景上来区分的话,隐藏模式适应于全前端的应用,授权码模式适用于有后端的应用,因为客户端根据授权码去请求token时是需要把客户端密码转进来的,为了避免客户端密码被暴露,所以请求token这个过程需要放在后台。
5.2授权服务
创建授权服务,并安装IdentityServer4
<PackageReference Include="IdentityServer4" Version="4.1.2" />
配置ids4
/// <summary>
/// 授权配置
/// </summary>
public class AuthConfig
{
/// <summary>
/// 定义ApiResource
/// 这里的资源(Resources)指的就是管理的API
/// </summary>
/// <returns>多个ApiResource</returns>
public static IEnumerable<ApiResource> GetApiResources()
{
return new[]
{
new ApiResource("ServiceA", "服务A")
{
Scopes={ "scope1" }//4.x必须写的
}
};
}
/// <summary>
/// 作用范围
/// </summary>
public static IEnumerable<ApiScope> GetApiScopes()
{
return new ApiScope[]
{
new ApiScope("scope1"),
new ApiScope("scope2"),
};
}
/// <summary>
/// 定义验证条件的Client
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId = "AuthCenter",//客户端唯一标识
ClientName="AuthenticationCenter",//客户端名称
ClientSecrets = new [] { new Secret("123456".Sha256()) },//客户端密码,进行了加密
AllowedGrantTypes = GrantTypes.ClientCredentials,
//授权方式,客户端认证,只要ClientId+ClientSecrets
AllowedScopes = new [] { "scope1" },//允许访问的资源
Claims=new List<ClientClaim>(){
new ClientClaim(IdentityModel.JwtClaimTypes.Role,"Admin"),
new ClientClaim(IdentityModel.JwtClaimTypes.NickName,"Admin"),
}
}
};
}
}
注入id4服务
运行授权服务
dotnet run --urls=http://*:9100 --port=9100
访问获取jwt
5.3JWT
JWT全称Json Web Token
把请求的Token放到https://jwt.io/
首先可以看到Token由Header(头部)、Payload(载荷)、Signature(签名)组成
然后看Payload发现获取的资源就是我们AuthConfig配置的
5.4.Ocelot配置id4
Peng.Microservice.GateWay网关服务Ocelot给API服务配置id4认证
Authority:认证服务地址
Ocelot配置id4路由
{
"DownstreamPathTemplate": "/connect/token",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9100
}
],
"UpstreamPathTemplate": "/connect/token",
"UpstreamHttpMethod": [ "Post" ]
},
{
"DownstreamPathTemplate": "/connect/authorize",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9100
}
],
"UpstreamPathTemplate": "/connect/authorize",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/connect/logout",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9100
}
],
"UpstreamPathTemplate": "/connect/logout",
"UpstreamHttpMethod": [ "Get" ]
}
运行3个服务
# 网关服务
dotnet run --urls=http://*:9000 --port=9000
# 授权服务
dotnet run --urls=http://*:9100 --port=9100
# 服务A
dotnet run --urls=http://*:5001 --port=5001
直接访问Api资源401
通过Ocelot网关请求Token,带上Token再访问Api
5.5授权角色
ocelot.json配置角色,只有Admin角色才可以访问
AuthConfig配置了客户端角色为Admin
所以请求到Token可以正常访问接口
修改配置的角色,id4客户端没有配置该角色权限,所以返回Forbidden(403)
标签:服务,--,Consul,Ocelot,http,ServiceA,IdentityServer4,客户端 From: https://www.cnblogs.com/pengboke/p/18156627