Nacos安装指引

说明

  • Nacos提供的应用包是跨平台通用的版本,其中包含了.sh.cmd的脚本,主程序是一个jar包,本文档以Linux安装使用为例进行说明;
  • 安装版本:nacos-1.3.2
  • 安装目录:/opt/nacos

安装步骤

1. 检查运行环境

  • Nacos主程序是一个jar包,需要在JAVA环境下运行,需要先检查是否已经配置好环境;

2. 下载解压

  • 下载应用包:wget https://github.com/alibaba/nacos/releases/download/1.3.2/nacos-server-1.3.2.zip
  • 解压:unzip nacos-server-1.3.2.zip
  • 移动文件夹到/opt目录下:sudo mv nacos /opt/nacos

3. 修改配置

由于Nacos默认以集群的方式运行的,当需要单体运行的时候,需要在启动脚本的时候添加额外的参数-m standalone,但经常输入额外参数会比较麻烦,因此可以直接修改启动脚本bin/startup.sh进行以下修改即可默认以单体的方式启动:

1
2
3
export MODE="cluster"
# 修改为
export MODE="standalone"

4. 操作命令

  • Nacos启动命令:sh /opt/nacos/bin/startup.sh
  • Nacos停止命令:sh /opt/nacos/bin/shutdown.sh

如使用的系统为Ubuntu一类请替换shbash

5. 验证启动及使用

  • 启动Nacos后,控制台会输入提示查看/opt/nacos/logs/start.out文件确认启动是否完成;
  • Nacos的默认端口为8848,可以通过浏览器访问地址http://${IP}:8848/nacos/打开Nacos的监控面板;
  • Nacos提供注册中心服务的地址为nacos://${ip}:8848

Java注释说明

目的

合理规范的代码注释,一方面可以使代码见注释知其义,有利于对代码的理解、调用、重构、复用等,另一方面可以生成有效并且美观的API文档。关于javadoc的完整说明请参照官网,本文将结合不同方面对javadoc的日常使用进行说明。

认知和使用

不少开发人员对于javadoc这个东西并没有充分的认知,没有理解其提供的各种标签和注解,因此在撰写javadoc的时候经常是随心所欲地添加描述,甚至还自定义了各种各样的不能被javadoc识别的标签和注解。这样出来的代码注释没有清晰的规范,结构凌乱,可读性低,更不能生成一份有效的API文档,失去了javadoc提供的所有优点。

因此要强调的第一件事是,学会去使用javadoc。举个例子,如果你正在使用IntelliJ IDEA并且使用默认的keymap,把你的光标放在某个类、方法、属性或者变量上,按下Ctrl+Q,你就能看到对光标处成员的描述说明,而这个描述说明就是由我们所撰写的javadoc渲染而成(最新的2020版本IDEA甚至可以设置在代码上默认显示渲染后的javadoc)。当你意识到自己写的注释在描述说明中会渲染出一个怎样的效果时,你就下意识地按照规范去维护好这些注释,使之显示成一个美观并且有效的描述说明。

需要强调的第二件事是,javadoc应该是在设计接口和编写代码的同时去撰写,而不应该是事后再去做补救,因为开发的过程中思维会比较缜密,考虑得会更周全,事后可能会忘记很多的细节,描述会有各种的疏漏,这两种情况下编写出来的注释内容质量是不在一个次元上的。而且,参考TDD(测试驱动开发)的说法,先编写注释其实也可以起到协助梳理、提供清晰思路的效果。

javadoc常用标签说明

以下对一些常用的标签进行说明。

@author name-text

@author标注在 上,用于标识一个类的作者,name-text即该作者的个人标识。一般不需要标注在方法上,我们可以通过Git History来了解各部分更改的作者。

@version version-text

@version指定 的版本,version-text为具体的版本号。

1
2
3
/**
* @version v1.0.0
*/

@since since-text

@since标记开始引入该特定变化的所处的阶段,一般后面的since-text为当前版本号,代表该变化产生于当前这个版本。

1
2
3
/**
* @since v1.0.0
*/

@deprecated deprecated-text

@deprecated用于说明一个类或成员已过期,deprecated-text对过期原因、代替的类或成员等进行一个详细的说明。一般被该标签标注的类或成员后续新的代码不再对其进行使用,保留仅作为过渡期兼容旧版本代码,后续一般会进行移除。

@see reference

@see指定了一个到另一个类或成员的链接,其一般的写法为@see package.class#member label,其中package为成员的完整包名,class为类名,member为成员名,可以是属性、方法,成员用#来标志。最后的label用于把前面的一长串字符显示为自定义的文字,相当于昵称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 类
* @see java.util.HashMap
*/

/**
* 类内属性
* @see java.util.HashMap#size
*/

/**
* 无参方法
* @see java.util.HashMap#values()
*/

/**
* 有参方法
* @see java.util.HashMap#putAll(Map)
*/

/**
* 使用label代替方法名
* @see java.util.HashMap#putAll(Map) putAll
*/

