springboot第53集:微服务分布式架构,docker-compose,Prometheus,...

程序源代码

共 16865字,需浏览 34分钟

 · 2024-04-10

从0搭建一套Prometheus监控体系

简介:

Prometheus是一款开源监控系统,起源于SoundCloud的警告工具包。自2012年以来,许多公司和组织开始广泛采用Prometheus。该项目具有活跃的开发人员和用户社区,吸引越来越多的参与者。如今,Prometheus已经成为一个独立的开源项目,摆脱了对任何特定公司的依赖。为了强调这一点并明确项目的治理结构,Prometheus在2016年加入了Cloud Native Computing Foundation,成为继Kubernetes之后的又一个成员。

主要特点:

  • 采用多维数据模型,其中时序由指标名称和键/值标签构成。
  • 支持灵活的查询语言(PromQL)。
  • 无依赖存储,支持本地和远程多种模型。
  • 使用HTTP协议,采用拉取模式,简单易于理解。
  • 监控目标可通过服务发现或静态配置的方式实现。
  • 支持多种统计数据模型,图形化友好。

前言:

  • 通常情况下,Prometheus采用二进制安装,以提高自定义性。
  • 随着云服务时代的发展,使用Docker部署的用户不断增加。
  • 两种安装方式,以满足不同场景下的选择需求。

node-exporter采用go语言开发,专门用来收集Linux系统中硬件、系统指标。既可以用二进制安装部署,也可以通过容器形式部署

mysql_exporter是用来收集MysQL或者Mariadb数据库相关指标的,mysql_exporter需要连接到数据库并有相关权限。既可以用二进制安装部署,也可以通过容器形式部署

docker-compose
      
      //指定版本安装:
$ sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.23.1/\
docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

//对二进制文件赋可执行权限
$ sudo chmod +x /usr/local/bin/docker-compose
      
      $ yum -y install docker-compose
      
      $ docker-compose --version
docker-compose version 1.23.1, build 1719ceb
      
      [root@localhost /]# java -version
openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)
      
      [root@localhost /]# rpm -qa | grep java
python-javapackages-3.4.1-11.el7.noarch
java-1.8.0-openjdk-headless-1.8.0.161-2.b14.el7.x86_64
tzdata-java-2018c-1.el7.noarch
java-1.7.0-openjdk-1.7.0.171-2.6.13.2.el7.x86_64
java-1.8.0-openjdk-1.8.0.161-2.b14.el7.x86_64
javapackages-tools-3.4.1-11.el7.noarch
java-1.7.0-openjdk-headless-1.7.0.171-2.6.13.2.el7.x86_64
      
      [root@localhost /]# rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.161-2.b14.el7.x86_64
[root@localhost /]# rpm -e --nodeps java-1.8.0-openjdk-1.8.0.161-2.b14.el7.x86_64
[root@localhost /]# rpm -e --nodeps java-1.7.0-openjdk-1.7.0.171-2.6.13.2.el7.x86_64
[root@localhost /]# rpm -e --nodeps java-1.7.0-openjdk-headless-1.7.0.171-2.6.13.2.el7.x86_64

[安装JDK]

上传新的jdk-8u191-linux-x64.rpm软件到/usr/local/src/执行以下操作:

      
      [root@localhost src]# rpm -ivh jdk-8u191-linux-x64.rpm 
警告:jdk-8u191-linux-x64.rpm: 头V3 RSA/SHA256 Signature, 密钥 ID ec551f03: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:jdk1.8-2000:1.8.0_191-fcs        ################################# [100%]
Unpacking JAR files...
    tools.jar...
    plugin.jar...
    javaws.jar...
    deploy.jar...
    rt.jar...
    jsse.jar...
    charsets.jar...
    localedata.jar...
[root@localhost src]# java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
      
      [root@localhost src]# java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
      
      [root@localhost src]# vi /etc/profile
      
      JAVA_HOME=/usr/java/jdk1.8.0_191-amd64
