skywalking插件开发的注意事项

最近蚂蚁金服中间件开源了 sofa 相关的部分组件,比如 rpc,欢迎大家参与讨论贡献,为 rpc 做链路适配的时候,skywalking 现在快到5.0版本了. 已经不支持 h2暂时,开发过程中了,环境的搭建.以下部分字段不能少.否则外面无法连接 es. docker run -d -p 9200:9200 -p 9300:9300 -e "network.host=0.0.0.0" -e "transport.host=0.0.0.0" -e "network.publish_host=0.0.0.0" -e "xpack.security.enabled=false" -e "network.bind_host=0.0.0.0" -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:5.5.0 这条命令会搞定. 同时 application.yml 文件中 storage: elasticsearch: cluster_name: docker-cluster cluster_transport_sniffer: false cluster_nodes: localhost:9300 index_shards_number: 2 index_replicas_number: 0 ttl: 70 这一段改一下. 其他的一些网上已有的文档,可以看看.SkyWalking 源码分析 —— 调试环境搭建

2018-05-13 · 1 min · bystander

javOSize:新一代java分析工具

介绍 最近看到这么个工具-javOSize .官网地址,去官网看了下.发现介绍很有意思,叫做 the missing sugar for your Java cup.(你的咖啡杯中缺少的那颗糖).于是感受一下这颗糖到底甜不甜 安装 安装非常简单,从这里下载,其实完成之后就是一个jar包.非常简单,不用配置啥的. 简单使用 使用方法就是从先附加到一个java进程上,在linux,上我直接执行 ps aux|grep java 就能看到了.不废话,得到java进程的pid之后,运行 java -jar javosize-1.0.9.jar pid pid就是pid的号了. 然后会看到如下图的界面,表示已经附加成功了.先看看都有啥.执行ls.看到有这么几个命令.我比较单纯,刚开始以为是可执行文件.结果丢人了.看了下官方文档,才知道是目录.进入对应的目录.然后执行ls就能看到对应的信息了.ls简直不能再万能..改目录支持的所有命令通过在对应的目录执行help来查看.个人尝试觉得好的功能有. 动态修改类 进入CLASSES目录,然后通过执行 ls|grep xxx 来找到需要修改的类,然后通过vi 就可以直接编辑.编辑完成后,直接保存就会动态替换.文档里说是支持jdk1.7以上,对1.6的支持估计是不行的.没有测试. 无须重启开启jmx 直接挂载之后,执行cd REPOSITORY 然后执行就好了. exec START_JMX_SERVER 6666 拦截任意代码 可以动态添加类似Spring中的aop方法.用于打印一些调用日志,排查线上问题.进入INTERCEPTOR目录.然后通过如下的方法给某个类的某个方法添加拦截器. create TickServlet begin mypackage.Hello doGet System.out.println("Servlet invoked"); 检测内存泄漏 进入 REPOSITORY 目录,执行 exec TOP_FAT_STATIC_VARIABLES 5 com.apache.*会取出某个包下面占用大小最大的5个类.会很方便找到. 自动检测性能问题 PROBLEMS 目录专业解决这种问题.进入目录后.执行ls命令.会看到这样的场景 Concurrency Deadlocked: false Memory High GC (>2%): false 这里目前只检测了死锁和频繁GC.已经很有用了.至于效果还有待观察. 无需重启开启GC 日志 和开启jmx一样,进入JMX目录后,执行 exec java.lang:type=Memory.setVerbose(true); 就开启了. 更多文档 官方文档

2015-07-04 · 1 min · bystander

休假停下来反思

