项目中也经常会遇到各种因为配置而引入的问题,很多技术支持解决不掉就找开发,结果发现大部分还是配置错误或网络不通等。如果在设计之初就能考虑到并针对这些问题做出应对设计,甚至给出异常的解决方案,确实可以减少很多处理现场问题的时间。

检查重复的jar包

最痴呆的问题,就是有多个版本的相同jar包,会出现新版本的 A 类,调用了旧版本的 B 类,而且和JVM加载顺序有关,问题带有偶然性,误导性,遇到这种莫名其妙的问题,最头疼,所以,第一条,先把它防住,在每个 jar 包中挑一个一定会加载的类,加上重复类检查,给个示例:

  1. static {
  2. Duplicate.checkDuplicate(Xxx.class);
  3. }

检查重复工具类:

  1. public final class Duplicate {
  2. private Duplicate() {}
  3. public static void checkDuplicate(Class cls) {
  4. checkDuplicate(cls.getName().replace('.', '/') + ".class");
  5. }
  6. public static void checkDuplicate(String path) {
  7. try {
  8. // 在ClassPath搜文件
  9. Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(path);
  10. Set files = new HashSet();
  11. while (urls.hasMoreElements()) {
  12. URL url = urls.nextElement();
  13. if (url != null) {
  14. String file = url.getFile();
  15. if (file != null && file.length() > 0) {
  16. files.add(file);
  17. }
  18. }
  19. }
  20. // 如果有多个,就表示重复
  21. if (files.size() > 1) {
  22. logger.error("Duplicate class " + path + " in " + files.size() + " jar " + files);
  23. }
  24. } catch (Throwable e) { // 防御性容错
  25. logger.error(e.getMessage(), e);
  26. }
  27. }
  28. }

检查重复的配置文件

配置文件加载错,也是经常碰到的问题。用户通常会和你说:“我配置的很正确啊,不信我发给你看下,但就是报错”。然后查一圈下来,原来他发过来的配置根本没加载,平台很多产品都会在 classpath 下放一个约定的配置,如果项目中有多个,通常会取JVM加载的第一个,为了不被这么低级的问题折腾,和上面的重复jar包一样,在配置加载的地方,加上:

  1. Duplicate.checkDuplicate("xxx.properties");

检查所有可选配置

必填配置估计大家都会检查,因为没有的话,根本没法运行。但对一些可选参数,也应该做一些检查,比如:服务框架允许通过注册中心关联服务消费者和服务提供者,也允许直接配置服务提供者地址点对点直连,这时候,注册中心地址是可选的,但如果没有配点对点直连配置,注册中心地址就一定要配,这时候也要做相应检查。

异常信息给出解决方案

在给应用排错时,最怕的就是那种只有简单的一句错误描述,啥信息都没有的异常信息。比如上次碰到一个 Failed to get session 异常,就这几个单词,啥都没有,哪个 session 出错? 什么原因 Failed? 看了都快疯掉,因是线上环境不好调试,而且有些场景不是每次都能重现。异常最基本要带有上下文信息,包括操作者,操作目标,原因等,最好的异常信息,应给出解决方案,比如上面可以给出:"从 10.20.16.3 到 10.20.130.20:20880 之间的网络不通,请在 10.20.16.3 使用 telnet 10.20.130.20 20880 测试一下网络,如果是跨机房调用,可能是防火墙阻挡,请联系 SA 开通访问权限" 等等,上面甚至可以根据 IP 段判断是不是跨机房。另外一个例子,是 spring-web 的 context 加载,如果在 getBean 时 spring 没有被启动,spring 会报一个错,错误信息写着:请在 web.xml 中加入: <listener>...<init-param>...,多好的同学,看到错误的人复制一下就完事了,我们该学学。可以把常见的错误故意犯一遍,看看错误信息能否自我搞定问题, 或者把平时支持应用时遇到的问题及解决办法都写到异常信息里。

日志信息包含环境信息

