Springboot整合Zipkin+kafka+ELK,实现链路追踪和日志收集

2023-11-05

背景

随着项目的深入,久不久可能出现些问题,但是查询起来又极其麻烦,线上有三台服务器,不知道报错日志在那台上,很麻烦。所以领导要求把项目的链路追踪和日志给统一输出到elk中,可以实现在elk查询。

Zipkin+Sleuth链路追踪

先来实现zipkin+sleuth链路追踪功能,至于zipkin+sleuth是什么不多累赘,自己网上查询。本人使用的自己搭建的zipkin项目,话不多说,直接上干货:

导入包

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
    <version>2.10.4</version>
    <exclusions>
        <exclusion>
            <artifactId>log4j-slf4j-impl</artifactId>
            <groupId>org.apache.logging.log4j</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
    <version>2.10.4</version>
</dependency>
<!-- 使用消息的方式收集数据(kafka) -->
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-collector-kafka</artifactId>
    <version>2.12.8</version>
</dependency>

<!-- 支持Elasticsearch 2.x - 6.x -->
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
    <version>2.8.4</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml文件配置

spring:
  application:
    name: zipkin
  # 收集粒度,1.0全部收集
  sleuth:
    sampler:
      percentage: 1.0
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: fc500383-342b-4d02-a9ce-5e87f2f58787
        heart-beat-timeout: 60
    stream:
      kafka:
        binder:
          brokers: localhost:9092
          zkNodes: localhost:2181
server:
  port: 9411
#  servlet:
#    context-path: /user
zipkin:
  storage:
    type: elasticsearch
    elasticsearch:
      hosts: http://localhost:9200
      #      username: elastic
      #      password: changeme
      cluster: elasticsearch
      index: zipkin
      index-shards: 1
      index-replicas: 1
  collector:
    kafka:
      bootstrap-servers: localhost:9092
      zookeeper: localhost:2181
      topic:

# 加上这个防止报错
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS
  metrics:
    web:
      server:
        auto-time-requests: false

启动类上加上@EnableZipkinServer,千万要记住,不然zipkin客户端找不到服务哦

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import zipkin2.server.internal.EnableZipkinServer;

@EnableDiscoveryClient
@SpringBootApplication
@EnableZipkinServer
public class CempSleuthApplication {

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

}

输入:http://localhost:9411/zipkin/ 查看一把吧。

kafka配置安装此处省略,自行网上搜索下载

ELK配置

相关文件安装包下载路径:

Logstash: https://www.elastic.co/downloads/logstash

Elasticsearch: https://www.elastic.co/downloads/elasticsearch

Kibana: https://www.elastic.co/downloads/kibana

ELK的安装下载此处省略,自行网上搜索下载。

这里主要是说出一些坑:

1、ElasticSearch-Head连接ES失败:单独查询es是没有问题的

在这里插入图片描述
在这里插入图片描述
问题解决方法:
a、es-head中修改: ES安装路径\elasticsearch-head-master\Gruntfile.js
在这里插入图片描述
b、进入es安装目录下的config目录,修改elasticsearch.yml文件.在文件的末尾加入以下代码
#设置跨域
http.cors.enabled: true
http.cors.allow-origin: “*”
node.master: true
node.data: true
重启ES和启动ES-HEAD,搞定
输入:http://localhost:9100/ 可以看到es-head启动成功,在这里插入图片描述
2、问题二: logstack的conf配置拉取kafka不同的主题topic,创建不同的索引index
我是这样配置的:采用不填的type来区分

input {
  kafka {
    bootstrap_servers => "localhost:9092"
    topics => ["zipkin"]
    codec => "json"
    auto_offset_reset => "earliest" #从最早的偏移量开始消费
    decorate_events => true    #此属性会将当前topic、offset、group、partition等信息也带到message中
    type => "zipkin" #所有插件通用属性,尤其在input里面配置多个数据源时很有用
  }
   kafka {
    bootstrap_servers => "localhost:9092"
    topics => ["my_log"]
    codec => "json"
    auto_offset_reset => "earliest" #从最早的偏移量开始消费
    decorate_events => true    #此属性会将当前topic、offset、group、partition等信息也带到message中
    type => "my_log" #所有插件通用属性,尤其在input里面配置多个数据源时很有用
  }

}
 
