SpringBoot整合Graylog做日志收集

news2024/11/28 10:55:53

日志收集折腾过程

ELK

之前整合过ELK做日志采集,就是Elasticsearch + Logstash + Kibana:

  • Elasticsearch:存储引擎,存放日志内容,利于全文检索
  • Logstash:数据传输管道,将日志内容传输到Elasticsearch,并且支持过滤内容,将内容格式化后再传输,可以满足绝大部分的应用场景
  • Kibana:开源的分析和可视化平台,在这里查看Elasticsearch中的数据

对我来说ELK有点重,服务占用资源高,并且部署和维护有些复杂,我的个人服务器玩这个有点力不从心,所以一直有在寻找替代方案。

EFK

Elasticsearch + Filebeat + Kibana,用Filebeat替代Logstash做日志的收集,它是由Golang开发,够轻量,占用资源少,如果没有过滤日志内容进行格式化的需求,用这个替代Logstash是很不错的选择。

ELFK

四个框架全用,网上看到有大佬这样用,应该是企业级别的部署,看着我就敬而远之,不敢玩。

自己撸一个

我对EFK的服务占用感到不满,于是自己用Golang写了一个轻量级工具,没有做采集、过滤,仅仅是从日志文件夹中grep出想要的内容,其实和手动grep没区别,不过可以用接口的方式查出想要的内容,而且极其轻量,这个工具我还用过好一段时间。

我把EFK的搭建过程和手撸工具的过程写在了这里,感兴趣可以去看看。

Spring Boot日志收集以及链路追踪

Graylog

最近我在折腾另一个日志收集方案,并且感觉不错,就是Graylog,它需要整合Mongo + Elasticsearch,它比较简单易用,提供网页端可视化页面,相当于Kibana,还支持日志报警。

值得说明的是,它支持处理多行日志,而在ELK中,多行日志需要用Logstash做一些格式化配置,这一点来说Graylog就做的很棒。

至于为什么需要整合Mongo,是因为需要借助Mongo来保存一些Graylog的配置信息。

环境搭建

我喜欢用Docker来搭建环境,所以如果你通过其他方式,可以到官网寻求答案

首先拉取一下镜像:

docker pull elasticsearch:7.12.0
​
docker pull graylog/graylog:4.3.6
​
docker pull mongo:4.2
复制代码

docker-compose.yml:

version: '3'
services:
  mongo:
    image: mongo:4.2
    container_name: mongo # graylog内默认连接名为mongo,所以这个不建议改
    restart: always
    volumes:
      - /home/mycontainers/mongo/data:/data/db # 路径映射
    ports:
      - 27017:27017
    network_mode: mynetwork # 设置网段
  elasticsearch:
    image: elasticsearch:7.12.0
    container_name: elasticsearch # graylog内默认连接名为elasticsearch,所以不建议改
    environment:
      - "TAKE_FILE_OWNERSHIP=true" # 挂载目录需要这个,不然没有权限
      - "discovery.type=single-node"    # 设置为单节点,集群就等进阶再说了
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"    # 分配堆大小
    volumes:
      - /home/mycontainers/es/data:/usr/share/elasticsearch/data
      - /home/mycontainers/es/logs:/usr/share/elasticsearch/logs
    ulimits: # 调整 ulimits 以及 nprocedit
      memlock:
        soft: -1
        hard: -1
    deploy:
      resources:
        limits:
          memory: 1g # 限制使用内存
    ports:
      - 9200:9200
      - 9300:9300
    network_mode: mynetwork
  graylog:
    image: graylog/graylog:4.3.6
    container_name: graylog
    environment:
      # echo -n "Enter Password: " && head -1 < /dev/stdin | tr -d '\n' | sha256sum | cut -d " " -f1
      - GRAYLOG_PASSWORD_SECRET=somepasswordpepper  # 用于密码加密加盐
      - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 # 密码,默认是admin,可以用上面的echo命令生成自己的密码
      - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9009/    # 对外开放的链接,注意端口,我改成了9009
    # volumes:
      # - /home/mycontainers/graylog/config/graylog.conf:/usr/share/graylog/data/config/graylog.conf
    network_mode: mynetwork
    restart: always
    depends_on:
      - mongo # 依赖于mongo和es两个环境
      - elasticsearch
    ports:
      - 9009:9000 # 端口映射
      # Syslog TCP
      - 1514:1514
      # Syslog UDP
      - 1514:1514/udp
      # GELF TCP
      - 12201:12201
      # GELF UDP
      - 12201:12201/udp