每次应用一出错,应用的开发或测试就会把出错信息发过来,询问原因,这时候我都会问一大堆套话,用的哪个版本呀?是生产环境还是开发测试环境?哪个注册中心呀?哪个项目中的?哪台机器呀?哪个服务? 累啊,最主要的是,有些开发或测试人员根本分不清,没办法,只好提供上门服务,浪费的时间可不是浮云,所以,日志中最好把需要的环境信息一并打进去,最好给日志输出做个包装,统一处理掉,免得忘了。包装Logger接口如:

  1. public void error(String msg, Throwable e) {
  2. delegate.error(msg + " on server " + InetAddress.getLocalHost() + " using version " + Version.getVersion(), e);
  3. }

获取版本号工具类:

  1. public final class Version {
  2. private Version() {}
  3. private static final Logger logger = LoggerFactory.getLogger(Version.class);
  4. private static final Pattern VERSION_PATTERN = Pattern.compile("([0-9][0-9\\.\\-]*)\\.jar");
  5. private static final String VERSION = getVersion(Version.class, "2.0.0");
  6. public static String getVersion(){
  7. return VERSION;
  8. }
  9. public static String getVersion(Class cls, String defaultVersion) {
  10. try {
  11. // 首先查找MANIFEST.MF规范中的版本号
  12. String version = cls.getPackage().getImplementationVersion();
  13. if (version == null || version.length() == 0) {
  14. version = cls.getPackage().getSpecificationVersion();
  15. }
  16. if (version == null || version.length() == 0) {
  17. // 如果MANIFEST.MF规范中没有版本号,基于jar包名获取版本号
  18. String file = cls.getProtectionDomain().getCodeSource().getLocation().getFile();
  19. if (file != null &amp;&amp; file.length() &gt; 0 &amp;&amp; file.endsWith(".jar")) {
  20. Matcher matcher = VERSION_PATTERN.matcher(file);
  21. while (matcher.find() &amp;&amp; matcher.groupCount() &gt; 0) {
  22. version = matcher.group(1);
  23. }
  24. }
  25. }
  26. // 返回版本号,如果为空返回缺省版本号
  27. return version == null || version.length() == 0 ? defaultVersion : version;
  28. } catch (Throwable e) { // 防御性容错
  29. // 忽略异常,返回缺省版本号
  30. logger.error(e.getMessage(), e);
  31. return defaultVersion;
  32. }
  33. }
  34. }

kill 之前先 dump

每次线上环境一出问题,大家就慌了,通常最直接的办法回滚重启,以减少故障时间,这样现场就被破坏了,要想事后查问题就麻烦了,有些问题必须在线上的大压力下才会发生,线下测试环境很难重现,不太可能让开发或 Appops 在重启前,先手工将出错现场所有数据备份一下,所以最好在 kill 脚本之前调用 dump,进行自动备份,这样就不会有人为疏忽。

http://dubbo.apache.org/books/dubbo-dev-book/principals/dummy.html

