Nitro's

Aug 17, 2019 - Comments - dev tech golang

Goim单机配置启动简单记录

Goim v2.0.0为例 运行环境:MacOS 10.14 依赖组件、框架 Java Kafka依赖 Kafka 消息队列 Zookeeper Kafka依赖 Redis 在线状态、服务状态缓存 Discovery 服务注册、发现框架 配置 Redis配置 host=localhost port=6379 ZooKeeper配置 host=localhost port=2081 Kafka配置 host=localhost port=9092 job job -conf=goim/cmd/job/job-example.toml -region=sh -zone=sh001 -deploy.env=dev comet comet -conf=goim/cmd/comet/comet-example.toml -region=sh -zone=sh001 -deploy.env=dev -weight=10 -addrs=127.0.0.1 logic logic -conf=goim/cmd/logic/logic-example.toml -region=sh -zone=sh001 -deploy.env=dev -weight=10 启动 Zookeeper 支持Kafka的运行 Kafka 消息队列启动,业务Push消息到这里 Redis 用户在线状态、服务状态的缓存服务启动 Discovery 启动服务注册、发现框架 logic启动,接收业务Push消息,推送到消息队列 comet启动,接受用户注册、连接注册、消息下发 job启动,读取消息队列,发送到comet 测试 通过源代码中的example,测试连通性是否正确,通过RPC的Push接口发送消息测试。

May 19, 2019 - Comments - tech

Retrofit、Volley、HttpClient比较

Retrofit作为现在大家用的最多HTTP请求框架,非常流行,Github上star 3w+。它为什么能超越Volley、HTTPClient能够一枝独秀呢?那先看看其他两个HTTP栈的实现。 HTTPClient Java界老牌HTTP栈实现,由Apache维护,它支持HTTP1.0/1.1、极其丰富的API来支持各种子协议,代码庞大臃肿也变成了它的缺点,虽然它的创建一开始是为了弥补Java SDK中java.net包HTTP请求的简单实现,Android在6.0以后彻底弃用了它,转而推荐使用HTTPURLConnection。 Volley 作为Google官方开源的一款HTTP栈,它支持切换HTTPURLConnection、HTTPClient底层协议栈的切换,同时提供了请求线程池、缓存的支持,刚一推出也是收获许多赞赏,但是它就像G家好多产品一样,几年一次的维护和有些bug都需要使用方去维护解决,都是开发者逐渐抛弃的原因。虽然从Volley开始,这些HTTP栈的实现都在逐渐向上层实现,因为不管是Android、iOS大部分App的网络交互都是Restful-API的实现,所以能在提供基础HTTP服务的基础上,提供请求内容的封装、响应内容的解析就越来越迫切,Volley在这方便做出了第一步,响应内容的解析以及支持自定义解析这些功能。但是Volley的致命问题在于它的响应内容处理上,必须将全部数据读取出来交给上层数据,这对内存的要求可能很高,缺乏一定的灵活性,所以只适合小数据量的HTTP请求。 Retrofit 来自Android界开源大厂Square.Inc ,底层HTTP栈来自于OKHTTP框架,它支持HTTP 1.1/2,支持TLS,HTTP2作为socket连接复用的最新技术,OKHTTP的支持可以说是一大重点,因为作为移动端App,相比浏览器中的Web开发,App端点的可控性可以让我们快速支持这种技术来提高加载速度,同时OKHTTP提供了请求拦截器方便我们在请求发起前的对参数进行操纵。 Retrofit建立在OKHTTP的基石之上,抽象出了Converter、CallAdapter这两个重要的概念。 Coverter作为HTTP请求、响应内容的类型服务类为上层不同的技术实现提供支持,现在支持GSON、Guava、JSON、XML、Protobuf,同样你可以根据自己的需求进行定制。 CallAdapter则为不同的上层框架提供了容器支持,让你能够在Retrofit的基础上同步、异步的分发请求与响应,现在支持Java8、RxJava、RxJava2的标准实现。 除此之外,动态代理、注解编程的使用,让开发者从复杂的请求参数、URL拼接中解放出来,更多的去关心业务逻辑的实现。 这一系列的优势让Retrofit逐渐得到开发者的青睐。 番外: 在Java11 OpenJDK的文档中看到另外一个HTTPClient的实现,支持HTTP2、支持上层RxJava编程,但这对于Android平台来说JDK 11还是有点远。 参考资料: OKHTTP JDK Httpclient

