2022年10月开始,公司从阿里请来的架构师将全力推进服务拆分这个计划。实际上这个计划早就提上日程了,只是没有一个带头大哥带着把这个事情搞起来,因为这个系统太庞大了,还非常的复杂,当时就没有哪一个人是对系统完全了解的,很多底层的非核心的原子服务干啥的都不清楚。平时也就核心业务所涉及到的几个服务是被大家所熟知的,其他的都是有待考察的系统。就在这样的背景下,就直接开干了。

所有的服务都从帆一云迁移到阿里云上,所以,所有的中间件也是购买的现成的阿里云的云产品。所有的服务都迁移过来了,发现整体流程跑不通,面对这种问题的解决思路提前就已经定好了,我们都知道在迁移的过程中会有很多想想不到的问题,然后真的是遇到什么问题就解决什么问题。前面还好,遇到的都是偏硬件、偏网络和安全的问题,这些问题在运维的协助下就轻松搞定了。因为还没有涉及到业务,就很容易解决。但是后面就遇到了一个非常棘手的问题,就是所有的dubbo服务现在都跑在阿里云上, 但是系统中的有些服务调用的是没有迁移的接口,这些接口就是车联的接口。存储了人车关系的数据和车辆相关的信息。

迁移的过程中,为了减少blocking的时间,我们每天会有晨会和晚上总结的会议,大家在会议上把遇到的blocking的问题提出来,因为有很多的问题都是相识的,所以在一起分享一下基本都能解决。后面我也是提议在Confluence上共享遇到的问题和解决方案,这样,大家遇到问题的第一时间到这个文档里面去找,找不到再去自己解决,解决后把解决方案同步到这里。实际上这种共享的思维一直被使用,到我走的时候我们还在不断的去填充自己的踩过的坑。

分析问题原因,主要原因就是原来的大家的所有的服务为了调用方便,都注册到了同一个ZK集群上,然后C端、B端、车联有一部份服务就都是发布到这个注册中心上,这样服务调用就少了很多的沟通成本。然后,对应C端迁移计划来讲,我们只是把C端的服务迁移出来了,对原来dubbo服务直接调用的接口是没有法办调用的,因为夸云了。实际上,很多问题如果只是从技术角度解决的话是很容易的,dubbo是支持多个注册中心的,它可以把我们调用的那几个接口发布到阿里云的注册中心上就可以了,但是,难就难在业务的方的妥协。车联不同意,也不想这么麻烦的耽误自己的项目计划,因为都是人力成本嘛,理解。

我的解决方案是使用代理服务。整理思路就是我们去搞一个代理服务,发布在原有的集群中,这个proxyService 是可以像原来那样调用车联的服务,然后提供一个http的对外接口。。这样一来,阿里云服务通过dubbo调用的车联的接口就可以通过http的方式调用proxyService暴露的接口。这样还存在一个问题,就是要将调用车联的接口的全部识别出来,然后在客户端发起调用的时候进行过滤拦截,使用http进行调用即可。这样完整的联路就打通了。听起来没有什么问题,但实际上还会遇到问题,站在对方的角度考虑问题是,你部署自己的服务得有自己的机器,不然你的服务出现了问题会影响到他们现在有的服务,然后就是一系列的是发邮件走流程搞基础配置,最终才把服务发布起来。

经过多次评审,接受多方的挑战,最终这样的方案通过并落地了。总是,是不容易。以下是自定义的Dubbo