复制代码

执行运行命令:

docker-compose -f docker-compose.yml up
复制代码

但有时候,我们在之前就已经部署好了Mongo和ES环境,所以不会在一个docker-compose文件中配置三个环境,我们把内容拆开如下:

es.yml:

version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.12.0
    container_name: elasticsearch # graylog内默认连接名为elasticsearch,所以不建议改
    environment:
      - "TAKE_FILE_OWNERSHIP=true"
      - "discovery.type=single-node"
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - /etc/localtime:/etc/localtime
      - /home/mycontainers/es/data:/usr/share/elasticsearch/data
      - /home/mycontainers/es/logs:/usr/share/elasticsearch/logs
    ulimits: # 调整 ulimits 以及 nprocedit
      memlock:
        soft: -1
        hard: -1
    deploy:
      resources:
        limits:
          memory: 1g # 限制使用内存
    ports:
      - 9200:9200
      - 9300:9300
    network_mode: mynetwork
复制代码

mongo.yml:

version: '3'
services:
  mongo:
    image: mongo:4.2
    container_name: mongo # graylog内默认连接名为mongo,所以这个不建议改
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime
      - /home/mycontainers/mongo/data:/data/db
    ports:
      - 27017:27017
    network_mode: mynetwork
复制代码

graylog.yml:

version: '3'
services:
  graylog:
    image: graylog/graylog:4.3.6
    container_name: graylog
    environment:
      # echo -n "Enter Password: " && head -1 < /dev/stdin | tr -d '\n' | sha256sum | cut -d " " -f1
      - GRAYLOG_PASSWORD_SECRET=somepasswordpepper
      - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
      - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9009/
      - GARYLOG_ELASTICSEARCH_HOSTS=http://elasticsearch:9200 # 链接es,这里是容器间通讯,所以写容器名
      - GRAYLOG_MONGODB_URI=mongodb://mongo:27017/graylog # 同上
    volumes:
      - /home/mycontainers/graylog/config/graylog.conf:/usr/share/graylog/data/config/graylog.conf # 指定配置文件,用于修改时区
    network_mode: mynetwork
    restart: always
    ports:
      - 9009:9000
      # Syslog TCP
      - 1514:1514
      # Syslog UDP
      - 1514:1514/udp
      # GELF TCP
      - 12201:12201
      # GELF UDP
      - 12201:12201/udp
复制代码

不同点在于手动配置mongo和es,还有多了一个配置文件映射,因为graylog默认UTC时区,我们的日志文件会相差8小时,所以在第一次启动成功graylog后,我们把它的配置文件拷贝出来,修改里面的root_timezone参数,再映射回去即可。

创建输入

现在我们可以访问Graylog了:http://xxx:9009

来创建一个输入:

勾选Global,Title随便写一个,其他不用改,保存即可,就能得到:

回到Search标签页,等日志文件输入即可。

Spring Boot整合Graylog

Maven依赖:

<!--graylog日志依赖-->
<dependency>
    <groupId>de.siegmar</groupId>
    <artifactId>logback-gelf</artifactId>
    <version>3.0.0</version>
</dependency>
复制代码

然后是logback的配置,这个根据需要使用就好,在resource中:

logback-spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--解决在项目目录中生成LOG_PATH_IS_UNDEFINED文件-->
    <property name="LOG_PATH" value="${LOG_PATH:-${java.io.tmpdir:-/logs}}"/>
    <!-- 引入SpringBoot的默认配置文件defaults.xml -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <!-- 引入SpringBoot中内置的控制台输出配置文件console-appender.xml -->
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    <!-- 引入自定义的文件输出配置文件logback-spring-file-level.xml -->
    <include resource="logback-spring-file-level.xml"/>
​
    <!-- 设置root logger的级别为INFO,并将控制台输出和文件输出中的appender都添加到root logger下 -->
    <root level="INFO">
        <!--没有这行,控制台将不会有输出,完全由日志进行输出-->
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="WARN_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="GELF"/>
    </root>
​
    <!-- jmx可以动态管理logback配置-->
    <jmxConfigurator/>
</configuration>
复制代码

logback-spring-file-level.xml:

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <!-- 从配置文件中读取-->
    <springProperty scope="context" name="APP_NAME" source="graylog.appName"/>
    <springProperty scope="context" name="GRAYLOG_HOST" source="graylog.host"/>
    <springProperty scope="context" name="GRAYLOG_PORT" source="graylog.port"/>