{@link}为段中插入到另一个引用的链接,注意需要使用{}括起来。写法为{@link package.class#member label},基本与@see一致。

1
2
3
4
/**
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*/

{@linkplain reference}

{@linkplain}的功能和使用都与{@link}完全一致,唯一的区别是{@link}显示出的样式是代码的样式,而{@linkplain}显示的则是普通文本的样式。

{@value reference}

{@value}用于引入某个静态常量,写法为{@value package.class#field},其中field为静态常量名,而最后显示在描述中的为静态常量的值。

{@code text}

{@code}用于插入一段特定的字符,样式是以代码模式显示,一般用以强调一些变量名、常量值、特殊意义的字符、枚举量等。

1
2
3
4
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*/

{@inheritDoc}

{@inheritDoc}用在重写的方法或者子类上,用于继承父类的javadoc,然后子类或者方法可以在这个基础上再加入自己的注释进行拓展。

@param parameter-name description

@param用于说明一个方法的参数,格式为@param parameter-name description,其中parameter-name为参数名,description为对参数的详细描述。

1
2
3
4
/**
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
*/

@return description

@return用于说明返回值的类型以及详细描述。

1
2
3
/**
* @return the number of key-value mappings in this map
*/

@throws/@exception class-name description

@throws@exception两个标签是一致的,用来标志一个类抛出的异常。写法为@throws class-name description@exception class-name description,其中class-name为所抛出异常的class,description为对抛出异常的描述。

1
2
3
/**
* @throws NullPointerException if the specified map is null
*/

标签

在写注释的时候,如果没有意识的话就会按照普通文本的方式去写,包括换行、进退格这些,但是这样不但显示出来的效果不好,格式还会被代码自动格式化的操作弄乱。首先,javadoc的渲染是以html的方式进行解析,所以对于换行退格等格式,普通文本出来的效果肯定不好,我们需要在文本中适当添加一些常用的html标签,来让代码注释的样式显示得整洁美观。比如换行</br>、新段落<p>、原样渲染<pre>、分点<ul><li>等等。(当然,如果你并不擅长用html的方式来写文档,并且没有非常追求原生性,是可以使用Markdown Doclet for Javadoc这个插件,使用Markdown替换html的。)

1
2
3
4
5
6
7
8
9
/**
* First paragraph.
* <p><ul>
* <li>the first item
* <li>the second item
* <li>the third item
* </ul><p>
* Third paragraph.
*/

样例

对于类,一般需要对类的作用进行描述,并且提供作者、版本等信息,最简单的写法如下:

1
2
3
4
5
6
7
8
/**
* 现货实例Controller
*
* @author xxx
* @version v1.0.0
* @since v1.0.0
*/
public class SpotInstanceController {}

属性成员

属性成员的注释一般直接进行描述即可:

1
2
3
4
/**
* The Spot instance service.
*/
private SpotInstanceService spotInstanceService;

方法

对于方法,我们需要进行详细的描述,包括功能描述、入参说明、返回结果说明、抛出异常说明。

1
2
3
4
5
6
7
8
9
/**
* 获取现货实例详情
*
* @param tmSceneDateKey 经济场景日期key
* @param tradeNum 交易序号
* @return 现货实例详情对象
* @throws Exception the exception
*/
public Object getSpotInstanceDetail(String tmSceneDateKey,Integer tradeNum) throws Exception {}

重点说明

上面给出的例子都是简例,但是实际撰写的时候必须要详细描述清楚,尤其是功能描述、入参、返回结果这几个部分。

  • 功能描述要表达清楚这个方法的作用、适用场景等;
  • @param@return应该清楚说明数据的类型和取值范围等,如果是对象的话最好可以说明对象中有没有哪些属性是空的、哪些是不需要填的这种粒度的说明(因为一个对象的类会用在多个地方,并不是完全为某一个方法量身定造的,比如一个对象在add操作时是不需要id的,但是在update的时候则必须填写id);如果是Map这类数据也最好能说明各种情况会返回的key的意义以及value的范围等。

简而言之,尽量做到看着注释可以理解整个方法的作用、如何去调用、返回结果的真实结构、有那些不可预测的运行结果,这样才能让你的代码更加清晰,更进一步用好设计模式等,把你的代码写得像诗一般优雅(事实上JDK源码的注释可以作为一份教科书般的参考)。

Git LFS简介

简介

**Git LFS(Large File Storage)**,即Git大文件存储,目的是把大文件的版本管理存储到Git仓库的外部。虽说由于Git本身的文件变化存储机理,原则上是不使用Git存储大文件的。但是项目类型多种多样,很难避免不会出现一些体积较大的文件,而如果这些文件频繁修改的话就会导致Git仓库的体积不断膨胀。Git LFS的出现正是为了解决这个问题,通过配置记录追踪某些大文件,在推送版本到远程托管仓库时被追踪的大文件会默认保存到托管服务器的一个配置好的位置,而不是存储在Git仓库里,仓库里仅保留一个文件指针。当下次执行clone的时候,对于该大文件只会下载当前chekcout的版本对应的文件,而历史版本则不会被clone到本地仓库里,只有checkout到其他版本的时候才会再下载对应版本的文件。

优缺点分析

  • 优点:把存储大文件的压力转嫁给托管服务器,并且因为Git仓库体积的减少,可以节省下载仓库的带宽和时间;
  • 缺点:背离了Git去中心化的设计初衷,其本地仓库变成了一个不完整的仓库,操作变得极度依赖网络;

环境配置

  • 本地:确认本地安装了Git LFS,新版本的Git客户端默认集成了这个模块(如果不安装LFS可能会导致大文件下载不全等问题);
  • 线上:GitHub和新版本的GitLab都默认支持LFS,无需额外安装环境;

使用说明

  • 首次使用Git LFS需要先安装配置git lfs install,如果命令执行结果返回Git LFS initialized.则说明已经可用;
  • 在仓库里执行命令git lfs track "xxx"对文件进行追踪,可使用*匹配多个文件;
  • 上一步骤会在仓库里产生一个配置文件.gitattributes,如果搬来已存在则会更新内容,注意要把该配置文件的改动提交到Git仓库里;
  • 随后只需正常地在Git仓库提交该大文件即可:
1
2
3
git add xxx
git commit -m "xxx"
git push origin xxx_branch
  • push以后便可以在托管服务器上看到该文件被标识为LFS文件,不占用Git仓库的空间,而clone的时候也是按普通的仓库一样操作即可;

常用场景

  • 仓库迁移的时候,我们需要先把LFS文件的全部版本下载到本地,可执行以下命令:
1
git lfs fetch --all
  • 当本地仓库积攒了比较多版本的LFS导致体积较大的时候,可以通过以下命令进行清理:
1
git lfs prune
  • 若想了解Git LFS的其他命令,可在命令行执行help命令查看:
1
git lfs help

Git Commit规范化

为了方便回溯历史、进行Merge和cherry-pick等,我们需要Git仓库的历史树具有较强的可读性,因此需要规范化commit messagecommit方式

Commit message

commit message是用于正确地简述该提交所涉及的内容,按照一定的规范撰写能有效地提高团队的工作效率。撰写的最基本格式可以按照<type>: <subject>这种模式,其中type是提交内容的类型,而subject则是提交的概要描述。如果概要描述subject无法清楚描述本次提交的内容,则可以在换行后的<body>部分撰写详细的Description。

更多详细的扩展模式可以参考commitizen提供的选项,这种更精细化的标准提供了更多的内容分类,包括提交代码的影响范围、关闭issue等。

常用的type有以下这些:

  • feat: 增加新功能
  • fix: bug的修复
  • docs: 文档的添加或修改
  • style: 不影响代码功能的代码格式变化
  • refactor: 代码的重构
  • perf: 提升性能的代码
  • test: 增加测试用例
  • build: 项目构建相关的代码
  • ci: 持续集成相关的代码
  • chore: 其他一些不影响源码的提交
  • revert: 提交的回滚

参考:Git: 教你如何在Commit时有话可说

相关规范工具

  • 命令行工具commitizen
  • Intellij IDEA插件:Git Commit Template,JetBrains全家桶通用;

Commit方式

关于Commit方式同样需要规范化:

  1. 清晰描述commit的内容,不同类型或不同功能的内容 分开多次提交 (IDEA或者VSCode都支持单个文件选择部分内容进行stage和commit);
  2. 根据commit message提交文件,不掺杂commit message描述以外的内容;
  3. 同一个文件的移动文件夹操作与重命名或者文件内容大量修改操作需要尽量分开进行commit,为了能识别文件变化操作是移动而不是删除文件并新增新的文件,这样能尽量保存文件的修改历史;

Linux目录说明

Linux根目录下的文件夹的作用说明。

  • /home: 用户的主目录
  • /root: root用户的主目录
  • /bin: 存放二进制可执行文件(ls/ps/kill等常用命令)
  • /sbin: 存放root用户使用的二进制可执行文件(ifconfig等命令)
  • /usr: 存放系统应用程序的安装目录
  • /opt: 额外安装的应用程序包
  • /etc: 存放系统配置管理文件
  • /mnt: 文件系统挂载目录
  • /boot: 系统引导文件
  • /lib: 存放系统程序运行所需要的共享库及内核模块
  • /var: 常态性变动文件目录,存放如日志等运行后会渐渐占用硬盘容量的文件
  • /tmp: 公用的临时文件存储目录
  • /dev: 设备文件,包含了所有Linux系统中使用的外部设备(一切皆文件)
  • /proc: 虚拟文件系统,是系统内核的映射。可以更改其中某些文件来改变内核运行状态,或者用来查看系统硬件及当前运行的进程信息。
  • /lost+found: 收留系统异常关机导致“无家可归”的文件,一般为空