那些年我们一起踩过的Dubbo"坑"
前言
微服务架构在如今的9102年已经不是什么新鲜的话题了,但是怎么做好微服务架构,却又是一个永恒的话题。比如服务粒度的划分,怎么控制好粗细?服务划分后,对于项目的部署会有什么改变?... 这会是一个很大的话题,以后可以分开篇章探讨一翻,但是我们本篇并不打算聊这个,而是讨论一下具体的实现技术--dubbo。
dubbo历史
2011 年末,阿里巴巴在 GitHub 上开源了基于 Java 的分布式服务治理框架 Dubbo,之后它成为了国内该类开源项目的佼佼者,许多开发者对其表示青睐。同时,先后有不少公司在实践中基于 Dubbo 进行分布式系统架构,目前在 GitHub 上,它的 fork、star 数均已破万。2014 年 10 月 30 号发布版本 dubbo-2.4.11,修复了一个小 Bug,版本又陷入漫长的停滞到2017年九月份。
在dubbo停滞的期间呢,当当网 Fork 了阿里的一个 Dubbo 版本开始维护,并命名为 dubbox-2.8.0。值得注意的是,当当网扩展 Dubbo 服务框架支持 REST 风格远程调用,并且跟随着 ZooKeepe 和 Spring 升级了对应的版本。之后 Dubbox 一直在小版本维护,2015 年 3 月 31 号发布了最后一个版本 dubbox-2.8.4。笔者公司用的也是这个版本,并稍微改造了下源码,下面会有提及。
其实在当前说到微服务,可能大家第一反应是springcloud,spring全家桶带来的便捷是显而易见的,然而为什么我们这里聊的是dubbo呢?原因之一是因为笔者公司只用了dubbo(别扔鸡蛋....),其二呢其实rpc框架很多原理是相通的,当我们理解了其中一个,再去看其他的框架,会有一种似曾相识的感觉,最后也没必要去争论XX框架的好与坏,选择最适合自己业务的就是最好的。
先交代下背景,我们这边是从2016年开始使用dubbo,使用的是dubbox-2.8.4 版本,然后因为一些场景不合适改了下代码,重新打包成2.8.5提交至公司的私服使用。好了,接下来就开始进入正文,聊聊这几年在dubbo使用过程中遇到坑,以及需要注意的地方吧。
正文
1、超时重试
这是一个很经典的坑,当时由于刚使用dubbo,很多配置都是基于默认的。刚好此时在项目中,有一个机器人送礼的逻辑比较复杂,当遇到某些特定的条件时,该逻辑的耗时会比正常情况下变长,这时候就出现了一个很神奇的现象,为何我只触发了一次送礼的请求,而线上却送了三次?
刚遇到这种情况可我惊呆了,重新审视了代码,发现并无问题。这就奇怪了,哪里来的3次?后来掉了几根头发以后,才在dubbo的文档中发现了服务这块有timeout跟retry属性,默认timeout=1000ms,retry=2。这下就豁然开朗,原来是第一次调用超时,导致又重试了2次,一共就是3次了。
找到问题的原因,我们就有办法解决了。由于我们这个接口不是幂等性的,而且也不用返回什么信息给调用者,所以我们可以通过一个线程池来执行这段耗时的逻辑,让rpc调用可以比较快的返回给调用者。这样就不存在超时的问题了。或者可以配合增加timeout时间跟retry=0也能实现,具体的业务逻辑需要自己找到合适的解决方案。
2、dubbo使用内网ip
正常情况下,我们的服务调用推荐走内网连接的方式,效率是比较高的。但是有些特殊的情况,我们需要dubbo注册服务的时候使用外网ip,该怎么修改呢?这时候就需要修改我们的服务器上 /etc/hosts 文件了,新增一条 “外网ip 主机名”的记录,restart我们的服务即可。
3、docker里面注册宿主机内网ip
说到微服务,当然也少不了docker了,我们当前用的是docker+overlay网络一个结构,直接把dubbo服务丢进容器里面跑的话,注册进zk的ip是容器ip。所以我们采取了一种折中的方式。
利用docker的特性,我们在创建容器的时候,把宿主机的ip以及需要暴露的端口写进容器的环境变量里面。然后就是修改dubbox的源码了,源码的com.alibaba.dubbo.registry.integration.RegistryProtocol类的getRegistedProviderUrl
方法,此方法用于返回注册到注册中心的URL。
private URL getRegistedProviderUrl(final Invoker<?> originInvoker){
//targetUrl 注册中心看到的地址
URL targetUrl;
URL providerUrl = getProviderUrl(originInvoker);
//配置的容器环境变量
String envParameterHost=System.getenv(ENV_HOST_KEY);
String envParameterPort=System.getenv(ENV_PORT_KEY);
if (StringUtils.isBlank(envParameterHost)||StringUtils.isBlank(envParameterPort)){//非容器环境:执行原来的注册逻辑
targetUrl=providerUrl.removeParameters(getFilteredKeys(providerUrl)).removeParameter(Constants.MONITOR_KEY);
}else {//容器环境,如果环境变量中DOCKER_NAT_HOST和DOCKER_NAT_PORT两个值都不为空则直接将这两个值作为url注册到zk
//执行重新拼接url的操作,涉及敏感代码这里不展示了
targetUrl=dockerRegUrlWithHostAndPort;
}
return targetUrl;
}
4、未注意服务重名
其实这是我们开发人员粗心大意出现的情况,开发的时候注册了2个相同签名的服务,但是业务逻辑是完全不同的,这会导致一个之前运行的正常的业务会偶尔调用失败,原因是因为dubbo的负载均衡策略,把一部分流量转移到我们新注册上来的服务上了,但是处理逻辑不同,导致错误。
5、版本的一致性
dubbo当前的releases版本已经去到2.7.1了,项目中要注意一下不同项目间版本的一致性,或者是dubbo跟dubbox的一些差别,最好做到统一,不然出现问题解决的成本会比较高。
6、属性配置的优先级
我们在dubbo的过程中会发现,提供者跟消费者中,很多属性是一样的,我们该怎么配呢?在dubbo的文档当中其实有推荐的用法。
在提供者端尽量多提供消费者端的属性。
参考文档,原因如下:
作服务的提供方,比服务消费方更清楚服务的性能参数,如调用的超时时间、合理的重试次数等
在 Provider 端配置后,Consumer 端不配置则会使用 Provider 端的配置,即 Provider 端的配置可以作为 Consumer 的缺省值 。否则,Consumer 会使用 Consumer 端的全局设置,这对于 Provider 是不可控的,并且往往是不合理的
Provider 端尽量多配置 Consumer 端的属性,让 Provider 的实现者一开始就思考 Provider 端的服务特点和服务质量等问题。
结语
其实在dubbo的使用过程中,还有挺多问题这里没列出来的,但是解决方法都差不多,首先文档要熟,做到心中有数,比如dubbo功能的成熟度,有些是不推荐在线上使用的,这时你就要谨慎了。然后文档里面确实是有遗漏的问题,我们有必要可以debug dubbo的源码,这个过程会比较痛苦,但是对于排查问题跟个人能力的提高是有很有帮助的。
大家在dubbo的使用过程中有什么问题也可以交流一下~
github:https://github.com/apache/incubator-dubbo
中文使用手册http://dubbo.apache.org/zhcn/docs/user/preface/background.html
那些年我们一起踩过的Dubbo"坑"的更多相关文章
- 那些年我们一起踩过的坑(javascript常见的陷阱)
1.object最后一个逗号 定义object直接量或json,最后一个逗号多写了,在ie下会报错,高级浏览器则不会,给只使用chrome调试的同学敲个警钟.踩了无数次这个坑了. 2.自动加分号 ...
- 三分之一的程序猿之社交类app踩过的那些坑
三分之一的程序猿之社交类app踩过的那些坑 万众创新,全民创业.哪怕去年陌生人社交不管融资与否都倒闭了不知道多少家,但是依然有很多陌生人社交应用层出不穷的冒出来.各种脑洞大开,让人拍案叫起. 下面我们 ...
- 【Fine原创】JMeter分布式测试中踩过的那些坑
最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试执行阶段工具本身对资源的过量消耗给性能测试带来了瓶颈, ...
- 与webview打交道中踩过的那些坑
随着HTML5被越来越多的用到web APP的开发当中,webview这一个神器便日渐凸显出重要地位.简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页面,css以及js代码 ...
- 美团在Redis上踩过的一些坑-目录(本人非美团)(转)
来自:http://carlosfu.iteye.com/blog/2254154 分为5个部分: 一.周期性出现connect timeout 二.redis bgrewriteaof问 ...
- 安装python爬虫scrapy踩过的那些坑和编程外的思考
这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬虫的比较发现开源爬虫scrapy比较好用.但是以前一直用的java和php,对python不熟悉,于是花一天时 ...
- [原创]阿里云RocketMQ踩过的哪些坑
由于公司的最近开始使用RocketMQ来做支付业务处理, 便开启了学习阿里云RocketMQ的学习与实践之路, 其中踩了不少的坑, 大部份是由于没有仔细查看阿里云的技术文档而踩的坑. 但是有一个非常大 ...
- Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!
Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Boot 2.x 的 Finchley 版本,现在一起为项目做一次整体框架升级. 升级前 ...
- Redis上踩过的一些坑
来自: http://blog.csdn.net//chenleixing/article/details/50530419 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DB ...
随机推荐
- JavaScript高级程序设计(一)
一.三种常见的著名的命名规则: 1.Camel(驼峰式命名):首字母是小写的,接下来的单词都以大写字母开头.例如:var myTestValue=0; 2.Pascal(帕斯卡命名):首字母是大写的 ...
- thinkphp框架实现删除上传的文件
public function article_delete(){ $article_id = I('get.article_id'); $model = M('zx_article'); $data ...
- sniffer pro 使用方法
一.捕获数据包前的准备工作 在默认情况下,sniffer将捕获其接入碰撞域中流经的所有数据包,但在某些场景下,有些数据包可能不是我们所需要的,为了快速定位网络问题所在,有必要对所要捕获的数据包作过滤. ...
- java的Calendar,获取月份少一月的问题及其它注意事项
java的Calendar,获取月份少一月的问题及其它注意事项: import java.util.*; public class DateClass{ public static void main ...
- opencv利用hough概率变换拟合得到直线后,利用DDA算法得到直线上的像素点坐标
图片霍夫变换拟合得到直线后,怎样获得直线上的像素点坐标? 这是我今天在图像处理学习中遇到的问题,霍夫变换采用的概率霍夫变换,所以拟合得到的直线信息其实是直线的两个端点的坐标,这样一个比较直接的思路就是 ...
- 第八章——降维(Dimensionality Reduction)
机器学习问题可能包含成百上千的特征.特征数量过多,不仅使得训练很耗时,而且难以找到解决方案.这一问题被称为维数灾难(curse of dimensionality).为简化问题,加速训练,就需要降维了 ...
- 在Python中用Request库模拟登录(一):字幕库(无加密,无验证码)
字幕库的登录表单如下所示,其中省去了无关紧要的内容: <form class="login-form" action="/User/login.html" ...
- Spring Batch 专题
如今微服务架构讨论的如火如荼.但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易.在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理.针对OLTP,业界有大量的开源框架.优秀的架 ...
- 在Ubuntu16.04上配置.Net Core 2 环境
一.安装.Net Core SDK 按照官方文档,执行以下命令安装SDK curl https://packages.microsoft.com/keys/microsoft.asc | gpg -- ...
- ajax技术基础详解
一.概述 1.什么是ajax 可以与服务器进行[异步]交互的技术,浏览器无需刷新 2.什么时候出现ajax? -- XMLHttp 微软 1999年微软公司发布IE5版本,内嵌了ajax技术 什么时候 ...