• SpringBoot 学习笔记:运维篇


    SpringBoot程序的打包和运行

    1. 开发部门使用Git、SVN等版本控制工具上传工程到版本服务器
    2. 服务器使用版本控制工具下载工程
    3. 服务器上使用Maven工具在当前真机环境下重新构建项目
    4. 启动服务

    程序打包

    IDEA环境下的打包

    命令行打包

    mvn package
    

    打包后会产生一个与工程名类似的jar文件,其名称是由模块名+版本号+.jar组成的。

    程序运行

    java -jar 工程包名.jar
    

    执行程序打包指令后,程序正常运行,与在Idea下执行程序没有区别。

    注意:如果你的计算机中没有安装 Java 的 JDK 环境,是无法正确执行上述操作的,因为程序执行使用的是 Java 指令。

    注意:在使用向导创建Spring Boot工程时,pom.xml文件中会有如下配置,这一段配置千万不能删除,否则打包后无法正常执行程序。

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    

    总结

    1. SpringBoot工程可以基于java环境下独立运行jar文件启动服务
    2. SpringBoot工程执行mvn命令package进行打包
    3. 执行jar命令:java –jar 工程名.jar

    命令行启动常见问题及解决方案

    # 查询端口
    netstat -ano
    # 查询指定端口
    netstat -ano |findstr "端口号"
    # 根据进程PID查询进程名称
    tasklist |findstr "进程PID号"
    # 根据PID杀死任务
    taskkill /F /PID "进程PID号"
    # 根据进程名称杀死任务
    taskkill -f -t -im "进程名称"
    

    Spring Boot项目快速启动(Linux版)

    待补充

    配置高级

    临时属性设置

    当我们的项目通过 IDEA 编写后利用 Maven Package 打包好了后就可以发布了。但是程序包打好以后,里面的配置都已经是固定的了,比如配置了服务器的端口是8080。如果我要启动项目,发现当前我的服务器上已经有应用启动起来并且占用了8080端口,这个时候就尴尬了。难道要重新把打包好的程序修改一下吗?比如我要把打包好的程序启动端口改成80。

    Spring Boot提供了灵活的配置方式,如果你发现你的项目中有个别属性需要重新配置,可以使用临时属性的方式快速修改某些配置。

    java –jar springboot.jar –-server.port=80
    

    注意:这里面书写的格式是properties文件格式

    java –jar springboot.jar –-server.port=80 --logging.level.root=debug
    

    属性加载优先级

    ​ 现在我们的程序配置受两个地方控制了,第一配置文件,第二临时属性。并且我们发现临时属性的加载优先级要高于配置文件的。那是否还有其他的配置方式呢?其实是有的,而且还不少,打开官方文档中对应的内容,就可以查看配置读取的优先顺序。地址奉上:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config

    我们可以看到,居然有14种配置的位置,而我们现在使用的是这里面的2个。第3条Config data说的就是使用配置文件,第11条Command line arguments说的就是使用命令行临时参数。而这14种配置的顺序就是Spring Boot加载配置的顺序,言外之意,命令行临时属性比配置文件的加载优先级高,所以这个列表上面的优先级低,下面的优先级高。其实这个东西不用背的,你就记得一点,你最终要什么效果,你自己是知道的,不管这个顺序是怎么个高低排序,开发时一定要配置成你要的顺序为准。这个顺序只是在你想不明白问题的时候帮助你分析罢了。

    ​ 比如你现在加载了一个user.name属性。结果你发现出来的结果和你想的不一样,那肯定是别的优先级比你高的属性覆盖你的配置属性了,那你就可以看着这个顺序挨个排查。哪个位置有可能覆盖了你的属性。

    之前在学习过程有遇到过这张问题,在yaml中配置了user.name属性值,然后读取出来的时候居然不是自己的配置值,因为在系统属性中有一个属性叫做user.name,两个相互冲突了。而系统属性的加载优先顺序在上面这个列表中是5号,高于3号,所以SpringBoot最终会加载系统配置属性user.name。

    总结

    1. 使用jar命令启动SpringBoot工程时可以使用临时属性替换配置文件中的属性
    2. 临时属性添加方式:java –jar 工程名.jar –-属性名=值
    3. 多个临时属性之间使用空格分隔
    4. 临时属性必须是当前boot工程支持的属性,否则设置无效

    开发环境中使用临时属性

    ​ 临时使用目前是有了,但是上线的时候通过命令行输入的临时属性必须是正确的啊,那这些属性配置值我们必须在开发环境中测试好才行。下面说一下开发环境中如何使用临时属性,其实就是Idea界面下如何操作了。

    ​ 打开Spring Boot引导类的运行界面,在里面找到配置项。其中Program arguments对应的位置就是添加临时属性的,可以加几个试试效果。

    image20211206101947622

    做到这里其实可以产生一个思考了,如果对java编程熟悉的小伙伴应该知道,我们运行main方法的时候,如果想使用main方法的参数,也就是下面的args参数,就是在上面这个位置添加的参数。

    public static void main(String[] args) {
    }
    

    ​ 原来是这样,通过这个args就可以获取到参数。再来看我们的引导类是如何书写的

    public static void main(String[] args) {
        SpringApplication.run(SSMPApplication.class,args);
    }
    

    ​ 这个args参数居然传递给了run方法,看来在Idea中配置的临时参数就是通过这个位置传递到我们的程序中的。言外之意,这里如果不用这个args是不是就断开了外部传递临时属性的入口呢?是这样的,我们可以使用下面的调用方式,这样外部临时属性就无法进入到SpringBoot程序中了。

    public static void main(String[] args) {
        SpringApplication.run(SSMPApplication.class);
    }
    

    ​ 或者还可以使用如下格式来玩这个操作,就是将配置不写在配置文件中,直接写成一个字符串数组,传递给程序入口。当然,这种做法并没有什么实际开发意义。

    public static void main(String[] args) {
        String[] arg = new String[1];
        arg[0] = "--server.port=8082";
        SpringApplication.run(SSMPApplication.class, arg);
    }
    

    总结

    1. 启动SpringBoot程序时,可以选择是否使用命令行属性为SpringBoot程序传递启动属性

    思考

    ​ 现在使用临时属性可以在启动项目前临时更改配置了,但是新的问题又出来了。临时属性好用是好用,就是写的多了会很麻烦。比如我现在有个需求,上线的时候使用临时属性配置20个值,这下可麻烦了,能不能搞得简单点,集中管理一下呢?比如说搞个文件,加载指定文件?还真可以。怎么做呢?

    配置文件分类

    ​ SpringBoot提供了配置文件和临时属性的方式来对程序进行配置。前面一直说的是临时属性,这一节要说说配置文件了。其实这个配置文件我们一直在使用,只不过我们用的是SpringBoot提供的4级配置文件中的其中一个级别。4个级别分别是:

    • 类路径下配置文件(一直使用的是这个,也就是resources目录中的application.yml文件)
    • 类路径下config目录下配置文件
    • 程序包所在目录中配置文件
    • 程序包所在目录中config目录下配置文件

    ​ 好复杂,一个一个说。其实上述4种文件是提供给你了4种配置文件书写的位置,功能都是一样的,都是做配置的。那大家关心的就是差别了,没错,就是因为位置不同,产生了差异。总体上来说,4种配置文件如果都存在的话,有一个优先级的问题,说白了就是加入4个文件我都有,里面都有一样的配置,谁生效的问题。上面4个文件的加载优先顺序为

    1. file :config/application.yml 【最高】
    2. file :application.yml
    3. classpath:config/application.yml
    4. classpath:application.yml 【最低】

    使用场景

    • 场景A:你作为一个开发者,你做程序的时候为了方便自己写代码,配置的数据库肯定是连接你自己本机的,咱们使用4这个级别,也就是之前一直用的application.yml。
    • 场景B:现在项目开发到了一个阶段,要联调测试了,连接的数据库是测试服务器的数据库,肯定要换一组配置吧。你可以选择把你之前的文件中的内容都改了,目前还不麻烦。
    • 场景C:测试完了,一切OK。你继续写你的代码,你发现你原来写的配置文件被改成测试服务器的内容了,你要再改回来。现在明白了不?场景B中把你的内容都改掉了,你现在要重新改回来,以后呢?改来改去吗?

    解决方案很简单,用上面的3这个级别的配置文件就可以快速解决这个问题,再写一个配置就行了。两个配置文件共存,因为config目录中的配置加载优先级比你的高,所以配置项如果和级别4里面的内容相同就覆盖了,这样是不是很简单?

    级别1和2什么时候使用呢?程序打包以后就要用这个级别了,管你程序里面配置写的是什么?我的级别高,可以轻松覆盖你,就不用考虑这些配置冲突的问题了。

    总结

    1. 配置文件分为4种
    • 项目类路径配置文件:服务于开发人员本机开发与测试
    • 项目类路径config目录中配置文件:服务于项目经理整体调控
    • 工程路径配置文件:服务于运维人员配置涉密线上环境
    • 工程路径config目录中配置文件:服务于运维经理整体调控
    1. 多层级配置文件间的属性采用叠加并覆盖的形式作用于程序

    自定义配置文件

    ​ 之前咱们做配置使用的配置文件都是application.yml,其实这个文件也是可以改名字的,这样方便维护。比如我2020年4月1日搞活动,走了一组配置,2020年5月1日活动取消,恢复原始配置,这个时候只需要重新更换一下配置文件就可以了。但是你总不能在原始配置文件上修改吧,不然搞完活动以后,活动的配置就留不下来了,不利于维护。

    ​ 自定义配置文件方式有如下两种:

    方式一:使用临时属性设置配置文件名,注意仅仅是名称,不要带扩展名

    image20211206105548238

    方式二:使用临时属性设置配置文件路径,这个是全路径名

    image20211206105716450

    ​ 也可以设置加载多个配置文件

    image20211206105750285

    ​ 使用的属性一个是spring.config.name,另一个是spring.config.location,这个一定要区别清楚。

    温馨提示

    ​ 我们现在研究的都是Spring Boot单体项目,就是单服务器版本。其实企业开发现在更多的是使用基于Spring Cloud技术的多服务器项目。这种配置方式和我们现在学习的完全不一样,所有的服务器将不再设置自己的配置文件,而是通过配置中心获取配置,动态加载配置信息。为什么这样做?集中管理。这里不再说这些了,后面再讲这些东西。

    总结

    1. 配置文件可以修改名称,通过启动参数设定
    2. 配置文件可以修改路径,通过启动参数设定
    3. 微服务开发中配置文件通过配置中心进行设置

    多环境开发

    ​ 讲的内容距离线上开发越来越近了,下面说一说多环境开发问题。

    ​ 什么是多环境?其实就是说你的电脑上写的程序最终要放到别人的服务器上去运行。每个计算机环境不一样,这就是多环境。常见的多环境开发主要兼顾3种环境设置,开发环境——自己用的,测试环境——自己公司用的,生产环境——甲方爸爸用的。因为这是绝对不同的三台电脑,所以环境肯定有所不同,比如连接的数据库不一样,设置的访问端口不一样等等。

    image20211206110958819

    多环境开发(yaml单一文件版)

    spring:
        profiles:
            active: pro        # 启动pro
    ---
    spring:
        profiles: pro
    server:
        port: 80
    ---
    spring:
        profiles: dev
    server:
        port: 81
    

    其中关于环境名称定义上述格式是过时格式,标准格式如下

    spring:
        config:
            activate:
                on-profile: pro
    

    总结

    1. 多环境开发需要设置若干种常用环境,例如开发、生产、测试环境
    2. yaml格式中设置多环境使用---区分环境设置边界
    3. 每种环境的区别在于加载的配置属性不同
    4. 启用某种环境时需要指定启动时使用该环境

    yaml多文件(掌握)

    主配置文件

    spring:
        profiles:
            active: pro        # 启动pro
    

    application-pro.yaml

    server:
        port: 80
    

    application-dev.yaml

    server:
        port: 81
    

    文件的命名规则为:application-环境名.yml。

    在配置文件中,如果某些配置项所有环境都一样,可以将这些项写入到主配置中,只有哪些有区别的项才写入到环境配置文件中。

    • 主配置文件中设置公共配置(全局)
    • 环境分类配置文件中常用于设置冲突属性(局部)

    总结

    1. 可以使用独立配置文件定义环境属性
    2. 独立配置文件便于线上系统维护更新并保障系统安全性

    properties多文件(了解)

    SpringBoot最早期提供的配置文件格式是properties格式的,这种格式的多环境配置也了解一下吧。

    主配置文件

    spring.profiles.active=pro
    

    环境配置文件

    application-pro.properties

    server.port=80
    

    application-dev.properties

    server.port=81
    

    文件的命名规则为:application-环境名.properties。

    总结

    1. properties文件多环境配置仅支持多文件格式

    多环境开发独立配置文件书写技巧

    ​ 作为程序员在搞配置的时候往往处于一种分久必合合久必分的局面。开始先写一起,后来为了方便维护就拆分。对于多环境开发也是如此,下面给大家说一下如何基于多环境开发做配置独立管理,务必掌握。

    准备工作

    ​ 将所有的配置根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

    • application-devDB.yml
    • application-devRedis.yml
    • application-devMVC.yml

    使用

    ​ 使用include属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔

    spring:
        profiles:
            active: dev
            include: devDB,devRedis,devMVC
    

    ​ 比较一下,现在相当于加载dev配置时,再加载对应的3组配置,从结构上就很清晰,用了什么,对应的名称是什么

    注意:
    当主环境dev与其他环境有相同属性时,主环境属性生效;其他环境中有相同属性时,最后加载的环境属性生效

    改良

    SpringBoot从2.4版开始使用group属性替代include属性,降低了配置书写量。简单来说就是都写好所以的配置,用哪个就选择哪个。

    spring:
        profiles:
            active: dev  # 更换环境修改这里即可
            group:
                "dev": devDB,devRedis,devMVC
                  "pro": proDB,proRedis,proMVC
                  "test": testDB,testRedis,testMVC
    

    总结

    1. 多环境开发使用group属性设置配置文件分组,便于线上维护管理

    多环境开发控制

    maven和SpringBoot同时设置多环境会产生冲突。

    但是呢,maven是做什么的?项目构建管理的,最终生成代码包的,SpringBoot是干什么的?简化开发的。简化,又不是其主导作用。最终还是要靠maven来管理整个工程,所以SpringBoot应该听maven的。

    • 先在maven环境中设置用什么具体的环境
    • 在SpringBoot中读取maven设置的环境即可

    maven中设置多环境(使用属性方式区分环境)

    <profiles>
        <profile>
            <id>env_dev</id>
            <properties>
                <profile.active>dev</profile.active>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>        <!--默认启动环境-->
            </activation>
        </profile>
        <profile>
            <id>env_pro</id>
            <properties>
                <profile.active>pro</profile.active>
            </properties>
        </profile>
    </profiles>
    

    SpringBoot中读取maven设置值

    spring:
        profiles:
            active: @profile.active@
    

    ​ 上面的@属性名@就是读取maven中配置的属性值的语法格式。

    总结

    1. 当Maven与Spring Boot同时对多环境进行控制时,以Maven为主,Spring Boot使用@..@占位符读取Maven对应的配置属性值
    2. 基于Spring Boot读取Maven配置属性的前提下,如果在Idea下测试工程时pom.xml每次更新需要手动compile方可生效

    日志

    • 编程期调试代码
    • 运营期记录信息
    • 记录日常运营重要信息(峰值流量、平均响应时长……)
    • 记录应用报错信息(错误堆栈)
    • 记录运维过程数据(扩容、宕机、报警……)

    代码中使用日志工具记录日志

    ​ 日志的使用格式非常固定,直接上操作步骤:

    步骤①:添加日志记录操作

    @RestController
    @RequestMapping("/books")
    public class BookController extends BaseClass{
        private static final Logger log = LoggerFactory.getLogger(BookController.class);
        @GetMapping
        public String getById(){
            log.debug("debug...");
            log.info("info...");
            log.warn("warn...");
            log.error("error...");
            return "springboot is running...2";
        }
    }
    

    ​ 上述代码中log对象就是用来记录日志的对象,下面的log.debug,log.info这些操作就是写日志的API了。

    步骤②:设置日志输出级别

    ​ 日志设置好以后可以根据设置选择哪些参与记录。这里是根据日志的级别来设置的。日志的级别分为6种,分别是:

    • TRACE:运行堆栈信息,使用率低
    • DEBUG:程序员调试代码使用
    • INFO:记录运维过程数据
    • WARN:记录运维过程报警数据
    • ERROR:记录错误堆栈信息
    • FATAL:灾难信息,合并计入ERROR

    ​ 一般情况下,开发时候使用DEBUG,上线后使用INFO,运维信息记录使用WARN即可。下面就设置一下日志级别:

    # 开启debug模式,输出调试信息,常用于检查系统运行状况
    debug: true
    

    ​ 这么设置太简单粗暴了,日志系统通常都提供了细粒度的控制

    # 开启debug模式,输出调试信息,常用于检查系统运行状况
    debug: true
    
    # 设置日志级别,root表示根节点,即整体应用日志级别
    logging:
        level:
            root: debug
    

    ​ 还可以再设置更细粒度的控制

    步骤③:设置日志组,控制指定包对应的日志输出级别,也可以直接控制指定包对应的日志输出级别

    logging:
        # 设置日志组
        group:
            # 自定义组名,设置当前组中所包含的包
            ebank: com.itheima.controller
        level:
            root: warn
            # 为对应组设置日志级别
            ebank: debug
            # 为对包设置日志级别
            com.itheima.controller: debug
    

    ​ 说白了就是总体设置一下,每个包设置一下,如果感觉设置的麻烦,就先把包分个组,对组设置,没了,就这些。

    总结

    1. 日志用于记录开发调试与运维过程消息
    2. 日志的级别共6种,通常使用4种即可,分别是DEBUG,INFO,WARN,ERROR
    3. 可以通过日志组或代码包的形式进行日志显示级别的控制

    优化日志对象创建代码

    ​ 写代码的时候每个类都要写创建日志记录对象,这个可以优化一下,使用前面用过的lombok技术给我们提供的工具类即可。

    @RestController
    @RequestMapping("/books")
    public class BookController extends BaseClass{
        private static final Logger log = LoggerFactory.getLogger(BookController.class);    //这一句可以不写了
    }
    

    ​ 导入lombok后使用注解搞定,日志对象名为log

    @Slf4j        //这个注解替代了下面那一行
    @RestController
    @RequestMapping("/books")
    public class BookController extends BaseClass{
        private static final Logger log = LoggerFactory.getLogger(BookController.class);    //这一句可以不写了
    }
    

    总结

    1. 基于lombok提供的@Slf4j注解为类快速添加日志对象

    日志输出格式控制

    ​ 日志已经能够记录了,但是目前记录的格式是SpringBoot给我们提供的,如果想自定义控制就需要自己设置了。先分析一下当前日志的记录格式。

    ![image20211206123431222](file:///D:/BaiduNetdiskDownload/Spring Boot/运维实用篇-资料/讲义/img/image-20211206123431222.png)

    对于单条日志信息来说,日期,触发位置,记录信息是最核心的信息。级别用于做筛选过滤,PID与线程名用于做精准分析。了解这些信息后就可以DIY日志格式了。本课程不做详细的研究,有兴趣的小伙伴可以学习相关的知识。下面给出课程中模拟的官方日志模板的书写格式,便于大家学习。

    logging:
        pattern:
            console: "%d %clr(%p) --- [%16t] %clr(%-40.40c){cyan} : %m %n"
    

    总结

    1. 日志输出格式设置规则

    日志文件

    ​ 日志信息显示,记录已经控制住了,下面就要说一下日志的转存了。日志不能仅显示在控制台上,要把日志记录到文件中,方便后期维护查阅。

    ​ 对于日志文件的使用存在各种各样的策略,例如每日记录,分类记录,报警后记录等。这里主要研究日志文件如何记录。

    ​ 记录日志到文件中格式非常简单,设置日志文件名即可。

    logging:
        file:
            name: server.log
    

    ​ 虽然使用上述格式可以将日志记录下来了,但是面对线上的复杂情况,一个文件记录肯定是不能够满足运维要求的,通常会每天记录日志文件,同时为了便于维护,还要限制每个日志文件的大小。下面给出日志文件的常用配置方式:

    logging:
        logback:
            rollingpolicy:
                max-file-size: 3KB
                file-name-pattern: server.%d{yyyy-MM-dd}.%i.log
    

    ​ 以上格式是基于logback日志技术设置每日日志文件的设置格式,要求容量到达3KB以后就转存信息到第二个文件中。文件命名规则中的%d标识日期,%i是一个递增变量,用于区分日志文件。

    总结

    1. 日志记录到文件
    2. 日志文件格式设置
  • 相关阅读:
    ROSS仿真系统简单教程
    python小练习1.1
    c语言文件I/O 文件读取和写入
    Python 学习笔记 多线程-threading
    parsec(The parsec benchmark suit )使用教程
    Checkpoint/Restore In Userspace(CRIU)使用细节
    Checkpoint/Restore in Userspace(CRIU)安装和使用
    考研总结
    北理计算机复试经验
    PAT(A) 1075. PAT Judge (25)
  • 原文地址:https://www.cnblogs.com/RioTian/p/15907932.html
Copyright © 2020-2023  润新知