title: Austinの 1. 从零搭建urlname: gzu0r1
date: ‘2022-05-18 18:35:24’
tags: []
categories: [项目实操]
启航 #01
什么是 Maven?
Maven 是一个「项目管理」工具,其核心功能是「依赖包管理」,在日常开发中,还承担着
「编译」、「测试」、「打包」、「部署」等其他功能。
开发常用maven 命令:
1.mvn compile2.mvn test3.mvn clean4.mvn pakage5.mvn install6.mvn deploy7.mvn versions:set -DnewVersion=xxxx 设置Maven的版本8.mvn dependency:tree 查看maven的依赖树(排查依赖很有效)常用参数-Dmaven.test.skip=true-Dmaven.javadoc.skip=true
什么是 SpringBoot?
SpringBoot 是 Spring 组件一站式解决方案,用于简化使用 Spring 的难度,简省繁重的配置,提供各种启动器,让我这么菜的程序员都能写代码。
SpringBoot の约定大于配置是一种开发原则,比如:
- Maven 目录结构。默认 resources 目录存放资源配置文件,java 目录存放 java 源文件,默认编译生成类在 target 目录等等
- 默认配置文件以 application.命令的 yml 或 properties 文件,且唯一
- 数据库连接信息以 spring:datasource:为前缀
SpringBoot 的两个重要作用:
- 当引入 SpringBoot 依赖(
spring-boot-start-parent)时,点入parent可以看到spring-boot-dependencies定义了很多默认依赖 ,开发中就不用写版本了。 - 启动 SpringBoot 时,会初始化很多默认配置(即面试常问的「自动配置」),总的说,
@SpringBootApplication等同于以下三个注解
@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan
为什么项目结构是多模块?
好处:
- 分包的话,所有代码在一个模块。修改后需要编译整个模块
- 分模块的话,直接在模块下
mvn conpile -Dmaven.test.skip=true即可
为什么 Git
Git 是版本控制工具,可以看到每次提交的功能,可以回退版本,利于多人协作
1. git clone (克隆代码)2. git checkout -b (新建分支)3. git checkout (切换分支)4. git add / git commit /git push (这几步我基本都是在IDE上用快捷键完成,很少自己敲命令)5. git fetch (获取最新的修改信息)6. git merge (合并代码)7. git statsh /git pop (有的时候临时会用,把代码放到暂存区中)8. git reset --hard (代码写烂了,直接回退吧)
参考&推荐
日志系统 #04
什么是日志?
日志简单说,就是记录程序运行时的信息
初学 Java 的时候一般用console和System.out.println做本地调试,但这种方法太傻了且程序部署到服务器之后不适用,因为生产环境和本地环境有很大的差别:
- 生产环境需要记录更多的日志
- 生产环境的日志需要保存到文件中
- 生产环境的日志内容需要一定的规范格式,比如时间
Java 日志体系

不同的技术框架所采用的 Java 日志实现很可能不一样,那么调用的 API 是否不同?
在这里,Sl4j做了类似 JDBC 的事情,它定义了日志的接口(门面模式),当项目使用别的日志框架时,就适配它。(类似 JDBC 定义接口,数据库厂商实现)。
因此,在项目中,最好使用 Slf4j 提供的 API,真实的 LOG 实现都可以用Slf4j 进行桥接。
日志有什么用?
日志的第一个典型的作用是定位问题,但它还有其他的重要功能。
开发中的很多数据来源于日志,在大数据领域中,数据有很多来源:关系型数据库、爬虫、日志等。
举个 🌰,3y 以前的公司有一套日志处理框架:
- 将正常的日志输出到指定文件
- 框架提供后台给予我们配置(文件的路径以及 Kafka Topic Name)
该框架作用:将日志文件转成 Kafka 消息,配合流式处理平台(Storm/Spark/Flink)对日志进行清洗后,可产生有价值的数据
Austin 日志
Austin 项目采用 SpringBoot 默认的日志组合:Sl4j + logback
logback 使用