项目经过一年终于告一段落.于是有了一个短暂的休假. 早上照例没能睡好觉.很早就醒了.然后又躺了一会,醒来看了会订阅.然后听了一集« Mr.Robot »,感觉还行,再对着字幕看了一遍,以后还是有一些地方理解的有问题.以后还是要多对着无字幕版的美剧去看,才能慢慢听懂更多的,比如今天听到个society,讲社交焦虑,听到很熟悉,就是没反应过来.学而不用则殆. 中午给文哥寄了个快递,顺便点个饭.之前的"手艺"应该也已经忘得差不多了.到杭州之后很少做饭,工作太忙.没办法.当然这只是借口.主要还是我懒吧. 下午按计划好的去浙江图书馆,从大学出来后,虽然书还是看了一些的.但是也再也没有走入图书馆.之前一直想去上海图书馆,结果一直耽搁,今天去浙江图书馆办了个证,借了几本书,看着里面的人自习的自习,借阅的借阅,想想还是有点熟悉的.遗憾的是书相同的份数有点少.想借的几本书都被人借走了,最终借了个**« 七周七语言 »,希望能给自己的编程带来不一样的思考角度.读完后争取写个书评和总结,还借了一本摄影相关的,毕竟拍照是服务妹子的技能.还有个« netty权威指南 »** ,虽然这本书评价好像不高,但是拿来看看还是可以的. 下午回家.杭州的下午还挺美的.天气凉爽.只是作为工作狗,没有下午出来的机会吧. 工作忙,不过在一切自动化的指导下,(马克思没有找我),对linux 的shell操作熟悉度急剧上升,希望能写的更好,让更多的过程自动化,也希望有时间停下来想一想.当时为什么选择写代码,为什么选择当前的职业,知道自己做了什么,知道自己是否进步,想起之前看到的一个话,不知真假, 只是因为三轮车好学,你就要一辈子骑三轮车吗? – Douglas Englebart 在职业之外,除了高效做好自己的工作外,也要学习更多的技能,英语,锻炼身体,其他编程相关的.不要安于现状.不要重复自己.还是那句话,不要让你的身份限制你的能力.

2015-07-02 · 1 min · bystander

SecureRandom第一次生成随机数非常慢

最近发现某个系统在第一次做操作的时候非常缓慢,逐步定位打印更加详细的日志后,发现问题是使用了SecureRandom 这个类来获取随机种子,这个类第一次初始化的时候setSeed的值,非常缓慢,偶尔出现, 排查的过程就是二分,不断定位具体的代码,最终定位 也就是说根本原因是SecureRandom 这个jre的工具类的问题.具体的bug搜索之后,见 http://bugs.java.com/view_bug.do?bug_id=6521844 详细的解释过程: 参考: http://www.websina.com/bugzero/faq/securerandom-slowness.html Q: Why the SecureRandom generateSeed is so slow or even hang on Linux OS? A: When you login, it hangs or takes more than a minute to get the response. If your server is on a Linux OS, the culprit here is SecureRandom generateSeed() which uses /dev/random to generate the seed. However, /dev/random is a blocking number generator and if it doesn’t have enough random data to provide, it will simply wait until it does, which forces the JVM to wait. Keyboard and mouse input as well as disk activity can generate the randomness or entropy needed. But on a server that lacks such activies, the problem may arise. 大意是说当使用SecureRandom 的时候默认使用的/dev/random 文件来生成种子,如果没有足够的种子数据,(这些数据是由键盘,鼠标,磁盘活动等产生的,如果没有这些活动,就没有足够的数据)会一直等待,导致jvm卡住,耗费比较长的时候.由于出现问题的这个环境的确是最近没什么操作,而且复现的操作也是隔个一个晚上,重新做业务才会出现. 文中给出了一种解决方案. 启动参数添加 -Djava.security.egd=file:/dev/./urandom,验证是可以的. 修改随机数获取方式 这里urandom是啥呢,引用自维基 /dev/random的一个副本是/dev/urandom(“unlocked”,非阻塞的随机数发生器[4]),它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。 类似案例: SecureRandom 导致tomcat启动过慢. https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source 从文中看到说java8已经提升了这个性能.但是一般生产环境的java版本是不会改的.

2015-06-30 · 1 min · bystander

关于重构和设计模式