​
    <!--INFO Level的日志-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用来标记分割日志的序号 -->
            <fileNamePattern>${LOG_PATH}.INFO.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 单个日志文件最大maxFileSizeMB, 保存maxHistory天的历史日志, 所有日志文件最大totalSizeCapMB -->
            <!-- 经过试验,maxHistory是指指定天数内,而不是多少天-->
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <!-- 配置日志的级别过滤器,只保留INFO Level的日志-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 格式化输出-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{"yyyy-MM-dd HH:mm:ss.SSS"} %-5level -[%X{traceId}] - %msg%n</pattern>
        </encoder>
    </appender>
​
    <!--WARN Level的日志-->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用来标记分割日志的序号 -->
            <fileNamePattern>${LOG_PATH}.WARN.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 单个日志文件最大maxFileSizeMB, 保存maxHistory天的历史日志, 所有日志文件最大totalSizeCapMB -->
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--过滤级别-->
            <level>WARN</level>
            <!--onMatch:符合过滤级别的日志。ACCEPT:立即处理-->
            <onMatch>ACCEPT</onMatch>
            <!--onMismatch:不符合过滤级别的日志。DENY:立即抛弃-->
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{"yyyy-MM-dd HH:mm:ss.SSS"} %-5level -[%X{traceId}] - %msg%n</pattern>
        </encoder>
    </appender>
​
    <!--ERROR Level的日志-->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用来标记分割日志的序号 -->
            <fileNamePattern>${LOG_PATH}.ERROR.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 单个日志文件最大maxFileSizeMB, 保存maxHistory天的历史日志, 所有日志文件最大totalSizeCapMB -->
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
            <!--<cleanHistoryOnStart>true</cleanHistoryOnStart>-->
        </rollingPolicy>
        <!--对指定级别的日志进行过滤-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--过滤级别-->
            <level>ERROR</level>
            <!--onMatch:符合过滤级别的日志。ACCEPT:立即处理-->
            <onMatch>ACCEPT</onMatch>
            <!--onMismatch:不符合过滤级别的日志。DENY:立即抛弃-->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--日志输出格式-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{"yyyy-MM-dd HH:mm:ss.SSS"} %-5level - [%X{traceId}] - %msg%n</pattern>
        </encoder>
    </appender>
​
    <!--自定义日志-->
    <appender name="CUSTOM_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用来标记分割日志的序号 -->
            <fileNamePattern>${LOG_PATH}.MYLOGGER.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 单个日志文件最大maxFileSizeMB, 保存maxHistory天的历史日志, 所有日志文件最大totalSizeCapMB -->
            <!-- 经过试验,maxHistory是指指定天数内,而不是多少天-->
            <maxFileSize>300MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>300MB</totalSizeCap>
        </rollingPolicy>
        <!-- 配置日志的级别过滤器,只保留INFO Level的日志-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 格式化输出-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{"yyyy-MM-dd HH:mm:ss.SSS"}\t%X{traceId}\t%msg%n</pattern>
        </encoder>
    </appender>
    <!--自定义日志日志不用绑定在root下,只记录指定输出-->
    <logger name="my_logger" additivity="false">
        <appender-ref ref= "CUSTOM_FILE"/>
    </logger>
​
    <appender name="GELF" class="de.siegmar.logbackgelf.GelfUdpAppender">
        <!--graylog服务地址-->
        <graylogHost>${GRAYLOG_HOST}</graylogHost>
        <!--连接端口-->
        <graylogPort>${GRAYLOG_PORT}</graylogPort>
​
        <encoder class="de.siegmar.logbackgelf.GelfEncoder">
            <originHost>${APP_NAME:-demo}</originHost>
            <!--发送日志级别名称,默认以数字代表日志级别-->
            <includeLevelName>true</includeLevelName>
        </encoder>
    </appender>
</included>
复制代码

我们在logback中引用了配置文件的系统变量,所以在application.yml中要添加这一段,当然硬写进xml也可以:

application.yml

logging:
  file:
    path: _mylogs/${server.port}.logs # 日志保存路径
    
graylog:
  host: mylocalhost # graylog服务host
  port: 12201   # graylog服务端口
  appName: graylogDemo  # 应用名,可填
复制代码

启动Spring应用,打印几条日志:

@RestController
public class TestController {
    private static final Logger log = LoggerFactory.getLogger(TestController.class);
​
    @GetMapping("/i")
    public void info() {
        log.info("info...................");
    }
​
    @GetMapping("/w")
    public void warn() {
        log.warn("warn...................");
    }
​
    @GetMapping("/e")
    public void error() {
//        log.error("error...................");
        int i = 1/0;
//        LogUtil.error("自定义异常");
    }
}
复制代码

稍等片刻,顺利的话我们就能在Graylog中查看到刚刚输出的日志了,至此大功告成。

总结

本篇文章只是说明了Graylog的一个入门使用,进阶的玩法可能要后面才有时间整理了。

不管用什么方案做日志收集,我认为只要简单易用,稳定靠谱就好,ELK作为当前主流的日志收集框架,除了部署麻烦些,耗费资源高些之外并没有明显短板,所以ELK也好,Graylog也罢,只要适合自己就可以。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无法在Anaconda环境中使用pre-commit run --all-files:缺少匹配版本的ruamel.yaml

参考来源&#xff1a;https://stackoverflow.com/questions/68794749/unable-to-run-pre-commit-in-anaconda-environment 问题 与电脑两地隔离了半个月&#xff0c;今天开机commit的时候忽然弹出了下面的错误&#xff08;自己图忘存了&#xff0c;图源置顶链接&#xff09;&…

b站黑马的Vue快速入门案例代码——小黑记事本

目录 目标效果&#xff1a; 重点原理&#xff1a; &#xff08;1&#xff09;push&#xff08;&#xff09;方法——向数组末尾&#xff0c;添加新元素&#xff0c;并返回新长度 &#xff08;2&#xff09;v-on可以传递自定义参数&#xff0c;v-on:click”...“的简写是clic…

jdk11新特性——标准Java异步HTTP客户端

目录一、概述二、HTTP Client 同步发送请求使用示例2.1、创建简单的服务端2.2、创建HTTP Client 同步代码三、HTTP Client 异步发送请求使用示例3.1、创建简单的服务端&#xff08;参考2.1&#xff09;3.2、创建HTTP Client 异步代码一、概述 Java 9 开始引入的一个处理 HTTP …

浅谈ioremap,vmalloc,mmap三者之间的脉络

前言 系统mmu开启后, 程序对内存的访问都是虚拟地址, 之后mmu会自动将虚拟地址变为实际的物理地址&#xff08;硬件行为&#xff09;, 所以我们的程序如果要访问物理地址的话&#xff0c;必须要通过mmu建立虚拟地址与物理地址之间的映射关系。对于虚拟地址映射到物理地址的操作…

非零基础自学Golang 第7章 函数 7.6 延迟执行语句 7.7 小结

非零基础自学Golang 文章目录非零基础自学Golang第7章 函数7.6 延迟执行语句7.7 小结第7章 函数 7.6 延迟执行语句 Go语言中存在一种延迟执行的语句&#xff0c;由defer关键字标识&#xff0c;格式如下&#xff1a; defer 任意语句defer后的语句不会被马上执行&#xff0c;在…

Redis持久化详解

一、概述 在Redis中&#xff0c;实现高可用的技术主要包括持久化、复制、哨兵和集群&#xff0c;下面分别说明它们的作用&#xff0c;以及解决了什么样的问题。 持久化&#xff1a;持久化是最简单的高可用方法(有时甚至不被归为高可用的手段)&#xff0c;主要作用是数据备份…

springboot整合系列之如何选择版本及项目搭建

特别说明&#xff1a;本次项目整合基于idea进行的&#xff0c;如果使用Eclipse可能会略有不同。因为我很久没用过eclipse了&#xff0c;所以也没有办法给出两个版本。如果不一致的地方就自行google解决吧~~ springboot整合之如何选择版本及项目搭建 springboot整合mybatis-pl…

