基于微信公众号的微服务架构
本文字数: 1k 阅读时长 ≈ 1 分钟
- 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 项目。
总体架构图如下
Redis
- 提到阿里云的这个 Redis,不得不吐槽一句,它竟然是不支持主从的,只能单实例,不过,用它做数据缓存,还真是蛮不错的选择,响应速度非常快。而且,因为是放置在内网的且只能内网访问,所以安全性也很高。
MongoDB
- 结构型数据,主要存储档案式的数据,比如每个用户的操作行为,以档案式记录并进行统计分析,方便下一阶段的项目做个性化服务。另外一些关联复杂的数据,也可以用 MongoDb 存储,可以提高访问速度。还有,一些对软件应用版本比较敏感的数据也可以存在 MongoDB 中,比如 a 版本拿到 A 数据,b 版本拿到 B 数据,而这个 AB 数据都是由很多关联关系复杂的数据所组成,如果把这些数据根据版本号存储在不同的 MongoDB 档案中,需要时,直接根据版本号拿就可以了,这样就避免了很多的 mysql 查询。
静态资源
- OSS + CDN
OSS 存储静态资源,CDN(内容分发网络) 可以加速静态资源的下载速度。至于资源链接地址,客户端可以通过接口访问从后端业务数据库中拿到。
bootstrap日期格式化
本文字数: 954 阅读时长 ≈ 1 分钟
- 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
详情请看官网解释
datetimepicker Jquery日期格式化
本文字数: 410 阅读时长 ≈ 1 分钟
年
- 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
搭建Material主题的Hexo博客
本文字数: 183 阅读时长 ≈ 1 分钟
全篇可以在这搜到:
本地搜索插件
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:
node8.0方法弃用解决办法
本文字数: 200 阅读时长 ≈ 1 分钟
刚升级node后发现报如下的错:
(node:34880) [DEP0061] DeprecationWarning: fs.SyncWriteStream is deprecated.
node.js从8.0开始已经弃用了fs.SyncWriteStream方法,hexo中有一个hexo-fs插件,调用了这个方法,所以就会报错。
解决办法:
- npm install hexo-fs —save
插件就更新了,问题就解决了。
RPC通俗解释
本文字数: 208 阅读时长 ≈ 1 分钟
RPC通俗解释
IPC和RPC
早些时间,一个电脑中多个线程互相独立,A线程和B线程都想用发送邮件功能,就需要开发两份代码,所以就有了一个协议是:IPC(Inter-process-communication)进行进程间通信,这样就可以在A中开发一个发送邮件的代码,B进程调用A进程代码就行了。
同比,现在的程序员们,为了方便调用其他电脑中的代码,研究出来RPC(Remote Procedure Call Protocol);
JVM介绍
本文字数: 1.2k 阅读时长 ≈ 1 分钟
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模型
内存空间:
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 和本地方法栈,当线程终止时三者所使用的空间也被回收掉。
如何保证推送消息能够准确推送到客户端
本文字数: 1k 阅读时长 ≈ 1 分钟
如何保证推送消息能够准确推送到客户端。
手机端:
- 轮询方式获取消息。
- 短信拦截模式。 发送短信通知消息,应用中的短信拦截模块拦截短信,并解析成数据。成本高。
持久连接。
监听电量变化,网络变化,开关屏幕等等时候注册BroadCastReceiver来接收通知,接手后进行消息获取。
有些ROM一旦用户kill掉主线程,就不会再投送广播消息给应用,导致应用无法启动,这是可以Fork一个进程,一旦发现主线程被杀,立即调用shell启动该Service(应用保活)
微服务间如何选择推送和拉取数据
在消息系统中,一般有两种消费模式:生产端推送消息,消费主动拉取消息。
数据是动态的,且实时性较强,宜采用生产端推送。
例如家长手机控制孩子手机使用,希望设置立即生效,家长端设置后由立即由中间系统进行通知。如果让消费端轮询查消息,不仅不能保证消息的实时性和准确性,而且系统也会造成一定的损耗,供应链系统也会被迫处理重复订单问题。
如果把消息设置成实时推送也是不合适的,推送成不成功不应该作为设置成功的条件。设置功能和推送功能不应该是强关联的,就像发送验证码,服务器收到了发送验证码的功能请求后,异步交给验证码发送功能,返回给客户200成功,随后验证码发送功能进行异步通知,确保通知成功即可。
客户端长时间离线状态
客户端长时间离线状态(断网,没电等等),没办法推送过去,会暂存在一个暂存表中,等待客户端联网等监听广播事件进行主动获取,消息获取成功,就会把离线消息表里的消息转移到已发送的消息表中。(不在本表中将已发送的消息的字段置为已读,会影响查询速度。)
推送的优点
- 时效性高。
- 服务器压力小。 相对比轮询拉取模式,每次推送都会有数据,有效避免了空轮询
- 交互简单。 只需要提供推送接口就好了,不需要额外开销。
推送的缺点
- 不能保证一定能推送成功。
- 缺乏数据多样性,推送的消息一般都有固定的模板
极光推送
- 活跃用户的到达率在90%以上。轮询获取99%以上。
- 并发情况下第三方服务的实时性不太理想。
自主研发的推送系统
- 对客户端的海量长连接的维护管理消耗太大。
- App端Service稳定性,保活。
- 有些厂商不允许有push service存在。
自主研发的推送架构
架构方案类似:
(图片来自架构之美公众号,侵删)
- 通过动态组合和扩展方式,结合移动Push推送数据分析,不同的手机使用不同的方案,针对性的优化,android平台中,融合多种不同的第三方推送PUSH平台,提高转化率。