之前在工作写了一个数据库查询的工具.大体背景就是这种工具需要跨不同环境的数据库,开发,测试,性能等.最早简单写了一个版本,在第一次查询时会初始化三个库的连接,保存在map中,然后后续查询直接根据使用者选择的环境类型取出对应的连接构造sql即可. 随着各个不同系统接入的越来越多,各个平台都保存了自己的连接,导致代码冗余度急剧上升,上周,利用晚上的一点时间读了一下«重构»,这本书,深受启发,一个是重构就是要采用小步快走的方式,在测试用例的覆盖下,快速改动,去掉代码中不合理的地方.另一个就是重构需要对业务的当下和未来的变化有一个比较深刻的理解,知道这个系统能做什么,不能做什么.才能更好地做重构. 于是,根据这个工具的特点,感觉抽象工厂模式比较合适,于是在抽象工厂模式的指导下,对关键部分进行了重构,在增加了几个类之后,代码复杂度开始下降.各个接入系统的代码基本上保持在了几十行内,之前都是几百行,大量冗余代码,只能说自己之前眼光太短浅了.并且,采用了类似单例模式的操作.当查询的时候,先根据当前环境作为key取连接,如果连接被关闭,或者不存在,则初始化,然后放到map中,返回.如果有的话,直接用.这样改动后,第一次查询的时候只需要初始化一个连接,速度极快.也算个好处.. 由此,反思了一下,设计模式之前也看过.但是总觉得各种书上讲的都比较浅显,给出的例子也似乎如作者所说,很符合那个模式,但实际上,在工作中如何识别当下的业务应该是比较难的,需要在业务变动中,不断地重构自己的代码,才能发现,某一种模式似乎特别适合解决这种问题,反之,重构也需要一定的设计模式作为基础,否则对代码的重构会只停留在抽取公共方法.重命名.大类变小类的阶段.. 希望接下来能够抽空把«敏捷软件开发:原则、模式与实践»这本书看完.同时能够真的理解这些模式的场合,想起一句话,知道一个技术方案的好,说明你还没有理解这种方法,只有你知道了这个方案的不足,你才真正理解了他,相信很多技术我都没有理解.设计模式也是,希望之后能够理解每种模式的不足,重构这本书也要经常翻翻,能加深对代码的理解.

2015-05-10 · 1 min · bystander

一键切换jdk版本

工作中有时候会切换jdk版本.有时候需要用个64位的.有时候需要用32位的.频繁手动很不方便,参考了一下,写了一个bat脚本,保存为bat,运行即可切换.同理可以改改,运来切换1.7,1.8这样的版本. @echo off :init set JAVA_HOME_32=D:\5.Program\Jdk32Home set JAVA_HOME_64=D:\Software\JdkHome :start echo. echo ============================================= echo jdk版本列表 echo 32 (%JAVA_HOME_32%) echo 64 (%JAVA_HOME_64%) echo ============================================= :select set /p opt=请选择jdk版本: if %opt%==32 ( start /I /WAIT /B wmic ENVIRONMENT where name='JAVA_HOME' set VariableValue="%JAVA_HOME_32%" >nul rem reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v JAVA_HOME /t reg_sz /d "%JAVA_HOME_32%" /f goto success ) if %opt%==64 ( start /I /WAIT /B wmic ENVIRONMENT where name='JAVA_HOME' set VariableValue="%JAVA_HOME_64%" >nul rem reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v JAVA_HOME /t reg_sz /d "%JAVA_HOME_64%" /f goto success ) echo 选择的版本错误,请重新选择! PAUSE goto start :success echo. echo 设置环境变了成功.

2014-11-07 · 1 min · bystander

蓝绿发布的整个部署过程

一直听说蓝绿发布,不知道是怎么个过程. thanks to blue-green-deployment 蓝绿发布的意义 整个发布过程,用户没有感受到任何宕机或者服务重启。 蓝绿发布的过程 第0步:部署以前的配置 第1步: 把绿色集群的状态改为’备用’. 从负载均衡的池里把这些地址去掉,这样,绿色的集群就不再回接收到来自用户的请求了.转而进入备用负载均衡的池里. 第2步:在绿色集群里部署新的代码,直到应用启动成功 第3步:使用备用负载均衡简单测试一下备用集群的部署情况.理想状态下是全自动的. 第4步:把绿色备用集群的状态改成存货,于是进入了存活负载均衡的池里 看到 蓝色运行v1版本,绿色运行v2版本,都连接的是相同的数据库.这意味着v2版本也要在老的数据模型上运行.如果数据库有变更,要等到所有的集群升级到新的代码上. 第5步: 对蓝色集群也进行同样的操作. 最终v2代码完成部署. 第6步:根据情况.运行数据库迁移  

2014-09-14 · 1 min · bystander

《Spring揭秘》读书笔记-第二章IoC的基本概念