ADI Blackfin DSP处理器-BF533的开发详解52:图像处理专题-CMOS摄像头采集图像(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 板卡上设计了一个摄像头接口&#xff0c;可以连接与板卡匹配的 ADSP-EDU-CMOS 子卡板。摄像头接口采用 20PIN 插针接入&#xff0c;将插…

照片变漫画怎么做?分享这几个照片变漫画的技巧给你

大家在网上是否有看到过一些绘画博主给别人画漫画图呢&#xff1f;这些图片中的人物形象与现实中的非常相像&#xff0c;而且看起来真的很像漫画中的人物一般&#xff0c;画出来对于一些没有绘画功底的人来说是比较困难的。那么我们又该如何得到我们在漫画中的图片呢&#xff1…

四种常见排序(冒泡、选择、插入、快速排序)--- Python版

经典排序算法总结与实现 经典排序算法在面试中占有很大的比重&#xff0c;也是基础&#xff0c;为了未雨绸缪&#xff0c;这次收集整理并用Python实现了八大经典排序算法&#xff0c;包括冒泡排序&#xff0c;插入排序&#xff0c;选择排序&#xff0c;希尔排序&#xff0c;归…

Python实现批量采集美女视*频 <无水印>

前言 大家早好、午好、晚好吖 ❤ ~ 我给大家准备了一些资料&#xff0c;包括: 2022最新Python视频教程、Python电子书10个G &#xff08;涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题&#xff09;、Python学习路线图等等 直接在文末名片自取即可&#x…

机器学习还能预测心血管疾病?没错,我用 Python 写出来了

全球每年约有1700万人死于心血管疾病&#xff0c;当中主要表现为心肌梗死和心力衰竭。当心脏不能泵出足够的血液来满足人体的需要时&#xff0c;就会发生心力衰竭&#xff0c;通常由糖尿病、高血压或其他心脏疾病引起。 在检测心血管疾病的早期症状时&#xff0c;机器学习就能…

nodejs+vue企业固定资产管理系统-vscode

目 录 摘 要 I 目 录 III 第一章 概述 1.1研究背景 1.2 开发意义 1.3 研究现状 1.4 研究内容 1.5 论文结构 第二章 开发技术介绍 2.5 B/S架构 3.1 可行性分析 3.1.1技术可行性 3.1.2操作可行性 3.1.3 经济可行性 3.1.4 运行可行性 3.2性能需求分析 3.4功能分析 第四章 系统设计…

轻量级的架构决策记录机制

作者&#xff1a;倪新明 ADR是一种性价比非常高的架构决策文档化实践&#xff0c;团队引入和实践成本很低&#xff0c;却能为团队带来极大收益&#xff01; 1 团队研发面临的问题 不论是在传统的IT行业&#xff0c;还是互联网行业&#xff0c;研发团队在架构决策层面或多或少…

在Arduino IDE上开发ESP32(离线安装SDK)

用过Arduino的朋友都知道&#xff0c;Arduino的整个生态强大得让你不能不服。大家所贡献出来的各种库让基于Arduino的开发虽然还没有变得无所不能&#xff0c;但也算是相当得心应手了。你所能想到的功能大体都能在网上找到对应的库和文章。可能是因为这个原因吧&#xff0c;所以…

Redis整理-未完成

目录 1. Redis安装 1.1 单机 1.2 主从 1.3 哨兵 1.4 集群 1.4.1 方式一 redis-cli --cluster命令 1.4.2 方式二 cluster meet/addslots/replicate 2. Redis配置 2.1 基本参数配置 2.2 持久化配置 2.3 内存策略设置 2.4 主从配置 2.5 哨兵配置 2.6 集群配置 2.6.…

吃透这份 “ 自动化测试 ” 核心技术栈,月薪30K还不是随便叫

为了帮助大家快速回顾学习自动化测试中的知识点&#xff0c;分享一下这些年来&#xff0c;我对于技术一些归纳和总结&#xff0c;和自己对作为一名 高级测试工程师需要掌握那些技能的笔记分享&#xff0c;希望能帮助到有心在技术这条道路上一路走到黑的朋友&#xff01; 一、L…

[附源码]Python计算机毕业设计SSM基于JAVA快递配送平台(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

语音怎么转换成文字?这几个实用方法分享给你

当我们在听一些流行的英文歌曲时&#xff0c;发现它没有附带翻译的时候&#xff0c;是不是常常听不懂歌曲的意思内容呢&#xff1f;面对这种情况应该怎么办呢&#xff1f;其实也不难&#xff0c;我们只需要利用软件来将歌曲转换成文字的格式就可以了&#xff0c;那你们知道如何…

分布式系统(交互、协作)

文章目录进程组织进程交互传染病协议反熵&#xff08;Anti-Entropy&#xff09;闲聊&#xff08;Gossiping&#xff09;P2P 路由Circular routingPastry应用层多播ESMScribe中间件通信协议RPCMOM进程协作有序组播基本组播FIFO 组播全排序组播定序者分布式协商因果序组播分布式互…