灰度发布集群服务进行生产环境的日志打印调试
2017-04-01 19:28
375 查看
灰度发布集群服务进行生产环境的日志打印调试
情景模拟:当项目发布之后,某些功能在经过某次确定的操作【1】之后,使另一操作【2】不能正常使用。而当时的源代码由于技术升级,恢复比较困难。在此情景下,需要在线调试。当没有执行操作【1】时,打印操作【2】在执行过程中关键对象的属性值日志信息;当执行了操作【1】时,打印操作【2】在执行过程中关键对象的属性值日志信息。系统环境: Centos7、Docker1.12.1
应用环境:分布式集群服务,Docker容器化发布,多节点服务应用
说明:
1.在支持打印日志的过程中需要替换Docker容器中的jar包,要求Docker支持docker cp命令;
2.替换的jar和被替换的jar包生成的jdk版本需要一致;
3.在jar包替换之前,最好在容器里先进行备份,然后从容器外拷贝有日志生成功能的相同命名的jar包予以覆盖;
4.由于jar替换之后,容器需要重启,替换的结果才能生效,所以该项目最好是分布式集群服务,支持灰度发布。
问题再现与定位:
由于jdk提供的加密【Cipher 是有状态的,而且是线程不安全的】,即在同一应用中,使用不同的加密方式,彼此之间可能会有影响。在项目上线后,加密模块不定期的会出现加密后的加密串,协作的系统解不出原密码的问题。在此问题下,Cipher对象的变量就成为一个关键的因素,只要在出现问题时,和正常运行时打印出其内的属性值,就可以定位到具体问题,从而进一步解决问题。
在此猜想之下,由于加密模块是自己实现的,那么就可以在获取ciper对象之后打印出其内的属性值,而由于其内的属性几乎都没有提供get方法,所以考虑采用反射机制获取其属性值信息。具体编码如下:
//打印日志 private static Logger loggerError = LoggerFactory.getLogger("com.changan.sso.sdk"); /** * 通过反射机制打印出对象的属性值信息 * * @param object * @throws IllegalArgumentException * @throws IllegalAccessException */ private static void getObjectMessage(Object object) throws IllegalArgumentException, IllegalAccessException { Class userCla = (Class) object.getClass(); /* * 得到类中的所有属性集合 */ Field[] fs = userCla.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { Field f = fs[i]; f.setAccessible(true); // 设置些属性是可以访问的 Object val = f.get(object); // 得到此属性的值 loggerError.info("name:" + f.getName() + "/t value = " + val); } } /** * 加密 * * @param plaintext * @param key * @return */ public static String encrypt(String plaintext, Key key) { try { // 使用密钥加密 Cipher cipher = Cipher.getInstance("RSA"); loggerError.info("*********************加密cipher信息打印开始******************"); getObjectMessage(cipher); loggerError.info("*********************加密cipher信息打印结束******************"); cipher.init(Cipher.ENCRYPT_MODE, key); // 加密后 byte[] result = cipher.doFinal(plaintext.getBytes(UTF8)); // 返回结果 return KeyUtil.encryptBASE64(result); } catch (Exception e) { // 打印日志 loggerError.error("加密异常", e); return null; } }
将此代码编写好之后,采用Docker容器中的jdk版本进行编译,必要时构建成jar,并上传至服务器上,通过以下命令将其拷贝到Docker容器内相对应的目录下:
$ docker cp test-1.0.8-SNAPSHOT.jar c33b415ec2de:/apache-tomcat/webapps/test/WEB-INF/lib/
在logback.xml中增加打印给日志信息的文件支持:
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 --> <property name="LOG_HOME" value="/data/core/logs" /> <!-- sso.sdk相关 --> <appender name="sso.sdk" class="ch.qos.logback.core.rolling.RollingFileAppender"> <Encoding>UTF-8</Encoding> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <fileNamePattern>${LOG_HOME}/com.changan.sso.sdk-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日志最大的历史 30天 --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <!-- root --> <logger level="INFO" name="com.changan.sso.sdk"> <appender-ref ref="sso.sdk" /> </logger> <!-- root --> <root level="INFO"> <appender-ref ref="console" /> <appender-ref ref="defaultLogFile" /> </root>
添加完毕后,保存并退出容器。执行容器重启命令:
$ docker restart test-web
随后安装执行正确的加密方式调用一次,在按照执行错误的加密方式调用一次,获取的日志信息如下:
从中明显可以得出,两次加密的加密提供商明显不同,问题定位准确,达到检验推测的目的。
相关文章推荐
- 如何对生产环境的JAVA应用进行远程调试
- log4net 发布到生产环境不写日志的解决方法--使用 NLog日志
- php生产环境 用 php://stdout 进行 安全 高效 调试
- 【Android】自动判断调试环境决定是否打印日志
- Nagios监控生产环境redis集群服务实战
- Docker 生产环境之日志 - 查看容器或服务的日志
- 如何在生产环境使用Btrace进行调试
- 互联网项目发布环境:测试、回归、预发布、灰度发布、生产环境的见解
- shell 管理SpringBoot 生产环境服务 (备份日志)
- Spring Cloud Spring Boot mybatis分布式微服务云架构(三十九)对log4j进行多环境不同日志级别的控制
- 如何在生产环境使用Btrace进行调试
- php-fpm 生产环境 调试信息 日志系统 设计 支持 thinkphp
- 回归自然-测试、回归、预发布、灰度发布、生产环境自己的理解
- 如何对生产环境的JAVA应用进行远程调试
- 生产环境WEB服务管理脚本之日志检测脚本
- 测试、回归、预发布、灰度发布、生产环境区别
- CXF之使用jaxws API 发布服务与进行客户端调用
- 使用VS2005搭建典型高效的SharePoint开发环境,提高生产效率,包含远程调试,自动部署
- 一个简单的用于嵌入式Linux开发的C调试日志打印接口
- 在Linux下安装android开发环境并以USB调试方式链接手机进行开发