Earyant的技术博客

欢迎来到Earyant的技术博客,在这里我将与你分享新技术。

  • wechatParent:
    • wechat-base-parent
    • wechat-business-parent
    • wechat-core-parent
    • wechat-web-parent

wechatParent

  • 职责: 一键构建所有需要发布的项目。
  • 特性
    • 所有项目初始时就带有这些 jar 包的依赖,例如:testng(单元测试相关),h2(单元测试相关),easymock(单元测试相关),lombok(根据注释自动生成 setter 和 getter)
    • 所有项目的额外特性,例如:单元测试插件
    • 项目发布管理,例如:私一的 maven 私服配置

wechat-core-parent

  • 职责:
    • 该部分与业务没有关联,只提供基础能力。例如:数据库持久能力,缓存能力,http封装能力,通用工具能力。
  • 通用特性:
    • javadoc插件,用于生成javadoc

wechat-base-parent

  • 只代表一个真实存在而且能独立存在的业务实体,简称base项目。

we-business-parent

  • 职责:
    • 它所聚合的的项目必须是一个提供 “共享” 业务流程,简称:business 项目。在这个流程过程中有可能需要引用 base 服务。它本身没有一个真实存在而且能独立存在的核心实体

wechat-web-parent

  • 职责:
    • 它所聚合的的项目可以通过互联网向用户提供服务,在产品规划上它自己独有的不被共享的业务,简称:web 项目。

总体架构图如下

image

Redis

  • 提到阿里云的这个 Redis,不得不吐槽一句,它竟然是不支持主从的,只能单实例,不过,用它做数据缓存,还真是蛮不错的选择,响应速度非常快。而且,因为是放置在内网的且只能内网访问,所以安全性也很高。

    MongoDB

  • 结构型数据,主要存储档案式的数据,比如每个用户的操作行为,以档案式记录并进行统计分析,方便下一阶段的项目做个性化服务。另外一些关联复杂的数据,也可以用 MongoDb 存储,可以提高访问速度。还有,一些对软件应用版本比较敏感的数据也可以存在 MongoDB 中,比如 a 版本拿到 A 数据,b 版本拿到 B 数据,而这个 AB 数据都是由很多关联关系复杂的数据所组成,如果把这些数据根据版本号存储在不同的 MongoDB 档案中,需要时,直接根据版本号拿就可以了,这样就避免了很多的 mysql 查询。

静态资源

  • OSS + CDN
    OSS 存储静态资源,CDN(内容分发网络) 可以加速静态资源的下载速度。至于资源链接地址,客户端可以通过接口访问从后端业务数据库中拿到。

  • p : 小写上下午 (‘am’ or ‘pm’) meridian in lower case (‘am’ or ‘pm’) - according to locale file
    • P : 大写上下午 (‘AM’ or ‘PM’) meridian in upper case (‘AM’ or ‘PM’) - according to locale file
    • s : 一位的秒 seconds without leading zeros
    • ss : 两位的秒 seconds, 2 digits with leading zeros
    • i : 一位的分钟 minutes without leading zeros
    • ii : 两位的分钟 minutes, 2 digits with leading zeros
    • h : 一位的24进制小时 hour without leading zeros - 24-hour format
    • hh : 两位的24进制小时 hour, 2 digits with leading zeros - 24-hour format
    • H : 一位的12进制小时 hour without leading zeros - 12-hour format
    • HH : 两位的24进制小时 hour, 2 digits with leading zeros - 12-hour format
    • d : 一位的天 day of the month without leading zeros
    • dd : 两位的天 day of the month, 2 digits with leading zeros
    • m : 一位的分钟 numeric representation of month without leading zeros
    • mm : 两位的分钟 numeric representation of the month, 2 digits with leading zeros
    • M : 缩写月份单词,三位数 short textual representation of a month, three letters
    • MM : 全拼月份单词 full textual representation of a month, such as January or March
    • yy : 两位的年 two digit representation of a year
    • yyyy : 四位的年 full numeric representation of a year, 4 digits

详情请看官网解释