output {

	if [type] == "zipkin" {
        elasticsearch {
            hosts => ["localhost:9200"]
            index => "zipkin-topic-%{+YYY.MM.dd}"
        }
    }
	if [type] == "my_log" {
        elasticsearch {
            hosts => ["localhost:9200"]
            index => "kafka-log-%{+YYY.MM.dd}"
        }
    }
    stdout {
        codec => rubydebug {metadata => true}  #logstash控制台输出日志和@metadata信息
    }
}

3、问题三:kibana创建搜索项,index创建不只在哪,直接上截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个选项可选可不选,就是师傅选择根据时间戳查询。
在这里插入图片描述
在这里插入图片描述
最后点击discover,可以看到刚刚创建的index 模板,就可以看到数据啦。到此ELK的配置都完成了。
启动项目就可以看到链路追踪的日志了。
在这里插入图片描述

springboot整和kafka和elk日志收集

1、项目导入包:

 <!-- elasticsearch -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>x-pack-transport</artifactId>
            <version>7.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.9.1</version>
        </dependency>

        <!--        zipkin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
        <!--以下依赖是logback接入kafka所需依赖-->
        <dependency>
            <groupId>com.github.danielwegener</groupId>
            <artifactId>logback-kafka-appender</artifactId>
            <version>0.2.0-RC1</version>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>5.2</version>
        </dependency>

2、application.yml文件配置

spring:
  	application:
    	name: cardmanage
  	sleuth: #链路追踪配置
    	sampler:
      		percentage: 1.0
  	zipkin:
     	sender:
       		type: kafka
     	kafka:
       		topic: zipkin
 	kafka:
   		bootstrap-servers: localhost:9092
 management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

3、日志文件logback-spring.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false-->
<configuration  scan="true" scanPeriod="5 seconds">

    <!-- 该节点会读取Environment中配置的值,在这里我们读取application.yml中的值 -->
    <springProperty scope="context" name="springAppName" source="spring.application.name"  />

    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/data/logs/cemp/cardmanage" />

    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${%level:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />

    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <!-- 输出格式 -->
        <encoder charset="UTF-8">
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 时间滚动输出 level为 DEBUG 日志 -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_debug.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</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}/log_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender><logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true-->
    <!--<logger name="org.springframework.web" level="info"/>-->
    <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
    <!--
        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
        第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
        第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
     -->

    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
        <appender name="kafkaAppender" class="com.github.danielwegener.logback.kafka.KafkaAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>
                    {
                    "severity": "%level",
                    "service": "${springAppName:-}",
                    "trace": "%X{X-B3-TraceId:-}",
                    "span": "%X{X-B3-SpanId:-}",
                    "exportable": "%X{X-Span-Export:-}",
                    "pid": "${PID:-}",
                    "thread": "%thread",
                    "class": "%logger{40}",
                    "rest": "%message"
                    }
                </pattern>
            </encoder>
            <!-- 此处为kafka的Topic名称,千万不要写错 -->
            <topic>my_log</topic>
            <!-- we don't care how the log messages will be partitioned  -->
            <keyingStrategy class="com.github.danielwegener.logback.kafka.keying.NoKeyKeyingStrategy" />
            <!-- use async delivery. the application threads are not blocked by logging -->
            <deliveryStrategy class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy" />
            <!-- each <producerConfig> translates to regular kafka-client config (format: key=value) -->
            <!-- producer configs are documented here: https://kafka.apache.org/documentation.html#newproducerconfigs -->
            <!-- bootstrap.servers is the only mandatory producerConfig  设置kafka的服务器ip和端口-->
            <producerConfig>bootstrap.servers=localhost:9092</producerConfig>
            <!-- don't wait for a broker to ack the reception of a batch.  -->
            <producerConfig>acks=0</producerConfig>
            <!-- wait up to 1000ms and collect log messages before sending them as a batch -->
            <producerConfig>linger.ms=1000</producerConfig>
            <!-- even if the producer buffer runs full, do not block the application but start to drop messages -->
            <producerConfig>max.block.ms=0</producerConfig>
            <!-- define a client-id that you use to identify yourself against the kafka broker -->
            <producerConfig>client.id=0</producerConfig>
        </appender>

    <!--   不同环境使用不同的输出 </root>-->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="DEBUG_FILE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="WARN_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="kafkaAppender" />
    </root>
</configuration>