JRE_HOME=/usr/java/jdk1.8.0_191-amd64/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH
      
      [root@localhost /]# source /etc/profile
[root@localhost /]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/java/jdk1.8.0_191-amd64/bin:/usr/java/jdk1.8.

安装新版mysql之前,我们需要将系统自带的mariadb-lib卸载

      
      [root@master ~]# rpm -qa|grep mariadb
mariadb-libs-5.5.41-2.el7_0.x86_64
[root@master ~]# rpm -e mariadb-libs-5.5.41-2.el7_0.x86_64 --nodeps

接下来是初始化数据库,我们使用如下命令均可

      
      [root@master~]# mysqld --initialize 

新版的推荐此方法,执行生会在/var/log/mysqld.log生成随机密码

更改mysql数据库目录的所属用户及其所属组,然后启动mysql数据库

      
      [root@master~]# chown mysql:mysql /var/lib/mysql -R
[root@master~]# systemctl start mysqld.service  
      
      [root@master~]# cat /var/log/mysqld.log | grep 'password'
      
      [root@master~]# service mysqld restart
[root@master~]# mysql -u root -p
      
      $ sudo yum remove docker
      
      $ sudo yum remove docker \
                  docker-common \
                  docker-selinux \
                  docker-engine
      
      yum --version
3.4.3
  Installed: rpm-4.11.3-43.el7.x86_64 at 2020-09-03 03:49
  Built    : CentOS BuildSystem <http://bugs.centos.org> at 2020-04-01 04:21
  Committed: Panu Matilainen <pmatilai@redhat.com> at 2019-10-04

  Installed: subscription-manager-1.24.51-1.el7.centos.x86_64 at 2023-05-27 04:39
  Built    : CentOS BuildSystem <http://bugs.centos.org> at 2022-05-18 15:54
  Committed: Christopher Snyder <csnyder@redhat.com> at 2022-04-18

  Installed: yum-3.4.3-167.el7.centos.noarch at 2020-09-03 03:49
  Built    : CentOS BuildSystem <http://bugs.centos.org> at 2020-04-02 15:56
  Committed: CentOS Sources <bugs@centos.org> at 2020-03-31

  Installed: yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch at 2020-09-03 03:49
  Built    : CentOS BuildSystem <http://bugs.centos.org> at 2020-05-12 16:27
  Committed: Michal Domonkos <mdomonko@redhat.com> at 2020-03-12

安装 yum-utils , 这样就能使用 yum-config-manager 工具设置 Yum 源。

      
      $ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

执行以下命令,添加 Docker 的 Yum 源。

      
      $ sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
      
      $ sudo yum-config-manager --enable docker-ce-edge
      
      $ sudo yum-config-manager --enable docker-ce-test

如想要禁用测试仓库,可执行以下命令:

      
      $ sudo yum-config-manager --disable docker-ce-edge
      
      $ sudo yum makecache fast
      
      $ sudo yum install docker-ce

在生产系统中,可能需要安装指定版本的 Docker ,而并不总是安装最新的版本。

执行以下命令,即可列出可用的 Docker 版本

      
      $ yum list docker-ce --showduplicates | sort -r

列出 Docker 版本后,可使用以下命令安装指定版本的 Docker 。

      
      $ sudo yum install 
      
      $ sudo yum -y install docker-ce-17.09.0.ce
      
      $ sudo docker run hello-world
      
      docker version

卸载 Docker 软件包

      
      $ sudo yum remove docker-ce

如需删除镜像、容器、卷以及自定义的配置文件,可执行以下命令

      
      $ sudo rm -rf /var/lib/docker
      
      InputStream isTrustCa = HttpRequestTest.class.getResourceAsStream("/cert/ca.jks");
InputStream isSelfCert = HttpRequestTest.class.getResourceAsStream("/cert/outgoing.CertwithKey.pkcs12");