理念就是让别人为你服务,中文名控制反转,也叫依赖注入DI public class FXNewsProvider { private IFXNewsListener newsListener; private IFXNewsPersister newPersistener; public void getAndPersistNews() { String[] newsIds = newsListener.getAvailableNewsIds(); if(ArrayUtils.isEmpty(newsIds)) { return; } for(String newsId : newsIds) { FXNewsBean newsBean = newsListener.getNewsByPK(newsId); newPersistener.persistNews(newsBean); newsListener.postProcessIfNecessary(newsId); } } } 假设这个类用来处理新闻, IFXNewsListener 用来获取新闻, IFXNewsPersister 用来把获取的新闻持久化 当我们需要获取不同的新闻源,比如道琼斯的新闻时,我们会写一个 DowJonesNewsListener 类和 DowJonesNewsPersister 类,然后实例化 public FXNewsProvider() { newsListener = new DowJonesNewsListener(); newPersistener = new DowJonesNewsPersister(); } 如果我们依赖于某个类或服务,最简单而有效的方式就是直接 在类的构造函数中新建相应的依赖类。 注意看, ,我们都是自己主动地去获 取依赖的对象! 可是回头想想,我们自己每次用到什么依赖对象都要主动地去获取,这是否真的必要?我们最终 所要做的,其实就是直接调用依赖对象所提供的某项服务而已 能不能我们用的时候自动送过来呢? 。现在是用什么,让别人直接送过来就成。所以,简单点儿说, IoC 的理念就是, 让别人为你服务!在图 2-1 中,也就是让 IoC Service Provider 来为你服务! ...

2014-07-01 · 2 min · bystander

[藏]图文并茂详解Eclipse断点

本文转自:http://my.oschina.net/colorleaf/blog/176569 这个算说的比较清楚的了,虽然简单但是很有用。收藏一下。 详解Eclipse断点 大家肯定都用过Eclipse的调试的功能,在调试的过程中自然也无法避免要使用断点(breakpoint),但不知是否对Eclipse中各类断点都有所了解。本篇图文并茂地介绍了Eclipse中全部类型的断点,及其设置,希望对大家有所帮助。(2011.11.20) 1. 示例程序 BreakpointDemo是一个臆造的应用程序,只是为了便于讲解Eclipse中各类断点的使用罢了。其代码如下图所示, BreakpointDemo主要包含两个方法: [1]setValue,该方法根据指定的次数(count),对成员变量value进行赋值,值的范围为0-9的随机整数。 [2]printValue,该方法会调用setValue()对value进行赋值,并打印出value的值;但,如果value能被3整除,那么就会抛出IllegalArgumentException异常。 2. Line Breakpoint Line Breakpoin是最简单的Eclipse断点,只要双击某行代码对应的左侧栏,就对该行设置上断点。此处,对第20行代码设置上Line Breakpoint,如下图所示, 可以为Line Breakpoint设置一个条件,那么当程序运行到该断点时,只有满足设定的条件,才会被中断。右键点击第20行的断点,选择"Breakpoint Properties…" 在弹出的属性对话框中,勾选上"Conditional",然后在文本框中输入"count % 2 == 0"。 该条件表示,当程序运行到第20行时,只有当count为偶数时,程序才会被中断。细心地话,你会发现该断点的图标发生了改变,多了一个问号。 3. Watchpoint Line Breakpoint关注于程序运行的"过程",大家也常把使用这种断点的调试称为单步调试。但有时候,我们对程序的运行过程不太了解,可能也不太关心,不能确定在什么地方设置断点比较合适,而可能比较关注某个关键变量的变化或使用。此时,就可以为该变量设置一种特殊的断点–Watchpoint。在此示例,我们最关心的就是成员变量value的值,那么就可以为它设置一个Watchpoint,双击第9行代码对应的左侧栏就可以了。 使用在2中所提及的方法,查看该断点的属性, 默认地,当该变量被访问或它的值被修改时,程序都会被中断。但在本示例中,只希望当对value的值进行修改时程序才需要被中断,所以取消对"Access"的勾选。 这时,我们会发现原来的Watchpoin图标也有变化了。 4. Method Breakpoint 与关注对某个变量的访问与修改一样,我们也可以关注程序对某个方法的调用情况,即,可以设置Method Breakpoint。在此处,设置针对方法setValue的Method Breakpoint。同理,双击第11行代码对应的左侧栏即可。 仍然要查看该断点的属性。默认地,只勾选了"Entry",而没有勾选"Exit"。 这表示,当刚进入该方法(调用开始)时,程序会被中断;而,离开该方法(调用结束)时,程序并不会被中断。在本示例中,需要同时勾选上"Exit"。 点击OK之后,可以看到该断点的图标也有所改变。 根据这里的设置,当程序运行到第20行后会在第12行被中断,尽管这里没有显式的断点,但这就是setValue()方法的入口(Entry)。必须注意地是,程序在运行到第16行时不会被中断,尽管它看起来像是setValue()方法的出口(Exit)。实际上,程序会在第17行被中断,这里才是setValue()调用结束的地方。 5. Exception Breakpoint 如果,我们期望某个特定异常发生时程序能够被中断,以方便查看当时程序所处的状态。通过设置Exception Breakpoint就能达到这一目标。本示例故意在第23行抛出了IllegalArgumentException异常,我们期望程序运行到此处时会被中断。但我们不直接为此行代码设置Line Breakpoint,而是为IllegalArgumentException设置Exception Breakpoint。设置Exception Breakpoint的方法与其它类型断点都不同,它不能通过双击左侧栏的方式在代码编辑器上直接进行设置。点击Breakpoints视图右上角形如Ji的图标, 会弹出如下所示的对话框, 在其中选中IllegalArgumentException,并点击OK,这时一个Exception Breakpoint就设置好了。 当value为3的倍数时,程序会在第23行被中断,这时我们就能使用调试器来看看value具体是等于0,3或6。 **6\. Class Load Breakpoint** 还有一种大家平时可能不太用的断点--Class Load Breakpoint,即当某个类被加载时,通过该断点可以中断程序。 [![15153248_2UA6](/images/8158c897f4e784042063a484c7256901902b6c20.png)](http://leaverimage.b0.upaiyun.com/2013/11/15153248_2UA6.png) 小结 上述的Eclipse断点,我们在现实工作中肯定都有意或无意地使用过其中的几种,只是不一定十分了解内情罢了。使用好Eclipse的各种断点,可以把很好地帮助我们分析程序,定位问题。

