- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring Cloud Alibaba 本地调试介绍及方案设计由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本地调试: 这里是指在开发环境中,部署了一整套的某个项目或者产品的服务,开发人员开发时,本地会起一个或多个服务,这些服务和开发环境中部署的服务是相同的,这种情况下,一个服务就会有多个实例,大多数微服务中的默认负载均衡策略都是轮询,这些实例会轮流被调用.
为了方便 本地调试,需要提供一种策略,可以指定在负载均衡时,选择哪个实例进行调用。在使用 Nacos 作为注册中心时,可以通过 上线和下线 的方式来选择使用哪个实例,但是这种方式只能强制调用某个实例,如果开发环境还有其他人在调试,自己程序 设置断点 时会阻塞所有调用,非常不利于多人调试的协调.
为了解决 本地调试 的问题,本文实现了一种简单实用的策略,可以通过 Nacos 动态配置服务路由,还可以基于用户,部门,组织等级别配置服务路由,实现 本地调试 的同时,实际上也实现 灰度发布.
本文基于 Spring Cloud Alibaba 框架,和 Spring Cloud 相比增加了一部分针对 Dubbo 的方案,因此本文适合以下框架参考:
Spring Cloud Gateway Spring Cloud Ribbon 。
下图是 Spring Cloud Alibaba 框架中,一次方法调用的可能情况,Ailbaba 这部分多的是图中 ServiceA -> ServiceB 部分使用 Dubbo 协议。Spring Cloud 框架中,用的是 ServiceA -> ServiceC 这种 Feign(HTTP) 方式.
图中的所有过滤器和拦截器,虽然名称不同,但是作用相同。这部分的主要作用就是 获取或传递路由规则,例如,可以实现基于 HTTP Header 设置路由规则的配置,可以基于 HTTP 和 token 实现基于用户的路由规则配置,这部分的实现和需求有关,没有统一的实现.
这里以这两种场景简单举个例子.
3.1 基于 HTTP Header 的本地调试方案 。
在这个方案中,按照上面的流程图叙述一遍.
service-route
请求头,请求头的内容为 servicea:10.10.10.130;serviceb:10.10.10.100;servicec:10.10.10.0/24
,在请求头中指明需要控制路由的服务信息(不需要控制的直接省略走默认)。ThreadLocal
)ThreadLocal
)RpcContext
将路由信息记录到 attachment
中,这样可以把路由配置传递到 ServiceB,如果 ServiceB 还需要调用其他服务,路由仍然会起到作用。RpcContext
获取路由配置,记录下来(如 ThreadLocal
),如果后续调用其他服务,逻辑和 4,5,6一样。在 6 这一步的 Provider Filter 结束调用的时候,注意清空路由信息(如 ThreadLocal.clear()
),避免对其他调用产生污染。IRule
实现基于自己路由规则的调用。RequestInterceptor
拦截器添加 service-route
头,将服务路由传递下去。3.2 基于操作用户的本地调试方案 。
基于操作用户的方案中,和上面类似,但是不需要在每次请求的时候设置 HTTP Header,但是需要一种方式存取服务路由的配置.
这里以使用 Nacos 配置管理实现服务路由配置的存取.
根据自己使用的用户在 Nacos 配置服务路由,配置名规则如 服务名.user-routes,使用 Spring Cloud Alibaba 的默认组 dubbo,用户服务路由的配置规则可以自己定义,这里举个简单例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
enabled:
true
# 启用,停用
ip:
10.10
.
0.0
/
24
# 默认优先IP或网段,所有IP都支持具体IP和网段
userIps: # Map<Long, String>,优先级最高,针对用户配置 IP 优先
# userId: IP
1
:
10.10
.
0.100
2
:
10.10
.
0.101
# 这部分定义根据自己需要设计
deptIps: # 针对部门配置
# deptId: IP
1
:
10.10
.
0.0
/
24
orgIps: # 针对组织配置
# orgId: IP
1
:
10.10
.
10.0
/
24
|
Spring Cloud Gateway 的 GlobalFilter 根据请求 token 获取 用户信息,记录用户信息(如 ThreadLocal).
ConfigService
,根据 服务名.user-routes
查询配置信息,同时监听该配置信息,根据这里的配置选择优先路由的服务。ThreadLocal
)。RpcContext
将用户信息记录到 attachment
中,这样可以把用户信息传递到 ServiceB,如果 ServiceB 还需要调用其他服务,用户信息仍然会起到作用。RpcContext
获取用户信息,记录下来(如 ThreadLocal
),如果后续调用其他服务,逻辑和 4,5,6一样。在 6 这一步的 Provider Filter 结束调用的时候,注意清空用户信息(如 ThreadLocal.clear()
),避免对其他调用产生污染。IRule
实现基于自己路由规则的调用。RequestInterceptor
拦截器设置token或用户信息,将操作用户传递下去。本文选择第 2 种方案,针对 1~9 步,分别讲解需要实现的接口和接口应用(生效)的配置.
上面提到的 ThreadLocal,实现时使用一个 static 变量存储,提供相应的存取清空的静态方法,方便跨接口的 用户信息 传递.
4.1 Spring Cloud Gateway 全局过滤器 。
假设有一个 UserGlobalFilter,该过滤器根据 token 获取并缓存用户信息,在请求完成后需要清空缓存的用户信息.
Spring Cloud Gateway 中的过滤器,直接在 @Configuration 的配置类中用 @Bean 提供即可.
4.2 Ribbon 负载均衡 。
实现 ribbon-loadbalancer 中的 com.netflix.loadbalancer.IRule 接口,将来调用具体服务时通过 choose 接口返回符合条件的实例.
实现这个接口之后,需要特殊的方式注册该接口,在启动类增加注解 @RibbonClients(defaultConfiguration = UserRuleConfiguration.class), 注解中指定了一个配置类,这个类一定不要添加 @Configuration 注解!!!.
在这个类中,通过 @Bean 注解返回一个 IRule 接口的实现.
在 Ribbon 中,会创建一个新的 ApplicationContext 来初始化这些配置,在这个新的 ApplicationContext 中,配置的 IRule 实现会被使用.
4.3 Spring MVC 拦截器 。
实现 HandlerInterceptor 拦截器,从请求获取用户信息并记录下来.
拦截器想要生效,需要提供一个配置类,继承 WebMvcConfigurer 接口,实现 addInterceptors 方法,在这个方法实现中添加拦截器的实现类.
4.4 Dubbo Consumer Filter 过滤器 。
实现Dubbo 的Filter接口,通过 RpcContext 传递前面记录的用户信息.
可以在实现类添加 @Activate 注解,指定 group 为 CommonConstants.CONSUMER.
按照 dubbo SPI 要求,添加 META-INF/dubbo/org.apache.dubbo.rpc.Filter 文件,写上实现类.
4.5 Dubbo Router 路由 。
这一步实际上可以放在 Dubbo 负载均衡实现,也可以用 Router 实现.
使用 Router 时,需要同时使用 RouterFactory 和 Router 接口,然后配置 RouterFactory 的 SPI 配置文件.
在 Router 的 route 方法中根据规则返回合适的 Invoker.
4.6 Dubbo Provider Filter 过滤器 。
实现Dubbo 的Filter接口,通过 RpcContext 获取传递过来的用户信息.
可以在实现类添加 @Activate 注解,指定 group 为 CommonConstants.PROVIDER.
按照 dubbo SPI 要求,添加 META-INF/dubbo/org.apache.dubbo.rpc.Filter 文件,写上实现类.
这个实现类可以和 4.4 的放一个 Filter 实现中,需要自己区分当前是 consumer 还是 provider 实现不同的逻辑.
4.7 Ribbon 负载均衡,同 4.2 。
这一步的实现和 4.2 一样,4.2 是用在 Spring Cloud Gateway 中,这里是配置到具体的服务中。配置方式一样.
4.8 Feign RequestInterceptor 拦截器 。
首先实现 RequestInterceptor 接口,在实现中往 requst 的 Header 中放置要传递的数据.
接口想要生效,需要和 Ribbon 类似的配置.
在 @EnableFeignClients 的注解中,通过 defaultConfiguration 设置一个 Feign 的配置类。在这个配置中通过 @Bean 提供 RequestInterceptor 接口的实现.
4.9 Spring MVC 拦截器,同 4.3 。
4.3 中是网关调用服务,4.9是服务通过 Feign (或resttemplate)调用服务,对被调用的服务来说都是 HTTP 请求,因此都会执行 Spring MVC 的拦截器,所以这里的实现是一样的.
本文提供了本地调试的方案和主要的实现要点,可以根据文中的关键指引和自己的实际需求实现自己的方案。关于本地调试如果有更好的方案,欢迎留言讨论.
判断IP是否相等或输入子网IP的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
static
boolean
ipInRange(String ip, String cidr) {
if
(cidr.indexOf(
'/'
) <
0
) {
return
ip.equals(cidr);
}
int
ipAddr = ipToInt(ip);
int
type = Integer.parseInt(cidr.replaceAll(
".*/"
,
""
));
String cidrIp = cidr.replaceAll(
"/.*"
,
""
);
if
(type ==
32
){
return
ip.equals(cidrIp);
}
int
cidrIpAddr = ipToInt(cidrIp);
int
mask =
0xFFFFFFFF
<< (
32
- type);
return
(ipAddr & mask) == (cidrIpAddr & mask);
}
public
static
int
ipToInt(String ip) {
String[] ips = ip.split(
"\\."
);
return
(Integer.parseInt(ips[
0
] <<
24
) |
Integer.parseInt(ips[
1
] <<
16
) |
Integer.parseInt(ips[
2
] <<
8
) |
Integer.parseInt(ips[
3
]));
}
|
到此这篇关于Spring Cloud Alibaba 本地调试方案的文章就介绍到这了,更多相关Spring Cloud Alibaba 本地调试内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/isea533/article/details/118513868 。
最后此篇关于Spring Cloud Alibaba 本地调试介绍及方案设计的文章就讲到这里了,如果你想了解更多关于Spring Cloud Alibaba 本地调试介绍及方案设计的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个 Cloud Run 服务,它通过 SQLAlchemy 访问 Cloud SQL 实例.但是,在 Cloud Run 的日志中,我看到 CloudSQL connection failed.
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 4年前关闭。 Improve t
在将 docker 容器镜像部署到 Cloud Run 时,我可以选择一个区域,这很好。 Cloud Run 将构建委托(delegate)给 Cloud Build,后者显然会创建两个存储桶来实现这
我正在尝试将 Cloud Functions 用作由 PubSub 触发的异步后台工作程序,并进行更长时间的工作(以分钟为单位)。完整代码在这里https://github.com/zdenulo/c
这是/etc/cloud/cloud.cfg的内容Ubuntu云16.04镜像: # The top level settings are used as module # and system co
如何从 Google Cloud Function 启动 Cloud Dataflow 作业?我想使用 Google Cloud Functions 作为启用跨服务组合的机制。 最佳答案 我已经包含了
我想使用 Cloud Shell 在我的第二代 Cloud Sql 实例上运行数据库迁移。 我找到了一个 example in the docs关于如何使用 gcloud 进行连接.但是当我运行命令时
我正在尝试使用 Google Cloud PubSub和我的 Google Cloud Dataproc群集,我收到如下身份验证范围错误: { "code" : 403, "errors" :
这是我的用例。 我已经有一个以私有(private)模式部署的 Cloud Run 服务。 (与云功能相同的问题) 我正在开发使用此 Cloud Run 的新服务。我在应用程序中使用默认凭据进行身份验
如何连接到 Cloud SQL 上的数据库,而无需在容器中添加我的凭据文件? 最佳答案 使用 UNIX 域套接字 (Java) 从云运行(完全托管)连接到云 SQL At this time Clou
我有一个google-cloud-ml作业,需要从gs存储桶加载numpy .npz文件。我遵循了this example上关于如何从gs加载.npy文件的操作,但是由于.npz文件已压缩,因此它对我
我想创建链接到另一个项目中的 Cloud Source Repository 的 Cloud Build 触发器。但是当我在应该选择存储库的步骤中时,列表是空的。我尝试了不同的许可,但没有运气。谁能告
向 Twilio 发送 SMS 时,Twilio 会向指定的 URL 发送多个请求,以通过 Webhook 提供该 SMS 传送的状态。我想让这个回调异步,所以我开发了一个 Cloud Functio
我需要更改我的项目 ID,因为要验证的 Firebase 身份验证链接在链接上显示了项目 ID,并且由于品牌 reshape ,项目名称已更改。根据我发现的信息,更改项目 ID 似乎不太可能。我正在考
用于部署我的 Angular 应用程序的 CI/CD 管道已关闭,但我看到 Google Cloud Run 在容器镜像更新后没有部署新修订版。 我已将 Cloud Build 设置为在 GitHub
报价https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless#enabling While Goog
Cloud Spanner 提供了两种不同的 API。 Cloud Spanner 读取与 Cloud Spanner SQL API 之间有什么区别? 最佳答案 在幕后,它们都使用相同的执行机制,因
我是 GCP 堆栈的新手,所以我对用于存储数据的 GCP 技术数量感到非常困惑: https://cloud.google.com/products/storage 虽然上面的文章中没有提到googl
我发现 Google Cloud Functions 的网络出站费用令人惊讶,我正在尝试了解发生这种情况的原因以及如何避免这种情况。 Stackdriver 监控表明有问题的函数是我的 ingest
我使用 Prisma使用 Cloud Run 和 Cloud SQL。在向 prisma.schema 提供 DATABASE_URL 后,它会在运行时抛出一个错误。 Can't reach data
我是一名优秀的程序员,十分优秀!