May 18, 2019 - Comments - tech

Java动态代理类的生成和调用

Java的动态代理在开发中都有大量的使用,如Spring框架,Android的HTTP开发框架Retrofit,本文主要关注动态代理编写使用背后的代理类是如何的生成以及与代理对象的调用是如何实现的,以Retrofit这个框架中动态代理的使用为例子进行分析。 在Retrofit中,某类的API接口大多定义在一个Service接口类中,某一个API接口则被声明为Service接口类的一个方法,通过方法的注解、参数来描述具体API参数等信息。在调用某个API接口时,Retrofit实例调用create()创建Service接口类的实例对象来完成调用,具体源代码如下: public <T> T create(final Class<T> service) { // 必须是接口,并且不允许是继承来的接口 Utils.validateServiceInterface(service); //是否预加载 if (validateEagerly) { eagerlyValidateMethods(service); } //动态代理的核心代码 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.

May 6, 2019 - Comments - dev tech

SVG Path命令属性

Android从5.0开始支持SVG矢量图,通过Vector Asset工具将SVG文件转换VectorDrawable定义的XML文件中,在运行时inflate这个xml文件来绘制图层,这对于减小APK资源文件体积和避免混乱的分辨率支持上都有很好的效果,同时Android通过Support支持库的形式给予了低版本的支持。 Android上对SVG的支持是受限制的,仅支持SVG tiny1.2版本的属性和标签,而且不支持text标签。 path标签是SVG中最常用的标签,这其中最重要的属性就是d(command)属性,它标明这个路径的绘制起点、终点、中间路径关键点、两点之间是否为直线、弧线、贝塞尔曲线等等。 d(command)属性主要分几类: 起点 用M、m来表示,如M150,0 表示从path的起点, 从x-150,y=0的坐标起点开始绘制 终点 用Z、z来表示,无参数 表示path的终点,链接到path的起点,闭合path,然后结束绘制 直线 假设当前点坐标为(10,10) L、l表示直线线段,如L100,100,表示从(10,10)开始,绘制一条到(100,100)的直线线段 H、h表示水平线段,如H100,表示从(10,10)开始,绘制一条到(100,10)的水平线段,等同于L100,10 V、v表示垂直线段,如V150,表示从(10,10)开始,绘制一条到(10,150)的垂直线段,等同于L10,150 三次贝塞尔曲线 假设当前点坐标为(100,200) C、c表示三次贝塞尔曲线,如C100,100 250,100 250,200,表示起点坐标为(100,200),控制点1坐标为(100,100),控制点2坐标为(250,100),终点坐标为(250,200),绘制这一条三次贝塞尔曲线线段。 S、s也表示贝塞尔曲线,只是它比较特殊,它的控制点1来自于上一条C、c、S、s曲线的控制点2坐标与上一条C、c、S、s曲线终点坐标连线上的对称点, 就如上面的例子,S曲线的控制点1坐标就为(250,300),这样的曲线在连贯性上是平滑曲线,所以也称为是平滑三次贝塞尔曲线; 如果上一条线段不是C、c、S、s三次贝塞尔曲线,那么默认它的控制点1坐标与起点坐标一致; 如S400,300 400,200,假设沿着上一条S贝塞尔曲线继续绘制,则起点坐标为(250,200),控制点1坐标为(250,300),控制点2坐标为(400,300),终点坐标为(400,200)。 二次贝塞尔曲线 假设当前点坐标为(200,300) Q、q表示二次贝塞尔曲线,如Q400,50 600,300,表示起点坐标为(200,300),控制点坐标为(400,50),终点坐标为(600,300),然后绘制一条二次贝塞尔曲线线段。 T、t也表示二次贝塞尔曲线,如同S、s平滑三次贝塞尔曲线一样,它“借用”了上一次二次贝塞尔曲线的控制点,取上次曲线控制点与上次曲线的终点坐标连线上对称点为新的控制点; 如果上一条线段不是Q、q、T、t二次贝塞尔曲线线段,那么默认它的控制点坐标与起点坐标一致。 如T1000,300,假设沿着上一条Q二次贝塞尔曲线继续绘制,则起点坐标为(600,300),控制点为(800,550),终点坐标为(1000,300)。 椭圆曲线 假设当前点坐标为(50,-25) A、a表示椭圆曲线,如a25,25 -30 0,1 50,-25 l 50,-25,表示椭圆半径rx=25,ry=25,x轴方向上的旋转角度-30。 参考资料: SVGwg.org Path Mozilla SVG

Mar 24, 2019 - Comments - tech

Blink内核相关术语、映射关系

在读Adblock Plus for Chrome插件的源代码时,拦截入口处有几个判断非常重要,这涉及到当前打开Tab的URL、来源、打开方式等概念,对应到Blink中术语有page、main frame、iframe、document等,翻阅一下Blink的README文档,找到官方的介绍在此做一下记录。 Page 一个Page对应于一个Tab,当然前提时OOPIF(Out-of-Process iframes)没有开启。每一个渲染进程可能包含多个Tab。 Frame Frame对应于HTML中的frame,可能是主frame或者iframe,每个Page在树形结构中可能包含一个或者多个frame。 DOMWindow 一个DOMWindow对应Javascript中的一个window对象,每个Frame有一个DOMWindow。 Document 一个Document对应Javascript中的一个window.document,每个Frame有一个Document。 ExecutionContext 一个ExecutionContext是一个抽象概念,在渲染进程的主线程中对应于一个Document,在工作者线程中对应于一个WorkerGlobalScope。 解释完这些,那就知道相互之间的对应关系了。 渲染进程:Page=1:N Page:Frame=1:M Frame:DOMWindow:Document(ExecutionContext)=1:1:1 这在某个时刻是成立的,因为某个时间段内涉及到iframe的locatio跳转新建frame以及frame的重用问题。

Jan 1, 2019 - Comments - life

门前一棵花树

元旦假期即将收尾,年末总结也写完了,源代码看了一个流程细节还未整理,然后就是照例进行的online大扫除:整理照片、清理存储空间、维护一下服务器、看看欠费是不是该交了[尴尬状]。 传送门 每次整理照片都能发现好多的意外,就比如把OneDrive的照片从Google Photo迁移的过程中发现一张中文命名的照片,好奇怪,怎么可能会有这样的原始照片,而且还是“我和张XX”的名字,这一定是假的“我”,放大看来果然是乱入,两个大学同学的合照被这样命名真是怀疑人生的节奏…然后把结婚的时候用iMovies制作的一段我俩的视频照例上传,先去搜索了一下Google Drive上是否存在,只记得是“Love”开头,输入关键词“Love”结果Google的情感联想搜索就开始了,文件名字在此刻不是关键了,除了含有“Love”文件名的照片以外,它把所有合照一并检索出来了,囧字D,竟然还有宠物狗的合照,嗯,感情不分你我,合到一块拍照就是爱,哈哈哈。 花树 在OneDrive上整理之前合辑的照片,又翻到了G318之旅几个GB的照片,翻看到那一片片的油菜花,联想到草稿箱里面还没动笔的6.27、6.28几天的旅行日记,是把它封存上还是续写上呢?这就又是一件纠结的事情了。过去的值得纪念,回忆不过也是一种缅怀罢了。 此刻的自己是如此的狼狈,又是如此的无奈,既要承认奶奶过世的事实无从相见最后一面,又要努力的前行因为这是只有前进没有后退的路。 大片的油菜花为谁而开,它只是招蜂引蝶授粉的方式而已。 美与浪漫在此刻不求,只愿珍惜当下~ 码字 存储搬迁的过程中还发现了刚刚开始学习Android时的一堆Demo,这应该就是自己一点点学习的印记吧,现在再看代码肯定是幼稚的写法,怎么可能会写出这样的代码,哈哈哈,一并清空;顺便还发现了一堆各式各样的获取微博列表、豆瓣私信的API实现,嗯,再想想这里面的一堆故事,哈哈一笑而过。 清理的不是过去,是记忆;老家门前的那棵树,其实早没了…

Dec 30, 2018 - Comments - hot life

敦刻尔克-2018

2018年即将结束,就好像2008年才刚刚走,一晃的十年,一飘而过的年轮总是写在脸上,那个稚嫩未脱的娃儿现在已然成长为一个肚皮微凸、熬夜犯困、卡丁车要看油价的青年汉子。 前天上班的时候还在和同事讨论说,现在的工作周报写起来有人喜有人烦,喜在每周回过头去看看自己有什么收获、做了什么工作、有什么需要亟待加强学习的地方,烦在每周临下班了如果没有提前做个准备总要去高速运行一下大脑或者翻看一下Git log才能记起来到底做了什么。嗯,我还是比较喜欢前者,而且更激进一些,每天都要做一下记录,而且时间划分为上下午,虽不至于每一刻钟都要精确,但大概的事情有几件还是要理清楚的,最后的结果如何,为什么要这么做都要记录。大体翻看了一下,再去找了一下自己的绩效表,大概一致,没有太多的出入,默默地给自己的一年工作打个分数,领导对自己有他的评价,自己对自己的工作也有一份心底评价,几差几落心底亮堂着。 凡事有记录有规划,失败了也是一种经验的总结,告诉自己舵轮应该转几度,不至于回头告诉自己我们就是失败了,No Reason就很扯了。 今年全年贡献给12306的流量和消费金额应该是勇创新高了,往返帝都和泰安的次数超出往年几倍。从年初的房子装修到后期的家具采购再到年底的结婚进行时,终于算是圆满完成了人生的一件大事。 2018年于我、Saphy同学都是在忙碌与抉择中极速前行: 清明节前房子大装、卫浴、厨具收尾 清明节宜家家具济南大采购 五一家具组装入户 六月小家具家电入户 八月青年做局父母为证全家欢 九月结婚照定格 十月Saphy同学把家还 十一月婚前协奏曲 十二月彼此携手,天合事成,情定终身 忙碌的一年就这样极速收尾,极速掠过,那天Saphy同学还在小抱怨:今年忙得都没有出去玩,京郊游在这时间夹缝里面感觉都是奢侈的。不过也还好,忙里偷闲地在京郊小溜达了几回,也算是给忙碌的工作与生活之间平添一份不带甜的葱油饼,食之略油腻,但能填饱肚子,哈哈哈。 就像张宇唱的那样: 从今以后他就是你一生的伴; 他的一切都将和你紧密相关; 她是别人用心托付在你手上; 你要用你一生加倍照顾对待; 一定是特别的缘份; 才可以一路走来变成了一家人。 Saphy同学于我,彼此相依,相伴到老。 静悄悄的2018年即将结束,我们期盼更多的搜索词是Good,更好的世界是Peace And Love; 感谢这一年的充实,感谢这一年的注脚,这注定是人生中最不平凡的一年; 感谢这一年给予了无私帮忙的亲戚朋友; 感恩大家彼此的遇见,彼此的欢乐、悲伤、幸福、坎坷,我们一并全收,带着勇气、安康迎接2019年的到来~ 敦刻尔克,没有撤退的前进~ 出壳,2019~

Dec 14, 2018 - Comments - life

重读大学

夏天的热惹不起冬天的冷,一双凉拖却可以穿越夏秋一脚跨入严冬,这就是老舍先生不想说实话的济南。济水之南,望山望水望雨荷的济,千佛百泉看泰山的南。一条经十路就像长安街,你堵着我,我堵着你,争相回望妈妈喊着回家吃饭的路途,如若不是高架一跃而起你可能真的是站在帝都国贸桥上思考你的人生路为什么走的这么慢,这么缓,慢慢,缓缓,慢慢… 就像陈小熊唱的那个济南,丢了历史的厚重,但又没有展现立体的现代感,相比成都、杭州、西安,济南就像一条打着补丁的裤子,想改成裙子却又没有好裁缝。拆拆建建之间一座座历史的厚重慢慢都被埋在了穿梭之间,变成一张张黑白照片放在博物馆里供后来人一览而过,一声叹,如同当年的北平一样被拆的面目全非到最后还是落下一个迁址的结果,现在呢,唯一能追忆的可能也就是那处洪家楼基督教堂。虽远望其壮观但从未踏足,每次心底默念下次路过一定要进去感受一下,或许心不诚则不灵,极近十年也从未成行,便留遗憾。遗憾之外,却是旁边那所静之所动的山东大学。 济南没有山大,济南可能不完整,山大没有济南山大还可以是山大,山大不仅是济南的,还是威海的、还是青岛的。千年之后的山大在遍地开花的大拆大建就没有停止,合并山东工业大学、山东医科大学,变成了巨无霸的新山大。 ——未完也不准备续了,拖了半年的稿子。只是记得想好的结尾: 邻居大爷:“娃,高考成绩咋样啊,考到哪里去了啊!?” 我:“济南,济南大学”,尴尬状… 邻居大爷:“哦,济南的大学啊,嗯,山东大学是个好大学!” 我:…… 济南的大学,山东的大学,济南大学,山东大学…热度要蹭就要紧贴着… 山东医科大学,山东中医药大学,山东医学院,泰山医学院,齐鲁医科大学,山东第一医科大学… 来自假山大毕业生的未完稿。

Sep 28, 2018 - Comments - dev tech

Chromium Android工程迁移编译过程

本文从Chromium编译的中间产物入手深入分析、学习Chromium Android版本的工程化定制流程。初始工作依赖于Chromium的ninja、GYP构建系统,在构建完成后基于编译中间产物,迁入Android Studio作为新的构建工程,测试编译发布的过程。 注:这种编译过程除了资源文件外其他编译中间产物,都不可修改,不具备大规模定制化的可能性,仅作为熟悉编译过程和代码结构的学习、测试使用。 前提 Chromium代码结构、Android开发、Android Studio使用 编译Chromium 编译步骤可以参考Chromium团队的文章,可以选择编译目标为chrome_public_apk、content_shell_apk,本文以chrome_public_apk为例。 编译结果APK 在以chrome_public_apk为编译目标后,在经历一段时间后编译完成,在out/***文件夹内就包含了所有的编译结果和编译中间产物,其中apk在apks文件夹内,可以拉取安装一下,除了包名外其他功能与Chrome基本一致,本文的迁移目标就是在Android Studio工程下同样可以编译出这个APK,再探讨后续的源码迁移和定制工作。 工作目录 在out/***文件夹下,我们主要涉及到的文件分为三类:so、jar、resource,各自又来自不同的Chromium模块。 apks—编译目标文件目录 gen—编译过程中间产物,基本不涉及 lib.java—jar文件的主要来源,将不同模块的java文件编译后汇集在这个目录 locale—国际化的资源文件 resource-zips—资源文件的主要来源,也是Android Studio module化的主要依据 lib.unstripped—so文件目录 建立Android Studio工程 由于Chromium原有模块是基于命名空间来管理的,而且Android的R资源文件定义方式与此关联,所以需要通过Android Application、Library module的方式进行区分,同时还需要将Android Support这一类第三方库通过Gradle依赖的方式进行关联,而不是JAR+资源文件的方式。 所以基于Chromium的模块划分方式分为如下几个子module: app—org.chromium.chrome,主App Application ui—org.chromium.ui,Android Library base—org.chromium.base,Android Library components—com.chromium.components,Android Library content—org.chromium.content,Android Library media—org.chromium.media,Android Library autofill—org.chromium.components.autofill,Android Library _web_contents_delegateandroid—org.chromium.components.web_contents_delegate_android,Android Library _thirdparty—com.chromium.third_party,Android Library tools—org.chromium.tools,Android Library url—org.chromium.url,Android Library builder—org.chromium.build,Android Library net—org.chromium.net,Android Library mojo—org.chromium.mojo,Android Library device—org.chromium.device,Android Library gpu—org.chromium.gpu,Android Library printing—org.chromium.printing,Android Library services—org.chromium.services,Android Library skia—org.chromium.skia,Android Library 迁移编译后so _lib.