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. react-pdf预览在线PDF的使用

    1.在react项目中安装react-pdf依赖包 建议安装8.0.2版本的react-pdf,如果安装更高版本的可能出现一些浏览器的兼容性问题: npm install react-pdf@8.0. ...

  2. SpringBoot——基础配置

    基础配置 配置格式 SpringBoot提供了多种属性配置方法 application.properties server.port=80 application.yml server: port: ...

  3. Tabby,一款老外都在用的 SSH工具,竟然还支持网页操作

    会编程的蜗牛 主要分享java编程,也会涉及其他方向的技术分享. 1篇原创内容 公众号 序言各位好啊,我是会编程的蜗牛,作为java开发者,或者说编程人员,程序员的我们,Linux服务器总是我们一个绕 ...

  4. CCF CSP-S 2024 提高组初赛解析

    本解析不提供阅读程序与完善程序题目的代码,如有需要请通过 luogu.com.cn 相关链接 下载 如有谬误烦请指正 答案 AACBB BDABD ACBCD ✓××BC ✓✓✓BCC ✓×✓CAC ...

  5. 如何理解iowait

    Linux中,%iowait 过高可能是个问题,严重的时候,它能使服务停止, 但问题是,多高才算高? 什么时候应该担心呢? 本文将讨论 iowait 的含义.相关的统计数据.原理以及 iowait的瓶 ...

  6. 技术分享 | 徐轶韬:从MySQL5.7升级到MySQL 8.0

    在6月20日举办的[墨天轮数据库沙龙-MySQL 5.7 停服影响与应对方案]中,甲骨文MySQL解决方案首席工程师徐轶韬分享了<从MySQL5.7升级到MySQL 8.0>主题演讲,本文 ...

  7. iOS使用SourceTree回滚回滚小结

    代码回滚,适用于的场景: 1.提交错代码,想放弃刚刚提交的部分:2.代码发生冲突,处理比较麻烦,为了代码安全,直接回滚到之前干净的代码.我个人理解,可以分为本地回滚和远程回滚: 一.本地回滚,回滚自己 ...

  8. mysql进阶-存储引擎篇

    本篇是将基础篇的知识进行深化了解底层机制的同时讲解企业中涉及到的高层级知识. 存储引擎 1.MySQL体系结构 连接层 最上层是一些客户端和链接服务,主要完成一些类似于连接处理.授权认证.及相关的安全 ...

  9. KubeSphere 宣布开源 Thanos 的企业级发行版 Whizard

    日前,青云科技宣布开源 Thanos 的企业级发行版 Whizard,为企业带来真正高可用.可扩展.可存储与查询海量监控数据.易运维.安全的 Prometheus 长期存储方案. Prometheus ...

  10. 详解 Hough 变换(基本原理与直线检测)

    Hough 变换原理与应用 前言: 详细介绍了 Hough 变换的基本思想.基本原理和应用等.其中大多都是自己的理解,难免有偏差,仅供参考. 文章目录 Hough 变换原理与应用 1. 基本概述 1. ...