public class CustomStubProxyFactoryWrapper implements ProxyFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(StubProxyFactoryWrapper.class);
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HttpRouter.class);
private final ProxyFactory proxyFactory;
private Protocol protocol;
static String active = System.getProperty("spring.profiles.active"); public CustomStubProxyFactoryWrapper(ProxyFactory proxyFactory) {
this.proxyFactory = proxyFactory;
} public void setProtocol(Protocol protocol) {
this.protocol = protocol;
} public <T> T getProxy(Invoker<T> invoker) throws RpcException {
logger.info("*************rpc代理已经启用{}***************", active);
T proxy = Proxy.getProxy(this.getInterfaces(invoker)).newInstance(new CustomInvocationHandler(invoker));
if (GenericService.class != invoker.getInterface()) {
String stub = invoker.getUrl().getParameter("stub", invoker.getUrl().getParameter("local"));
if (ConfigUtils.isNotEmpty(stub)) {
Class<?> serviceType = invoker.getInterface();
if (ConfigUtils.isDefault(stub)) {
if (invoker.getUrl().hasParameter("stub")) {
stub = serviceType.getName() + "Stub";
} else {
stub = serviceType.getName() + "Local";
}
} try {
Class<?> stubClass = ReflectUtils.forName(stub);
if (!serviceType.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName());
} try {
Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType);
proxy = constructor.newInstance(proxy);
URL url = invoker.getUrl();
if (url.getParameter("dubbo.stub.event", false)) {
url = url.addParameter("dubbo.stub.event.methods", StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
url = url.addParameter("isserver", Boolean.FALSE.toString()); try {
this.export(proxy, invoker.getInterface(), url);
} catch (Exception var9) {
LOGGER.error("export a stub service error.", var9);
}
}
} catch (NoSuchMethodException var10) {
throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), var10);
}
} catch (Throwable var11) {
LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + var11.getMessage(), var11);
}
}
} return proxy;
} public Class<?>[] getInterfaces(Invoker invoker) throws RpcException {
Class<?>[] interfaces = null;
String config = invoker.getUrl().getParameter("interfaces");
if (config != null && config.length() > 0) {
String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null && types.length > 0) {
interfaces = new Class[types.length + 2];
interfaces[0] = invoker.getInterface();
interfaces[1] = EchoService.class; for(int i = 0; i < types.length; ++i) {
interfaces[i + 1] = ReflectUtils.forName(types[i]);
}
}
} if (interfaces == null) {
interfaces = new Class[]{invoker.getInterface(), EchoService.class};
} return interfaces;
} public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
return this.proxyFactory.getInvoker(proxy, type, url);
} private <T> Exporter<T> export(T instance, Class<T> type, URL url) {
return this.protocol.export(this.proxyFactory.getInvoker(instance, type, url));
}
}

创建自定义的starter,需要设置默认配置信息:

使用自定义的SPI。

程序员,多学技术,思路打开。突然想起来了一句话,是用来描述艾弗森的。大概意思是:你用一百种方式过他,而他只用一种方式过你。

贴几个地址:

https://cn.dubbo.apache.org/zh-cn/docs/references/spis/proxy-factory/

服务拆分之《Dubbo服务跨云通信》的更多相关文章

  1. 阿里云 EDAS-HSF 用户指南

    阿里云 EDAS-HSF 用户指南 针对 EDAS v2.3.0©Alibaba EDAS 项目组2015/8/19 1 前言本文档旨在描述阿里云 EDAS 产品中应用服务化模块的基本概念,以及如何使 ...

  2. 阿里云OCR图片转换成文字识别调用

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using S ...

  3. 网卡配置文件详解 用户管理与文件权限篇 文件与目录权限 软连接 tar解压命令 killall命令 linux防火墙 dns解析设置 计划任务crond服务 软件包安装 阿里云 yum源 安装

    Linux系统基础优化及常用命令 Linux基础系统优化 引言没有,只有一张图. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. ...

  4. 国内首个全域边缘节点服务发布,阿里云助力企业把握5G机遇

    7月24日,阿里云峰会开发者大会在上海世博中心举办.作为2019年首场最受瞩目的云计算开发者大会,阿里云携一众云计算技术大牛与开发者面对面,探讨各自领域的技术干货与前沿趋势.同时,也发布了多项重大重磅 ...

  5. 阿里云入坑指南&&nodejs 安装配置

    买了阿里云1G1核1M的机器(800元,3年) 登录阿里云-实例-选择实例所在地区-重置密码 用公网IP ssh连接 #升级CentOS yum -y update #安装or更新组件 yum -y ...

  6. ECS服务里或者阿里云服务器的二级域名设置方法

    我们要实现的效果是,xuxinshuai.abc.com ,具体怎么实现,看下面的流程 第一步:备案域名要有,假如就是www.abc.com 第二步:网站的服务器是IIS的情况下,在部署网站时,需要设 ...

  7. express 配置 https 服务 ( 以阿里云服务器为例), 探索一周终于搞定

    首先最重要的是 你要明白 https接口的接收或者发送 的形式 是  https://域名:端口号   而不是 https://ip:端口号   一,首先,去阿里云注册免费ssl证书   1,在搜索框 ...

  8. 转载一篇阿里云Terraform 开发指南

    连接:https://www.jianshu.com/p/0aebea117cae 是一个比较详细的开发指南          

  9. 阿里云短信服务调用例子-Python

    阿里云短信服务调用例子 阿里云官方文档https://helpcdn.aliyun.com/document_detail/101893.html 首先需要安装阿里云PythonSDK(下面是pyth ...

  10. 阿里云服务(一) OSS

    阿里电子商务迄今是中国最大的电商网站,各个厂商都在去模仿.就像google的大数据处理,Hadoop的思想等等,只有做出了一些成绩,起了带头羊,那么将会是非常吃香的.从今天开始简单学习了解一下阿里的各 ...