KeyStore selfCert = KeyStore.getInstance("pkcs12");
selfCert.load(isSelfCert, "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
kmf.init(selfCert, "password".toCharArray());
KeyStore caCert = KeyStore.getInstance("jks");
caCert.load(isTrustCa, "caPassword".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
tmf.init(caCert);
SSLContext sc = SSLContext.getInstance("TLS");

TrustManager[] trustManagers = tmf.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
sc.init(kmf.getKeyManagers(), trustManagers, (SecureRandom) null);

// 1. 全局配置证书
OkHttpClient.Builder builder = new OkHttpClient.Builder()
    .sslSocketFactory(sc.getSocketFactory(), trustManager)
    .hostnameVerifier(TrustAllHostNames.INSTANCE);
HttpRequest.setHttpClient(builder.build());

// 2. 单次请求配置证书
HttpRequest.get("https://123.xxx")
    .useConsoleLog(LogLevel.BODY)
    .sslSocketFactory(sc.getSocketFactory(), trustManager)
    .disableSslValidation()
    .execute()
    .asString();
mqtt

控制报文中的文本字段编码为UTF-8格式的字符串。UTF-8  是一个高效的Unicode字符编码格式,为了支持基于文本的通信,它对ASCII字符的编码做了优化。

每一个字符串都有一个两字节的长度字段作为前缀,它给出这个字符串UTF-8编码的字节数

MQTT控制报文

ef4d42471e81924211daabe23cbdc065.webpimage.png 8fff52edc072eefe4b7b16d39cf40c2b.webpimage.png 9e458ebae4218d19c6c369982e9543a3.webpimage.png 4430d790a6d980671091fc70c72de8c0.webpimage.png d737323e3150d809af0da66616cc9433.webpimage.png

homebrew 和 npm 的区别?

  1. homebrew,可以理解成 macOS 的软件管理工具,粗俗点说就是 mac 界的 qq 软件助手之类的东西。所以通过 brew,安装什么 chrome浏览器啊、atom 编辑器之类的可视化工具也是可以的。
  2. npm,是 node.js 界的程序/模块管理工具,也就是说 npm 只管理那些服务于 JavaScript 社区的程序。而且跨平台,windows 和 macOS,以及其他类 unix 操作系统都可以用。
  3. npm是用于 NodeJS 语言的包管理器,NodeJS 是跨平台的;而 homebrew 是用于OS X系统的包管理器,类似Windows的各种软件管理工具(所谓XX软件市场之类)和Linux的apt-get/yum/pacman等。
  4. npm 是 node.js 的包管理工具,只要有 node 环境,不管是 windows, macOS, 还是 linux 都可以使用 npm 下载模块,brew 是 mac 的包管理工具,只有 macOS 上才有。
  5. Webstorm IntelliJ Darcula Theme (主题插件,提供和 Webstorm一样的字体和主题)
  6. 小霸王(通过类似 webview 形式嵌套提供各种小游戏,如魂斗罗、坦克大战等)
  7. 韭菜盒子(VSCode 里也可以看股票 & 基金 & 期货实时数据,做最好用的投资插件。)
  8. Live Host (快速编辑 host 文件、每日获取最佳 github ip 解决 DNS 污染问题。)
  9. Live Server(快速启动一个端口服务)
  10. git blame(可以快速的查看某一行最近的一次修改是谁、什么时候、哪次提交修改的)
  11. git graph(可以进行版本管理,比如pull、push、修改比较、log、merge)
  12. gitlens (在vscode中使用git必备插件,功能非常强大)
  13. filesize(在底部显示当前文件到大小)

这行代码定义了一个静态的日志记录器(Logger)变量,使用 SLF4J(Simple Logging Facade for Java)接口,并通过 LoggerFactory 获取 Logger 的实例。这是一种常见的在 Java 项目中使用日志的方式。

  • static: 这个变量是静态的,属于类而不是类的实例。静态变量在类加载时初始化,并且在整个应用程序的生命周期内保持不变。
  • Logger logger: 这是日志记录器的声明,类型是 Logger
  • LoggerFactory.getLogger(GPSPosInfo.class): 通过 LoggerFactory 工厂类的 getLogger 方法,获取一个 Logger 实例。传递的参数是类 GPSPosInfo.class,这样在日志中就可以标识出日志消息是从哪个类输出的。

在使用 SLF4J 进行日志记录时,常用的日志级别包括 DEBUG、INFO、WARN、ERROR。你可以使用这个 logger 对象记录不同级别的日志

ObjectUtils.nullSafeEquals 是 Spring Framework 提供的一个用于比较两个对象是否相等的方法。它考虑了对象为 null 的情况,避免了在比较过程中出现空指针异常。

@NoArgsConstructor@AllArgsConstructor 是 Lombok 提供的注解,用于自动生成类的无参构造方法和全参构造方法。

  1. @NoArgsConstructor: 自动生成无参构造方法。使用这个注解的类会在编译时生成一个默认的无参构造方法,无需手动编写。
  2. @AllArgsConstructor: 自动生成全参构造方法。使用这个注解的类会在编译时生成一个包含所有成员变量的全参构造方法,无需手动编写。

@ToString 是 Lombok 提供的注解之一,用于自动生成类的 toString() 方法。它会自动按照类的字段生成一个格式化的字符串,用于方便地输出对象的内容。

创建一个 JedisConnectionFactory 对象,然后通过一系列的设置为该连接工厂配置连接信息,如主机名、端口、密码、数据库等。接着,配置了连接池相关的参数,包括最大空闲数、最小空闲数、最大连接数、最大等待时间等。

注解 @EqualsAndHashCode,并通过 callSuper = true 参数指定了在生成 equalshashCode 方法时调用父类的相应方法。

      
      logger.debug("This is a debug message");
logger.info("This is an info message");
logger.warn("This is a warning message");
logger.error("This is an error message");

  1. 空值检查: 在处理数据之前进行空值检查,确保数据的完整性。
  2. 方法拆分: 将长方法拆分成更小的方法,提高代码的可读性和可维护性。
  3. Lambda 表达式: 使用 Lambda 表达式和方法引用来简化集合处理。
  4. 常量定义: 将一些常量值提取为静态常量,提高代码的可维护性。
  5. 异常处理: 添加适当的异常处理机制,确保代码的健壮性。
  6. 可配置参数: 将一些硬编码的参数提取为可配置的参数,使得代码更具灵活性。

在 Vue 3 中,watch 选项提供了 flush 选项,你可以使用 flush: 'sync' 来确保在组件初始化时立即执行一次监听函数

  1. findFirst
  • 获取第一个匹配的结果。如果没有找到匹配项,它将返回一个空的 Optional
orElse("")
  • 如果 Optional 为空(表示没有找到匹配项),则返回一个空字符串 ("")。

!CollectionUtils.isEmpty

是否不为空,以避免空指针异常。

  1. Lambda 表达式:
  • 简洁性和可读性: 使用Lambda表达式可以减少冗余的代码,使代码更为简洁,同时提高可读性。在这种情况下,通过Lambda表达式替代了匿名内部类,使得线程的创建过程更为清晰。
  • 优雅的函数式编程风格: Lambda表达式是Java对函数式编程支持的一部分,能够在一些场景中实现更优雅的函数式编程风格。
CompletableFuture:
  • 异步执行: CompletableFuture 提供了更为强大和灵活的异步执行机制。通过CompletableFuture.runAsync方法,可以在后台异步执行任务,而无需手动创建线程。
  • 更好的可组合性: CompletableFuture 支持将多个异步操作组合在一起,形成更为复杂的异步操作流。这使得代码更易于组织和维护。
      
      CompletableFuture.runAsync(() -> {
    
})
  1. 更具体的类型:
  • 将方法的返回类型更改为 List<Map<String, Object>>,以便更清晰地表达返回值的类型。
使用更具描述性的变量名:
  • 修改变量名 page2 为更具描述性的 page,以提高代码的可读性。
异常处理:
  • 代码中没有对远程调用结果和 JSON 解析结果的异常进行处理。在实际代码中,你可能需要进一步处理这些异常,例如打印日志、抛出自定义异常或者根据业务需要进行其他处理。
避免 null 的返回:
  • 在解析 Feign 调用结果的过程中,对 null 进行了检查,以避免可能的空指针异常。
合并返回语句:
  • 将最后的返回语句合并,使得代码更为紧凑。

// 使用 TypeToken 来获取泛型类型

  1. 使用 Objects.isNull
  • 使用 Objects.isNull 来检查对象是否为空,这是 Java 7 引入的方法,避免了手动比较 == null
使用 StrUtil.isNotBlank
  • 使用 StrUtil.isNotBlank 方法来判断字符串不为空,这比直接使用 !StringUtils.isEmpty 更为简洁。

使用 Optional.ofNullable 以避免 null 值引发的空指针异常。

使用 map 获取 对象中的 属性。为 null,整个链式调用将返回 Optional.empty()

如果前面的链式调用中存在 null 值,使用 orElse(null) 提供默认值为 null

使用 ObjectUtils.nullSafeEquals 检查 locate 是否与已定位枚举的代码相等。

  1. distinct()
  • 使用 distinct 进行去重,确保列表中的值是唯一的。
.collect(Collectors.toList())
  • 使用 collect 收集结果为列表。

collect(Collectors.toList()) 是 Java 8 中 Stream API 提供的一个方法,它用于将流中的元素收集到一个列表中。

      
      public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略 getter 和 setter 方法
}

使用 Optional.ofNullable 包装 ,以避免可能的 null 引用异常。

使用 map 操作将可能为 null 的值转换为字符串表示。如果值为 null,则整个链式调用返回一个空的 Optional

  1. .map(Objects::toString)
  • 使用 map 操作将可能为 null 的值转换为字符串表示。如果值为 null,则整个链式调用返回一个空的 Optional
.map(Long::parseLong)
  • 使用 map 操作将字符串表示的时间戳转换为 Long 类型。如果值为 null 或无法解析为 Long,则整个链式调用返回一个空的 Optional
.orElse(0L)
  • 使用 orElse 操作提供一个默认值,如果整个链式调用返回空的 Optional,则返回默认值 0L

BatteryInfoBO.builder()

  • @Builder 注解会在编译时为带有该注解的类生成一个建造者模式的构造器。
  • builder() 是 Lombok 自动生成的静态方法,返回一个构造者对象,你可以使用这个构造者对象设置属性,并最终调用 build() 方法构建对象。
      
      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4JDefaulting to no-operation (NOPlogger implementation
SLF4JSee http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
An error occurredThis is an example exception.
Exception in thread "mainjava.lang.RuntimeExceptionThis is an example exception.
    at ExampleClass.main(ExampleClass.java:10)
  1. 日志体系的抽象logger 是 SLF4J 或其他日志门面的通用接口,而 log 可能指代不同的日志框架(例如 Log4j、Java Util Logging 等)。使用 logger 提供了更高的抽象,使得你可以在不更改代码的情况下切换底层的日志实现。
  2. SLF4J 的性能:SLF4J 提供了一种将日志语句延迟计算的机制,只有在达到适当的日志级别时才计算日志语句的值。这种延迟计算的机制在性能上有一些优势,因为它可以避免不必要的字符串拼接。
  3. 日志级别的判断:SLF4J 支持更多的日志级别(例如 TRACE),而 log 通常使用简单的几个级别(例如 DEBUG、INFO、WARN、ERROR)。使用 logger 可以提供更多的日志级别选项。
  4. 参数化日志:SLF4J 提供了参数化日志的机制,可以有效避免手动拼接字符串。这有助于提高代码的可读性和维护性。
      
      @Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

加群联系作者vx:xiaoda0423

仓库地址:https://github.com/webVueBlog/JavaGuideInterview

浏览 3
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报