http://www.bootcss.com/p/bootstrap-datetimepicker/

  • y 一位数的年份(2001 显示为 “1”)。
  • yy 年份的最后两位数(2001 显示为 “01”)。
  • yyyy 完整的年份(2001 显示为 “2001”)。

  • M 一位数或两位数月份值。
  • MM 两位数月份值。一位数数值前面加一个零。
  • MMM 三个字符的月份缩写。
  • MMMM 完整的月份名。

  • d 一位数或两位数的天数。
  • dd 两位数的天数。一位数天数的前面加一个零。
  • ddd 三个字符的星期几缩写。
  • dddd 完整的星期几名称。

小时

  • h12 小时格式的一位数或两位数小时数。
    hh12 小时格式的两位数小时数。一位数数值前面加一个零。
  • H24 小时格式的一位数或两位数小时数。
  • HH24 小时格式的两位数小时数。一位数数值前面加一个零。

分钟

  • m 一位数或两位数分钟值。
  • mm 两位数分钟值。一位数数值前面加一个零。

  • s 一位数或两位数秒数。
  • ss 两位数秒数。一位数数值前面加一个零。

上下午

  • t 一个字母的 AM/PM 缩写(”AM” 显示为 “A”)。
  • tt 两个字母的 AM/PM 缩写(”AM” 显示为 “AM”)。

1命令行创建一个md文件。

  • hexo new “title”
  • 在 hexo 主目录下 source -> _posts 新建以 .md 为后缀的文件。

    这两种方式都可以创建一个,不过命令行形式会在md中创建描述文件:

    ---
    title: 完整写一篇博客
    date: 2017-07-18 14:03:42
    tags:
    ---
    

创建Front-matter

 参数    描述    默认值
 layout    布局    post
 title    标题    文件名
 date    建立日期    文件建立日期
 updated    更新日期    文件更新日期
 tags    标签(不适用于分页)
 categories    分类(不适用于分页)
 permalink    覆盖文章网址
 thumbnail    缩略图地址
 toc    显示 TOC 按钮    true
 comment    显示评论    true
 notag    不生成标签按钮    false
 top    置顶    false
 mathJax    启用 Mathjax    false

友情url链接

 pages:
      About:
          link: "#about"
          icon: person
          divider: false

参考

全篇可以在这搜到:

戳这里

本地搜索插件

npm install hexo-generator-search —save
在主配置文件中添加:
search:
path: search.xml
field: all

rss订阅插件

npm install hexo-generator-feed —save

feed:
type: atom
path: atom.xml
limit: 20
hub:
content:

刚升级node后发现报如下的错:

  • (node:34880) [DEP0061] DeprecationWarning: fs.SyncWriteStream is deprecated.

    node.js从8.0开始已经弃用了fs.SyncWriteStream方法,hexo中有一个hexo-fs插件,调用了这个方法,所以就会报错。

解决办法:

  • npm install hexo-fs —save

插件就更新了,问题就解决了。

RPC通俗解释

IPC和RPC

早些时间,一个电脑中多个线程互相独立,A线程和B线程都想用发送邮件功能,就需要开发两份代码,所以就有了一个协议是:IPC(Inter-process-communication)进行进程间通信,这样就可以在A中开发一个发送邮件的代码,B进程调用A进程代码就行了。
同比,现在的程序员们,为了方便调用其他电脑中的代码,研究出来RPC(Remote Procedure Call Protocol);

JVM介绍

JVM包括:

* 1、 字节码指令集
* 2、 一组寄存器
* 3、 一个栈
* 4、 一个垃圾回收堆
* 5、 存储方法区

JVM 的生命周期

1) JVM 实例对应了一个独立运行的 java 程序它是进程级别
1) 启动。启动一个 Java 程序时,一个 JVM 实例就产生了,任何一个拥有 public static void main(String[] args) 函数的 class 都可以作为 JVM 实例运行的起点
2) 运行。main() 作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM 内部有两种线程:守护线程和非守护线程,main() 属于非守护线程,守护线程通常由 JVM 自己使用, java 程序也可以表明自己创建的线程是守护线程
3) 消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用 Runtime 类或者 System.exit() 来退出

2) JVM 执行引擎实例则对应了属于用户运行程序的线程它是线程级别的

JVM模型

image

内存空间:

1) 方法区: 指令计数器以及其他隐含寄存器
2) Java堆: 
3) Java栈:
4) 本地方法栈:

共享不共享:

共享:
    1) 方法区
    2) 栈(Heap)