到此日志收集也好了,启动项目,到kibana可以看到zipkin和kafka-log分别收集了链路追踪和系统日志的数据。
在这里插入图片描述
各人觉得使用日志配置文件这种方式比使用kafka切面收集的方式来的方便简单。以上内容都是各人开发过程中实际遇到的问题,同事也搜索了网上很多的大神的博客最终把项目搞定。如有不对和不妥之处请多多指教。本人微信:“441338280”,欢迎一起交流学习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot整合Zipkin+kafka+ELK,实现链路追踪和日志收集 的相关文章

  • Spring应用中Eureka健康检查的问题

    我正在开发一个基于 Spring 的应用程序 其中包含多个微服务 我的一个微服务充当尤里卡服务器 到目前为止一切正常 在我所有其他微服务中 用 EnableEurekaClient 我想启用这样的健康检查 应用程序 yml eureka c
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 检测并缩短字符串中的所有网址

    假设我有一条字符串消息 您应该将 file zip 上传到http google com extremelylonglink zip http google com extremelylonglink zip not https stack
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • 帮助将图像从 Servlet 获取到 JSP 页面 [重复]

    这个问题在这里已经有答案了 我目前必须生成一个显示字符串文本的图像 我需要在 Servlet 上制作此图像 然后以某种方式将图像传递到 JSP 页面 以便它可以显示它 我试图避免保存图像 而是以某种方式将图像流式传输到 JSP 自从我开始寻
  • Hibernate 的 PersistentSet 不使用 hashCode/equals 的自定义实现

    所以我有一本实体书 public class Book private String id private String name private String description private Image coverImage pr
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 最新的 Hibernate 和 Derby:无法建立 JDBC 连接

    我正在尝试创建一个使用 Hibernate 连接到 Derby 数据库的准系统项目 我正在使用 Hibernate 和 Derby 的最新版本 但我得到的是通用的Unable to make JDBC Connection error 这是
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • 使用 CXF-RS 组件时,为什么我们使用 而不是普通的

    作为后续这个问题 https stackoverflow com questions 20598199 对于如何正确使用CXF RS组件我还是有点困惑 我很困惑为什么我们需要
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • Java中super关键字的范围和使用

    为什么无法使用 super 关键字访问父类变量 使用以下代码 输出为 feline cougar c c class Feline public String type f public Feline System out print fe