dubbo的防痴呆设计的更多相关文章

  1. VB 共享软件防破解设计技术初探(三)

    ×××××××××××××××××××××××××××××××××××××××××××××× 其他文章快速链接: VB 共享软件防破解设计技术初探(一)http://bbs.pediy.com/sho ...

  2. VB 共享软件防破解设计技术初探(二)

    VB 共享软件防破解设计技术初探(二) ×××××××××××××××××××××××××××××××××××××××××××××× 其他文章快速链接: VB 共享软件防破解设计技术初探(一)http ...

  3. VB 共享软件防破解设计技术初探(一)

    VB 共享软件防破解设计技术初探(一) ×××××××××××××××××××××××××××××××××××××××××××××× 其他文章快速链接: VB 共享软件防破解设计技术初探(二)http ...

  4. 进阶篇:4.3)DFA设计指南:防错设计( 防呆设计)

    本章目的:每一个装配步骤都有设计防错. 1.前言 关于防错设计,作者有想说的话: 1)防错设计是DFA重要的一条.因为太过重要,作者单独开一分章写! 2)只有理解了设计防错的重要,才会去设计防错特征. ...

  5. Dubbo入门到精通学习笔记(十):dubbo服务集群 、Dubbo分布式服务子系统的划分、Dubbo服务接口的设计原则

    文章目录 dubbo服务集群 Dubbo服务集群部署 Dubbo服务集群容错配置--集群容错模式 1.Failover Cluster 失败自动切换,当出现失败,重试其它服务器.`(缺省) 通常用于读 ...

  6. 微服务Dubbo和SpringCloud架构设计、优劣势比较

    本文主要围绕微服务的技术选型.通讯协议.服务依赖模式.开始模式.运行模式等几方面来综合比较Dubbo和Spring Cloud 这2种开发框架.架构师可以根据公司的技术实力并结合项目的特点来选择某个合 ...

  7. dubbo服务治理框架设计

    dubbo.JSF作为使用最广泛的服务端框治理架,其设计和实现思想值得进行学习研究. 整个服务管理框架核心的原理基于反射以及socket调用实现,服务管理框架包含服务的注册管理 服务的索引管理以及服务 ...

  8. Dubbo服务接口的设计原则

    1.接口粒度 1.1 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo暂未提供分布式事务支持.同时可以减少系统间的网络交互. 1.2 服务 ...

  9. Dubbo原理与框架设计

    Dubbo是常用的开源服务治理型RPC框架,在之前osgi框架下不同bundle之间的方法调用时用到过.其工作原理和框架设计值得开源技术爱好者学习和研究. 一.Dubbo的工作原理 调用关系说明 服务 ...

随机推荐

  1. 资源重复 uac.res resource kept(转)

    一般按照网上流传的方法制作UAC.RES放到DELPHI程序里面来就可以出现盾牌.但是某些DELPHI的项目在添加了UAC.RES后编译会报错,例如: [DCC Error] E2161 Warnin ...

  2. Ejabberd作为推送服务的优化手段(转)

    AVOS Cloud目前还在用Ejabberd做Android的消息推送服务.当时选择Ejabberd,是因为Ejabberd是一个发展很长时间的XMPP实现,并且基于Erlang,设想能在我们自主研 ...

  3. Java 获取本地IP地址

    private static String getIpAddress( ){ String ip = ""; Collection<InetAddress> colIn ...

  4. 基于zookeeper或redis实现分布式锁

    前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...

  5. .net 平台下的AI框架

    Aforge.net之旅——开篇:从识别验证码开始 基于AForge.Net框架的扑克牌识别 人工神经网络入门(4) —— AFORGE.NET简介 .NET开源工程推荐(Accord,AForge, ...

  6. protect,internal的区别

    protected: 爷爷有一张银行卡,爸爸可以用,儿子也可以用,隔壁老王不可以用(因为老王跟爷爷没有继承关系) internal: 王总有一张银行卡,秘书可以用,经理可以用,王总儿子不可以用(因为银 ...

  7. special points about git

    1 about "origin/master tracks the remote branch" 1.1 what does tracking mean? after " ...

  8. iOS 流布局 UICollectionView使用(简单使用)

    简介 UICollectionView是iOS6之后引入的一个新的UI控件,它和UITableView有着诸多的相似之处,其中许多代理方法都十分类似.简单来说,UICollectionView是比UI ...

  9. QQ登录集成到自己网站php代码(转载)

    我们现在在各大网站论坛都可以看到点击一个QQ图标就可以利用自己的QQ号在网站进行登录了,下面我来告诉你一段QQ登录集成到自己网站php代码,有需要的朋友可参考. 1.打开open.qq.com 添加创 ...

  10. [2018-11-03]2018年10月28日宁波dotnet社区活动回顾及下次活动预告

    离上次活动,有半年了,汗.之后尽量保证每月一次,以组织为主,多邀请嘉宾来分享. 本次活动不足之处 人手不足:由于活动组织事项受限于人手(目前就我一个,这次活动前后我又应邀给大红鹰学院应届生介绍dotn ...