不共享:
    1)程序计数器
    2)VM stack 虚拟机栈
    3)本地方法栈


1) 程序计数器: 
2) 栈: 线程私有的,每个线程创建的同时都会创建 JVM 栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及 Stack Frame,非基本类型的对象在 JVM 栈上仅存放一个指向堆上的地址。
3) 堆:1)存储 *对象实例以及数组值*
       2)**!Sun Hospot JVM为了提高对象内存分配的效率,对于所创建的线程都会分配一个独立的空间TLAB(Thread Local Allocation Buffer) ,其大小由JVM根据运行的情况计算而得,在TLAB中分配的对象不需要加锁,因此JVM在给线程的对象分配内存时会尽量在TLAB中分配,性能和C性能差不多高效,如果对象过大,仍然直接在堆中分配。 **
       3)TLAB仅作用于新生代的Eden Space,因此多个小对象比一个大对象高效。
       4)新创建的对象总是被放在新生代中,如果在一次或者多次GC后活下来,就会被转移到老年代。
4)方法区:1)在Sun JDK中对应着为永久带、持久带 !!!
           2)方法区存放了所加载类的信息(名称,修饰符等),类中的静态变量,类中定义为final类型的常量,类中的Field信息,类中的方法信息,当开发人员用Class对象的getname,isInterface等获取信息时,数据都来源于方法区,方法区也是**共享的**,在一定条件下,也会被GC,当方法区使用的内存超过其允许的大小,也会抛OutMemory异常。

原因:

JVM每遇到一个线程,都会为其分配一个程序计数器,VM stack 和本地方法栈,当线程终止时三者所使用的空间也被回收掉。

如何保证推送消息能够准确推送到客户端。

手机端:

  • 轮询方式获取消息。
  • 短信拦截模式。 发送短信通知消息,应用中的短信拦截模块拦截短信,并解析成数据。成本高。
  • 持久连接。

    监听电量变化,网络变化,开关屏幕等等时候注册BroadCastReceiver来接收通知,接手后进行消息获取。
    有些ROM一旦用户kill掉主线程,就不会再投送广播消息给应用,导致应用无法启动,这是可以Fork一个进程,一旦发现主线程被杀,立即调用shell启动该Service(应用保活)

微服务间如何选择推送和拉取数据

在消息系统中,一般有两种消费模式:生产端推送消息,消费主动拉取消息。

数据是动态的,且实时性较强,宜采用生产端推送。

例如家长手机控制孩子手机使用,希望设置立即生效,家长端设置后由立即由中间系统进行通知。如果让消费端轮询查消息,不仅不能保证消息的实时性和准确性,而且系统也会造成一定的损耗,供应链系统也会被迫处理重复订单问题。
如果把消息设置成实时推送也是不合适的,推送成不成功不应该作为设置成功的条件。设置功能和推送功能不应该是强关联的,就像发送验证码,服务器收到了发送验证码的功能请求后,异步交给验证码发送功能,返回给客户200成功,随后验证码发送功能进行异步通知,确保通知成功即可。

客户端长时间离线状态

客户端长时间离线状态(断网,没电等等),没办法推送过去,会暂存在一个暂存表中,等待客户端联网等监听广播事件进行主动获取,消息获取成功,就会把离线消息表里的消息转移到已发送的消息表中。(不在本表中将已发送的消息的字段置为已读,会影响查询速度。)

推送的优点

  • 时效性高。
  • 服务器压力小。 相对比轮询拉取模式,每次推送都会有数据,有效避免了空轮询
  • 交互简单。 只需要提供推送接口就好了,不需要额外开销。

推送的缺点

  • 不能保证一定能推送成功。
  • 缺乏数据多样性,推送的消息一般都有固定的模板

    极光推送

  • 活跃用户的到达率在90%以上。轮询获取99%以上。
  • 并发情况下第三方服务的实时性不太理想。

自主研发的推送系统

  • 对客户端的海量长连接的维护管理消耗太大。
  • App端Service稳定性,保活。
  • 有些厂商不允许有push service存在。

自主研发的推送架构

架构方案类似:

image
(图片来自架构之美公众号,侵删)

  • 通过动态组合和扩展方式,结合移动Push推送数据分析,不同的手机使用不同的方案,针对性的优化,android平台中,融合多种不同的第三方推送PUSH平台,提高转化率。