随机推荐

  1. 大年初四,Flutter Forward 中国社区直播活动与你不见不散

    之前我们预告过,2023 年 1 月 25 日 (年初四),Flutter 团队将在肯尼亚首都内罗毕举办 Flutter Forward 大会,并同时开启线上直播.本次活动将为展示最新的 Flutte ...

  2. Brainstorm 了道题但是不会做

    题 因为没想出来暂时没定数据范围,不过应该会在 \(n^{2}\) 到 \(n^{3}\) 级别 我的一个思路是先对合法的方案连并查集,然后并查集内判重,但是不会算方案数,因为假如找到重的了不能直接看 ...

  3. SuperMap iManager云套件数据动态更新刷新地图与数据服务

    一.使用背景 有这么一个需求,后端也就通过SuperMap iDesktop或数据库更新了新增或更新某个数据地理信息后,云套件SuperMap iManager中的服务没有更新,无法实时查看到更新的数 ...

  4. 【赵渝强老师】删除表和Oracle的回收站

    一.Oracle的Drop Table语句 首先,我们来看一下Oracle Drop Table的语法格式. 解释一下里面的参数: schema Schema表示方案名称,这里可以理解为用户名,缺省为 ...

  5. 一个SMMU内存访问异常的问题

    最近碰到棘手的问题: 以太网进行iperf测试时, 发生了SMMU (System Memory Management Unit)访问异常导致内核崩溃. 原本只是内部测试发现, 后面在试验车上也概率性 ...

  6. 【PyTorch】state_dict详解

    这篇博客来自csdn,完全用于学习. Introduce 在pytorch中,torch.nn.Module模块中的state_dict变量存放训练过程中需要学习的权重和偏执系数,state_dict ...

  7. Vue3中的新的内置组件

    在vue2中的内置组件: 动态路由中的 component :作用:动态显示路由的挂载点,使用 is 属性动态显示组件 : keep-alive :作用:使被包裹的组件保留状态,避免被重新渲染 : 路 ...

  8. Vmware挂载san存储_vSphere 6.x 共享存储LUN丢失分区表修复(精华)

    Vmware挂载san存储_vSphere 6.x 共享存储LUN丢失分区表修复 炎炎夏夜客户机房空调意外故障,前端ESXI物理服务器由于温度过高都自保关机,存储和SAN没有自保关机.上班修复空调后, ...

  9. 再见,Centos!

    近日,CentOS官方宣布CentOS系列稳定版Linux系统将停止维护,取而代之的是测试版的CentOS Stream,这也意味着CentOS将会退出历史舞台,因此引发了CentOS用户的强烈不满. ...

  10. Seralizable

    class CSer { private String name; private int age; public CSer() { } public CSer(String name, int ag ...