SpringBoot 默认加载 resources 下的logback.xml或logback-spring.xml配置文件
如果都不存在,logback 默认调用BasicConfigurator,创建一个最小化配置
最小化配置由一个关联到根 logger 的 ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化
logback 配置
默认的 logback 是打印在 console 里的,我们希望将日志记录在文件下。
所以,在resources下新建logback配置。常见配置内容:
<?xml version="1.0" encoding="UTF-8"?><configuration scan="true" scanPeriod="10 seconds"><contextName>austin</contextName><!-- 设置日志输出路径 可以使“${}”来使用变量。TODO 这里后面是需要读配置的 --><property name="log.path" value="logs"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/austin-info.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/logs/austin-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>1000MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>info</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 ERROR 日志 --><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/austin-error.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/austin-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>1000MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><root level="info"><!-- TODO console打印后面可以只针对dev环境的 --><appender-ref ref="CONSOLE"/><appender-ref ref="INFO_FILE"/><appender-ref ref="ERROR_FILE"/></root></configuration>
好用的开发库 #05
讲一些开发用的好东西:工具包、Lombok 和常用库
什么是工具包
一般每个项目都有一个 utils 包,装一些常用的工具类,比如DateUtils、HttpUtils、Collections
Java 工具包推荐
Java 领域业内比较出名的两个工具包:commons和guave,国人维护的:Hutool
先了解一下这些工具包里封装了什么功能,当自己想要封装时,查一下前人有没有做好了这个功能,不要重复造轮子。这些工具包的链接 🔗
Lombok
Lombok 是一个 Java 库,IDEA 已经内置了 Lombok 插件,SpringBoot 2.1.x 之后的版本也在 Starter 中内置了 Lombok 依赖。
上面的介绍就看出来 Lombok 这东西有点牛了,在实际的开发中它的作用也相当直观,不用在一个个类里手动生成 set/get 方法也太省事了!Lombok 还有其他常用的注解:@Builder、@Slf4j、@Data等。
关于 Lombok 的原理 👉《对线面试官》 注解 #02
JSON 库 & HTTP 库
JSON 库作用:帮助 Java 后端开发做序列化和反序列化
- 前后端接口交互基本用 JSON 格式
- 有时候为了方便将数据转成 JSON 存储
- …
目前使用比较多的 JSON 库由:fastjson、Gson和Jackson
HTTP 库的调用常用在微信消息发送、短信发送等等,在 Java 生态中,HTTP 库大致分为三类:
- HttpURLConnection
- Apache HttpClient
- OkHttp
一般使用这些 HTTP 工具库,需要用 Utils 简化 HTTP 的调用:
下图来自 3y 公众号原文,因为我自己手敲一遍也记不住没啥用,直接截图好了

Austin 项目选择Okhttp作为 Http 库,算是业内标杆。
补充:SpringCloud 微服务间的请求一般使用 OpenFeign。
发送短信 #06
短信介绍
短信是一整个消息推送平台中最重要的消息类型,在日常开发中有许多使用场景:
- 验证码:登录注册、支付等重要场景
- 通知:用户订单信息、重要信息通知用户、商家等
- 营销类:在特定时间发送营销消息
- …
必要准备
选择腾讯云作为 austin 项目下初步发送短信的渠道商
功能实现
调用第三方 API 有两种选择:HTTP 调用和内嵌 SDK
Austin 项目采用 SDK,加自动生成代码
在配置文件修改账号信息和调用下接口,就可以收到自己的短信了。
为什么 austin 是消息平台
发送短信或其他消息的步骤很简单,就是对接 API 调用发送的接口。
一般项目发完就没有后续了,为什么使用 austin 平台?解决如下几个问题
- 调用消息接口,用户收不到反馈怎么办?
需要存储发送的记录,还需要接口保存短信的回执,并在后台提供相关查询页面

- 某个短信渠道商挂了怎么办?
接入多个渠道商,失败了就调其他的,支持动态分配渠道商的流量

- 这个月短信花了多少钱?
将短信的发送和回执数据存到 Hive,每个月跑一次 Hive 脚本进行对账。

- 现在调用短信的量大吗?
监控从接口调用到消息下发整个过程的数据(主要是接口 QPS 和下发人数)

- 业务方不小心连续发了两次怎么办?
作为平台需要有这种兜底的功能

- 这条短信是谁发的?
给接入方套”模板“,有了模板才能溯源,才能做数据追踪,模板是作为平台的基石。
- 经常要接入短信渠道怎么办?
上规则引擎将业务代码抽离,无需上下线即可实现功能。

搭环境 #番外 01
之前是项目的介绍,现在开始正式搭建环境并扒取启动项目。
搭建 MySQL
我之前搭过了…
原文链接
使用 austin

clone
mvn
修改
properties.yml,数据库和腾讯云配置信息打开
austin.sql,执行 DDL找到 austin-web 模块对应的 Controller,调试短信
ps:腾讯云的配置已经不在 properties.yml 里,只能往下继续学习才能进行测试
MySQL #07
数据库选择
MySQL,原因:
- 开源易用
- 低成本快速的数据存储插入方案
ORM 选择

SpringDataJPA
使用数据库的经验
我们在实际中生产环境中很有可能是不设计关联表,而是直接把相关字段冗余在一张表里。这样在查询的时候,就能直接通过一张表查到对应的信息了,不用进行多层关联

支持在代码里写业务逻辑的。所有都是单表查询,在程序代码中对数据进行关联(数据库的 JOIN 能干到的事,在程序上一定能干得到)。这样的好处就在于:SQL 简单,SQL 易复用,SQL 易优化

支持在代码里写业务逻辑的。所有都是单表查询,在程序代码中对数据进行关联(数据库的 JOIN 能干到的事,在程序上一定能干得到)。这样的好处就在于:SQL 简单,SQL 易复用,SQL 易优化
在绝大数情况下,我们的接口瓶颈都是来源于「数据库」,而非应用服务器。多 JOIN 且复杂的 SQL 是不好优化的,而简单的 SQL 是比较好优化的,并且我认为程序逻辑往往都要比 SQL 更容易维护。

开发之外的数据库
一、DDL 和 DML 都需要走工单
二、DQL 查询线上数据需要权限
三、程序上一般不直连数据库(会有代理层)
四、完备的监控告警
austin 建表 DDL

