Maven 插件配置指南
本文主要参考了《Guide to Configuring Plug-ins》: maven 实际上有两种插件: 构建插件,需要在<build/>元素里配置。如<build><pluginManagement/></build>,当然也有<build><plugins/></build>。 报告插件,会在“site generation”里被执行,应该在<reporting/>里配置。如<reporting><plugins/></reporting>。 要引用插件至少要有三个元素:groupId,artifactId, version。 mojo 是什么 根据《What is MOJO in Maven?》,mojo 是 Maven plain Old Java Object 的意思。实际上是可执行的 goal。 通用配置 一个插件通常包含一个以上的mojo,当一个 mojo 被映射到 goal 的时候,则包含多个 mojo(即一个插件可能有多个...
Maven 构建生命周期
maven-生命周期.xmind 构建生命周期的基础知识 Maven 基于一个“构建生命 周期”的中心概念,也就意味着构建和发布一个特定的工件(也就是工程)的过程已经被清晰地定义了。 有三种内置的生命周期:default,clean 和 site。default 生命周期处理处理项目部署,clean 生命周期处理项目清理,site 生命周期处理项目的站点(site)文档的创建。 实际上这些 lifecycle 只是在(比如 idea 里)对 phase 归类的时候特别有用,我们平时使用 mvn 命令的时候是无法指定这几个生命周期的。 一个构建生命周期是由多个阶段(phases)组成的 上面每个生命周期是由不同的 phase 列表组成的。一个 phase 表示一个生命周期的一个 stage(这两者有什么差别?)。 default 里 phases 的顺序大致上是是 validate -> compile -> test -> package -> verify -> install -> deploy。 使用命令行 如果我们使用命令: 1mvn...
卡表和 RSet
上下文 卡表和 RSet(Remember Set),是 JVM 为了解决分代收集时,live set 扫描需要穿梭到不同的代的时候的效率问题。 使用缓存表来提高查询效率,是化顺序查找为部分随机查找的一种常用的设计思路。 例如,在传统的计算机体系结构中,当我们把内存分成页以后,会有一个页表,页表又会有一个快表,作为一个中间缓存项,来帮助我们查找我们需要使用的页表项(table entry)。 JVM 在进行垃圾收集的时候,有一项非常重要的工作就是确定这一次垃圾收集的对象到底有多少个,即确定 live set 的范围。 对于新生代垃圾收集器而言,这个问题又有其特殊之处。根据 JVM 的弱分代收集假设(weak generational hypothesis)的存在,每次垃圾收集的时候,新生代的扫描范围可能很大,但新生代的 live set 不应该太大。card table/Remember Set 的设计目的,就是尽量减少无用的垃圾扫描范围,使用类似操作系统或者数据库的脏页表的形式,来做类似快表的查询。 卡表(card table) 卡表是 CMS 的解决方案。 卡表通常在 JV...
数据建模名称规范
综合 NV + DiDi + Ali 的各种命名规范。 DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。 DTO( Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。 BO( Business Object):业务对象。 由Service层输出的封装业务逻辑的对象。 AO( Application Object):应用对象。 在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。 VO( View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。 POJO( Plain Ordinary Java Object):POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。 Query:数据查询对象,各层接收上层的查询请求。 注意超过2个参数的查询封装,禁止使用Map类来传输。 Entity:JPA 规范下从数据持久层存储里取出来的对等对象。其实相当于 DO 。 Request:RESTful 接...
业务分析方法
背景 从 prd 出发,分析业务需求,寻找可以创造价值的方案。 业务分析的价值 全面分析用户的各项需求 告诉我们“做什么” 业务分析的目的 理解产品需求,识别业务范围 分析业务模块的重要程度、优先级 发现产品设计的不足 为后后续测试分析做准备 业务分析方法-整体过程 用不同的动作达到不同的产出。 理解 需求背景(必须) 举例:阿里巴巴账户体系 要初步阐述:1. 产生什么价值。 2. 需要解决什么问题。3. 甚至要阐明要达到什么目标(比如,基于支付宝账户体系统一账户id)。 现状分析(必须) 产品定位 现有业务架构 产品业务范围 规划业务架构**(1. 要有分期的意识,识别产品形态。 2. 要有清洗数据的方案,预测安全风险)** 识别(抽象分析建模) 业务角色(实际上就是系统交互的输入方,有多少个角色,就需要关注多少个东西) 自然人 其他系统 业务串联(为了找业务用例。业务串联就是把一堆文字描述串在一起) 业务用例(建模-业务用例图 用例是对场景的概括) 分析业务用例(建模-活动图 活动图是对用例的拆解) 提炼(进一步建模) 关键流程 由活动图的 ...
系分方法论交流笔记
分析、设计和架构的区别 系分 = 业务分析 + 系统设计 系分其实就是 Analysis + Design 业务分析才是最重要的大头 要理解: 架构约束 项目约束 要有: 权衡 选择 的过程 理解业务,要理解业务背后的东西,产出的是模型。 一步一步走,推演出来解决方案,要有方法论。 系统设计是很明确的工作了 应用设计 + 数据设计 + 技术设计 = 系统方案 要考虑的额外问题: 非功能设计:运行关注点、运维关注点、开发关注点、测试关注点。 项目约束 常见方法论 用例驱动设计 SOAD 面向服务的分析和设计 OOAD 面向对象分析和设计 DDD 领域驱动设计 DDD特别适合复杂系统。有一个以不变应万变的对象,才可以在未来承载复杂的业务演进过程。 这几种方法论可以混合使用。 需求分析与业务建模 把 prd 从薄读到厚,把文档中缺失的部分补全。 系分做 PRD 评审的时候,影响比较大的点一定要尽早确认。一些对系统变化可控,可预测的变化,可以暂时放过,后续在补充。 面向服务的业务建模 分析主业务服务,设计业务功能域,设计业务功能域边界。这个过程可能不断地螺旋式地重构。 如果用...
Docker 与存储
写在前面的话 容器的默认状态难以从容器中搬运出来。 容器的默认状态是基于联合文件系统的,也就是需要存储驱动的支持,效率会比直接写到宿主机文件系统里要差一点。 所以此处 storage driver,就正对应 network driver 了。 把数据写入到宿主机上的方法有:volumes 和 bind mounts。如果在 linux 上,还有 tmpfs mount。注意,这些东西不是 storage driver。 他们之间的关系是: 在操作系统和 docker 层面,可以认为 volumes 是有实际存储的设备(虽然被虚拟化)的抽象(在 k8s 抽象里是 volumeMounts),而 mount 是带有 path 的一个挂载点(在 k8s 抽象里是 mountPath)。 Volumes 在宿主机文件系统上,Volumes 使用一块专属的路径来存储 docker 文件,如/var/lib/docker/volumes/,其他进程不应该碰这些文件。 Volumes 是 Docker 持久化数据最佳的选择。 常见创造数据卷的方法 只能迟至容器创建时把一个数据卷和容器关联起...
OOM 调查使用到的工具
基础工具 top 与 htop。这两个东西比 free 好用。比较神奇的是,为什么线上还有装了 htop这样的非标准 top。字节跳动自己开源了一个 atop,可以细致地监控线程信息,也可以快速采集系统信息,是一个不错的监控工具。 pmap。这个东西是莫枢自己也用来 dump 详细的内存轮廓的地址,但可能需要使用他提到的一个 Serviceability Agent API 来读才读得懂。这个工具的输出可以看到各段内存的起止,但不经帮助,很难读出各个子线程的栈来。 这个命令在非 root/sudo 权限下看到的是 jvm 启动参数,在 root/sudo 权限下看到的是内存轮廓,这时候就需要 Serviceability Agent API 了。 smem。这个东西对内存的 RSS/PSS/USS 分析得很好。但并不能帮助我们直接获知我们最期待的栈内存轮廓,比如当前 JVM 的 stack 到底是怎么分布的,占了多少内存?而且更重要是,线上机器没有这个工具。 直接 cat /proc/pid/smaps 其实其他的进程内存查看工具的信息可能都能在这里看得到,但是需要耐心。而且,...
Docker 与网络
docker 操纵网络是无形的,它通过修改路由规则来让某些包在特定的 network 里面流动。在 Linux 下,它是通过操纵 iptables 来做到这件事的(windows下通过其他机制)。 docker 驱动 docker 的网络是可插拔的,因为使用了驱动。默认就自动携带的驱动是: bridge 默认的网络驱动。 当所有的容器都在一个宿主机的时候,应该使用这个驱动。 在计算机网络的范畴里,一个桥接网络是一个链路层设备,转发网络片段。一个桥可以一个硬件设备或者宿主机内核里的软件设备。 在 Docker的范畴里,桥接网络使用一个软件桥来让容器连在同一座桥上,通过桥通信。同一个宿主机里,不同桥网络是不能相互通信的(实际上不同的网络就不应该彼此通信)。 启动 docker 的时候,一个默认的桥接网络就被创建了。如果没有其他网络被创建,则默认大家都使用这个网络。所有新创建的容器,都会自动在这个名称为 bridge 网络里互连。用户也可以创建自定义的桥接网络,自定义的桥接网络拥有更高的优先级。 自定义网络的优势 用户自定义网络在容器化应用程序里,提供了更好的隔离和互操作性。在同一个...
日期与时间
JSR 310 Java Date与Time API 新旧 API 的更迭 旧的 Java API 主要包括java.util.Date和java.util.Calendar 两个包的内容。这两个包的时间类型是可变的。如 Date 的实例可以通过 setYear 来产生变化。 JSR 310 中包括的日期类型主要有: 计算机时间:Instant,对应 java.util.Date,它代表了一个确定的时间点,即相对于标准Java纪元(1970年1月1日)的偏移量;但与java.util.Date类不同的是其精确到了纳秒级别。 人类时间:对应于人类自身的观念,比如LocalDate和LocalTime。他们代表了一般的时区概念,要么是日期(不包含时间),要么是时间(不包含日期),类似于java.sql的表示方式。此外,还有一个MonthDay,它可以存储某人的生日(不包含年份)。每个类都在内部存储正确的数据而不是像java.util.Date那样利用午夜12点来区分日期,利用1970-01-01来表示时间。这些类型的实例是 immutable 的,而且只能通过工厂方法创建。 时区...