2013-11-16 · 1 min · bystander

Spring松耦合示例

面向对象设计的理念是把整个系统分成一组可重用的组件,然而,当系统变得越大的时候,尤其是在java中,这最大的对象依赖将会紧紧耦合,以至于非常难以管理和修改,而现在,你可以使用Spring框架扮演一个中间模块的角色,方便高效地管理其他组件依赖 输出生成的例子 看个例子,假设你的项目有一个方法可以输出内容到csv或者json格式,你可能写出这样的代码 package com.mkyong.output; public interface IOutputGenerator { public void generateOutput(); } ,然后是实现接口的类 package com.mkyong.output.impl; import com.mkyong.output.IOutputGenerator; public class CsvOutputGenerator implements IOutputGenerator { public void generateOutput(){ System.out.println("Csv Output Generator"); } } 再写个Json生成的类 package com.mkyong.output.impl; import com.mkyong.output.IOutputGenerator; public class JsonOutputGenerator implements IOutputGenerator { public void generateOutput(){ System.out.println("Json Output Generator"); } } 有好几种方法来调用IOutputGenerator接口,以及我们如何使用Spring来避免对象的过度耦合。 方法1-直接调用 package com.mkyong.common; import com.mkyong.output.IOutputGenerator; import com.mkyong.output.impl.CsvOutputGenerator; public class App { public static void main( String[] args ) { IOutputGenerator output = new CsvOutputGenerator(); output.generateOutput(); } } 问题: 这种方法,output这个对象和CsvOutputGenerator耦合在了一起,每次要改变输出格式的话都要修改代码,如果这类代码遍布项目,那么改起来就跪了 方法2-通过帮助类调用 也许你会想创建一个Helper类吧所有的output实现都移进去 package com.mkyong.output; import com.mkyong.output.IOutputGenerator; import com.mkyong.output.impl.CsvOutputGenerator; public class OutputHelper { IOutputGenerator outputGenerator; public OutputHelper(){ outputGenerator = new CsvOutputGenerator(); } public void generateOutput(){ outputGenerator.generateOutput(); } } 然后可以这样调用 package com.mkyong.common; import com.mkyong.output.OutputHelper; public class App { public static void main( String[] args ) { OutputHelper output = new OutputHelper(); output.generateOutput(); } } 问题: 看起来似乎更加优雅了,你仅仅需要管理这个Helper类就可以实现不同格式的输出需求改变了,然而,Helper还是和CvsOutputGenerator耦合,每一次要改变输出格式的时候,都要对Helper类做一下微调。 方法3-Spring Spring依赖注入很合适,可以使不同的格式生成类分离开来 ...

2013-09-20 · 2 min · bystander