随机推荐

  • Android自动化测试工具——Monkey

    前言 最近开始研究Android自动化测试方法 整理了一些工具 方法和框架 其中包括android测试框架 CTS Monkey Monkeyrunner benchmark 以及其它test tool等等 一 什么是Monkey Monk
  • python range和xrange

    python range和xrange 如果需要迭代一个数字序列的话 可以使用range 函数 range 函数可以生成等差级数 如例 for i in range 5 print i 这段代码将输出0 1 2 3 4五个数字 range
  • Python中对负数的整除和取余及特值情况

    整数取余负数 技巧 先忽略负号 之后取余 和正常取余不同的是 被取余的数x一个数 不能比取余的数小 可以相等 这意味着任何一个整数取余 1结果都为0 之后用这个数减去取余的数 最后在得到的结果上加上负号 当被取余的负数取正后大于取余的数时
  • lettuce jedis 比较

    Lettuce 和 Jedis 的定位都是Redis的client 所以他们当然可以直接连接redis server Jedis在实现上是直接连接的redis server 如果在多线程环境下是非线程安全的 这个时候只有使用连接池 为每个J
  • PostgreSQL IoT,车联网 - 实时轨迹、行程实践 1

    背景 车联网 IoT场景中 终端为传感器 采集各个指标的数据 同时包括时间 GIS位置信息 速度 油耗 温度 EDU采集指标 在运动过程中 通过GPS准实时上报到服务端 服务端则通常根据设备 比如车辆 时间范围 查询指定设备在某个时间区间的
  • redis 由浅入深 之 进阶(服务器)

    Redis 服务器 Redis 服务器命令主要是用于管理 redis 服务 bgrewriteaof 命令用于异步执行一个 AOF AppendOnly File 文件重写操作 重写会创建一个当前 AOF 文件的体积优化版本 即使 Bgre
  • linux服务器上僵尸进程查看并杀死方法

    今天在熟悉Linux命令的时候 使用top查看服务器负载的时候 发现了zombie 简单理解成僵尸吧 这个参数 这个参数就代表僵尸进程的含义 什么是僵尸进程呢 这里盗用一下官方的解释 一个进程在调用exit命令结束自己的生命的时候 其实它并
  • c语言程序设计彩色输出,C语言编程之《输出带有颜色》

    在前一篇文章我们学习了让计算机开口说话是使用printf 但是我们发现 计算机 说 出的话都是 黑底白字 的 其实计算机可以输出彩色的 我们一起来看看吧 注意此处代码只能在Windows操作系统下编译运行 下面 我们来看看 如何让颜色出现吧
  • Webpack5 的一些知识总结

    大厂技术 高级前端 Node进阶 点击上方 程序员成长指北 关注公众号 回复1 加入高级Node交流群 前言 webpack 5是2020年发布的 webpack 4是2018年发布的 在webpack 4之上也做出了挺多的改变 比如 添加
  • MySQL JDBC URL参数

    参数清单 属性名 定义 要求 默认值 版本 Connection Authentication 连接 鉴定 user 连接的用户 No 全部 password 连接时使用的密码 No 全部 socketFactory 驱动程序用于创建与服务
  • 基于Python 课程设计-学生管理系统(附源码+可执行程序)

    前言 基于Python 课程设计 学生管理系统 附源码 可执行程序 非常完整的一个项目 可以作为课程设计去学习 本系统的完整源码在文章结尾处 大家自行获取即可 开发环境要求 本系统的软件开发及运行环境具体如下 操作系统 Windows 7
  • VSCode配置

    VSCode配置 1 SSH远程连接到ubuntu系统 VSCode下载扩展 Config文件编写 接入SFTP 免密登陆 2 Debug模式下进入标准库文件 第三方包源码 3 VSCode大纲只显示类和函数 不显示变量 1 SSH远程连接
  • leetcode:165. 比较版本号

    题目来源 leetcode 题目描述 题目分析 比较两个版本号大小 版本号由修订号组成 中间使用 分隔 越靠近字符串前边 修订号的优先级越大 当v1 gt v2时返回 1 当v1 lt v2时返回 1 相等时返回 0 双指针 如样例所示 v
  • 微服务中使用Sentinel实现服务容错

    在微服务架构中 我们将业务拆分成一个个的服务 服务与服务之间可以相互调用 但是由于网络原因或者自身的原因 服务并不能保证服务的100 可用 如果单个服务出现问题 调用这个服务就会出现网络延迟 此时若有大量的网络涌入 会形成任务堆积 最终导致
  • 快速入门(完整):Python练手经典实例100个 (让你的Python技能点全亮)

    Python练手经典实例100个 一 Python 基础 62 例 1 十转二 2 十转八 3 十转十六 4 字符串转字节 5 转为字符串 6 十转ASCII 7 ASCII转十 8 转为字典 9 转为浮点类型 10 转为整型 11 转为集
  • [转]修改python默认的编码方式

    今天碰到了 python 编码问题 报错信息如下Traceback most recent call last File ntpath pyc line 108 in joinUnicodeDecodeError ascii codec c
  • L6200E: Symbol **** multiply defined

    这个错误是链接器 Linker 报告的错误 指示在链接过程中出现了符号 SystemInit 的多重定义 具体来说 符号 SystemInit 被两个目标文件 system stm32f0xx 1 o和system stm32f0xx o
  • 图解RAM结构与原理,系统内存的Channel、Chip与Bank

    文章目录 转载正文 标题挥发性内存分2种 SRAM和DRAM 主内存子系统 channel 和 DIMM rank 和 chip bank row column 内存的读写方式 越多越好 加速读写能力 本文转载来自 图解RAM结构与原理 系
  • 利用mybatis框架的解析器实现文本动态参数

    问题 脚本模板完成后 有些不同的主机执行同一个脚本模板时需要的参数不一样 那么在不同的主机上执行同个脚本时怎么动态将参数赋值给待执行的脚本 而不用直接修改脚本内容 解决方案 Mybatis框架本身的解析器GenericTokenParser
  • Springboot整合Zipkin+kafka+ELK,实现链路追踪和日志收集

    背景 随着项目的深入 久不久可能出现些问题 但是查询起来又极其麻烦 线上有三台服务器 不知道报错日志在那台上 很麻烦 所以领导要求把项目的链路追踪和日志给统一输出到elk中 可以实现在elk查询 Zipkin Sleuth链路追踪 先来实现