SpringBoot Zipkin Dubbo Rpc 调用链路追踪完整流程 (二)

本文主要是介绍SpringBoot Zipkin Dubbo Rpc 调用链路追踪完整流程 (二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SpringBoot Zipkin Dubbo Rpc Http日志链路追踪完整流程 (二)

文章目录

    • SpringBoot Zipkin Dubbo Rpc Http日志链路追踪完整流程 (二)
        • 1.准备工作
            • 1)安装启动Zipkin
            • 2)安装启动Zookeeper
            • 3)项目架构 用户微服务 调用 订单微服务
        • 2.配置项目用户微服务 user
            • 1)构建项目A user
            • 2)导入user项目
            • 3)配置user微服务 application.properties
            • 4)配置user微服务 Log4j2配置文件
            • 5)修改user微服务 Pom文件
            • 6)引入项目测试类Controller
            • 6)引入项目配置类
            • 7)启动项目、测试Http请求
            • 8)查看Log日志及Zipkin界面
        • 3.配置 User 调用 Order 微服务
            • 1)controller包中 新建 RpcController
            • 2)调用controller中的 rpc http接口

1.准备工作
1)安装启动Zipkin
2)安装启动Zookeeper
3)项目架构 用户微服务 调用 订单微服务

本项目主要将 采用 SpringBoot 2.4.2 + Zipkin + Dubbo 2.7.x 实现
两个微服务 用户微服务User,订单微服务Order(父子module项目 分为order-client 第三方调用jar及 order-webapp)
上述的 这些步骤 可以查看上一篇文章 SpringBoot Zipkin Dubbo Rpc 调用链路追踪完整流程 (一)


在这里说一下坑,我为什么不直接用sleuth 来配置,想看 sleuth实现Http调用的链路追踪 可以看下我的文章 SpringBoot SpringCloud Sleuth Zipkin实现 链路追踪

2.配置项目用户微服务 user
1)构建项目A user

构建SpringBoot项目 用户微服务 user,在页面 https://start.spring.io/ 中构建项目 user,直接新建一个Springboot项目
插件勾选了 web
在这里插入图片描述

构建完成 ,解压zip包,然后 用IDEA导入项目

2)导入user项目

打开IDEA 导入项目,然后 查看目录结构
在这里插入图片描述

3)配置user微服务 application.properties

配置application.properties ,log4j2需要指明日志配置的xml文件 如 resources下log4j下log4j2-dev.xml文件
配置user 微服务启动端口 9989
配置dubbo协议相关
配置zipkin配置相关

#项目配置
server.port=9989
spring.application.name=user
#项目配置#Dubbo 配置dubbo.protocol.name=dubbo
dubbo.application.name=userApplication
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.consumer.check=false
dubbo.provider.filter=tracing
dubbo.consumer.filter=tracing#log日志配置
logging.config=classpath:log4j/log4j2-dev.xml
#log日志配置end#zipkin配置
zipkin.base.url=http://127.0.0.1:9411/api/v2/spans
zipkin.enable=true
#zipkin配置
4)配置user微服务 Log4j2配置文件

在resources下新建log4j文件夹,然后新建 log4j2-dev.xml文件 修改自己的项目名 $PROJECT_NAME 及 项目日志存储路径 $FILE_PATH

要想log4j2打印TraceId、SpanId,必要听别人说要配置 [%X{X-B3-TraceId},%X{X-B3-SpanId}] 没卵用,重要事情说三遍
这个版本的只有按照这个配置才是可以生效的[%X{traceId},%X{spanId}]
这个版本的只有按照这个配置才是可以生效的[%X{traceId},%X{spanId}]
这个版本的只有按照这个配置才是可以生效的[%X{traceId},%X{spanId}]
在这里插入图片描述

Log4j2-dev.xml 配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,
当设置成trace时,可以看到log4j2内部各种详细输出
-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5"><!--日志级别以及优先级排序:OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL--><!--变量配置--><Properties><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><!--%logger{36} 表示 Logger 名字最长36个字符--><property name="LOG_PATTERN" value="[%d{yyy-MM-dd HH:mm:ss:SSS}]  [%X{traceId},%X{spanId}] %highlight{%-5level}[%thread] %style{%logger{36}}{cyan} : %msg%n" /><!-- 定义日志存储的路径,不要配置相对路径 --><property name="PROJECT_NAME" value="user" /><property name="FILE_PATH" value="E:\myworkspace\log\${PROJECT_NAME}" /></Properties><appenders><console name="Console" target="SYSTEM_OUT"><!--输出日志的格式--><PatternLayout pattern="${LOG_PATTERN}" disableAnsi="false" noConsoleNoAnsi="false"/><!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/></console><!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--><File name="FileLog" fileName="${FILE_PATH}/test.log" append="false"><PatternLayout pattern="${LOG_PATTERN}"/></File><!--这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${PROJECT_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz"><!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="${LOG_PATTERN}"/><Policies><!--interval属性用来指定多久滚动一次,默认是1 hour--><TimeBasedTriggeringPolicy interval="1"/><SizeBasedTriggeringPolicy size="20MB"/></Policies><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--><DefaultRolloverStrategy max="15"/></RollingFile><!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${PROJECT_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz"><!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="${LOG_PATTERN}"/><Policies><!--interval属性用来指定多久滚动一次,默认是1 hour--><TimeBasedTriggeringPolicy interval="1"/><SizeBasedTriggeringPolicy size="20MB"/></Policies><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--><DefaultRolloverStrategy max="15"/></RollingFile><!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${PROJECT_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz"><!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="${LOG_PATTERN}"/><Policies><!--interval属性用来指定多久滚动一次,默认是1 hour--><TimeBasedTriggeringPolicy interval="1"/><SizeBasedTriggeringPolicy size="20MB"/></Policies><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--><DefaultRolloverStrategy max="15"/></RollingFile></appenders><!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--><!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--><loggers><!--过滤掉spring和mybatis的一些无用的DEBUG信息--><logger name="org.mybatis" level="info" additivity="false"><AppenderRef ref="Console"/></logger><!--监控系统信息--><!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。--><Logger name="org.springframework" level="info" additivity="false"><AppenderRef ref="Console"/></Logger><root level="info"><appender-ref ref="Console"/><appender-ref ref="FileLog"/><appender-ref ref="RollingFileInfo"/><appender-ref ref="RollingFileWarn"/><appender-ref ref="RollingFileError"/></root></loggers></configuration>
5)修改user微服务 Pom文件

Pom文件需要修改成引用Log4j2的日志jar包,springboot默认依赖logback,现在要修改pom文件,去掉logback包,添加log4j2 jar包作为日志输出依赖
主要操作为 :
1.去除web包下的logging依赖
2.添加log4j2jar包依赖
3.添加dubbo及zookeeper依赖
4.添加 brave 相关客户端依赖, brave的依赖版本靠 dependencyManagement 中的brave-bom 5.13.3、zipkin-reporter-bom 2.16.3版本来控制

Pom如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.jzj</groupId><artifactId>user</artifactId><version>0.0.1-SNAPSHOT</version><name>user</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><dubbo.version>2.7.7</dubbo.version><curator.version>4.0.1</curator.version><brave-bom.version>5.13.3</brave-bom.version><zipkin-reporter-bom.version>2.16.3</zipkin-reporter-bom.version></properties><dependencies><!--  项目相关依赖 引用order的rpc jar包     --><dependency><groupId>com.jzj</groupId><artifactId>order-client</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><!-- 去掉springboot log默认配置 --><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!-- 引入log4j2依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!--Log4j2 异步日志Jar--><dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.3.6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--添加Dubbo及Zookeeper、zkclient依赖		--><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>${dubbo.version}</version></dependency><!--        zookeeper客户端注册中心依赖--><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${curator.version}</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${curator.version}</version></dependency><!-- SpringBoot 2.7.x Dubbo 版本 配置Zipkin--><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-instrumentation-dubbo</artifactId></dependency><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-spring-beans</artifactId></dependency><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-context-slf4j</artifactId></dependency><!--        tracing --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-sender-okhttp3</artifactId></dependency><!--        tracing  & mvc--><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-instrumentation-spring-webmvc</artifactId></dependency><!--        tracing  & http--><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-instrumentation-httpclient</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-bom</artifactId><version>${brave-bom.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-reporter-bom</artifactId><version>${zipkin-reporter-bom.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><!--为什么加这个 ,不加这个后期产生一个错误,在编译时候报错 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project order-webapp--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--在这里修改版本--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.4.3</version></plugin><!----></plugins></build></project>
6)引入项目测试类Controller

在com.jzj.user目录下新建 controller包,包中新建测试类SiteController, 保证测试http端口
http://localhost:9989/temp/ping
http://localhost:9989/temp/log
http://localhost:9989/temp/http

package com.jzj.user.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.net.URI;@ResponseBody
@RestController
@RequestMapping("temp")
public class SiteController {private static Logger log = LoggerFactory.getLogger(SiteController.class);@Autowiredprivate RestTemplate restTemplate;@RequestMapping("ping")public Object ping() {log.info("进入ping");return "pong user";}@RequestMapping("log")public Object log() {log.info("this is info log");log.error("this is error log");log.debug("this is debug log");log.warn("this is warn log");log.trace("this is trace log");return "123";}@RequestMapping("http")public Object httpQuery() {String roomUrl = "http://localhost:9989/temp/ping";URI ping = URI.create(roomUrl);String pingResult = restTemplate.getForObject(ping, String.class);return pingResult;}}
6)引入项目配置类

在com.jzj.user包下新建autoconfig包
在autoconfig包下新建rest包,新建类RestTemplateConfig 用于使用RestTemplate封装http请求

package com.jzj.user.autoconfig.rest;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;/*** RestTemplate配置类*/
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory factory){return new RestTemplate(factory);}@Beanpublic ClientHttpRequestFactory simpleClientHttpRequestFactory(){SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setReadTimeout(5000);//单位为msfactory.setConnectTimeout(5000);//单位为msreturn factory;}
}

在autoconfig包下新建trace包,新建类TracingConfig用于使用链路追踪配置

package com.jzj.user.autoconfig.trace;import brave.CurrentSpanCustomizer;
import brave.SpanCustomizer;
import brave.Tracing;
import brave.context.slf4j.MDCScopeDecorator;
import brave.http.HttpTracing;
import brave.propagation.B3Propagation;
import brave.propagation.ExtraFieldPropagation;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.rpc.RpcTracing;
import brave.sampler.Sampler;
import brave.servlet.TracingFilter;
import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import zipkin2.Span;
import zipkin2.codec.Encoding;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.Sender;
import zipkin2.reporter.okhttp3.OkHttpSender;import javax.servlet.Filter;/*** @author jzjie*/
@Configuration
@Import(SpanCustomizingAsyncHandlerInterceptor.class)
public class TracingConfig extends WebMvcConfigurerAdapter {@Bean@ConditionalOnProperty(value = {"zipkin.enable"},matchIfMissing = false)Sender sender(@Value("${zipkin.base.url}") String url) {return OkHttpSender.newBuilder().encoding(Encoding.PROTO3).endpoint(url).build();}/*** Configuration for how to buffer spans into messages for Zipkin*/@Bean@ConditionalOnBean(Sender.class)AsyncReporter<Span> spanReporter(Sender sender) {AsyncReporter.Builder builder = AsyncReporter.builder(sender);builder.queuedMaxSpans(50000);builder.queuedMaxBytes(104857600);return builder.build();}/*** Controls aspects of tracing such as the service name that shows up in the UI*/@BeanTracing tracing(@Value("${dubbo.application.name}") String applicationName, @Value("${zipkin.enable:false}") Boolean enable, @Autowired(required = false) AsyncReporter spanReporter) {Tracing.Builder builder = Tracing.newBuilder().localServiceName(applicationName).propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name")).currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()// puts trace IDs into logs.addScopeDecorator(MDCScopeDecorator.create()).build());if (enable) {builder.spanReporter(spanReporter);builder.sampler(Sampler.ALWAYS_SAMPLE);} else {builder.sampler(Sampler.NEVER_SAMPLE);}return builder.build();}@BeanSpanCustomizer spanCustomizer(Tracing tracing) {return CurrentSpanCustomizer.create(tracing);}/*** Decides how to name and tag spans. By default they are named the same as the http method*/@BeanHttpTracing httpTracing(Tracing tracing) {return HttpTracing.create(tracing);}@BeanRpcTracing rpcTracing(Tracing tracing) {return RpcTracing.create(tracing);}/*** Creates server spans for http requests*/@BeanFilter tracingFilter(HttpTracing httpTracing) {return TracingFilter.create(httpTracing);}@AutowiredSpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;/*** Decorates server spans with application-defined web tags*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(webMvcTracingCustomizer);}}
7)启动项目、测试Http请求

maven插件 clean 项目,然后 install项目,如果编译通过,没问题,跳过此步骤,直接访问 controller
如果又出错了 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project user

当然还是配置 Build的版本

    <!--为什么加这个 ,不加这个后期产生一个错误,在编译时候报错 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project order-webapp--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--在这里修改版本--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.4.3</version></plugin><!----></plugins></build>

启动项目,访问端口 9989 controller端口
http://127.0.0.1:9989 /temp/ping
http://127.0.0.1:9989 /temp/log
http://127.0.0.1:9989 /temp/http
在这里插入图片描述

8)查看Log日志及Zipkin界面

Console端Log日志
在这里插入图片描述

Zipkin界面
userApplication就是 application.properties 中配置的 dubbo.application.name=userApplication
在这里插入图片描述

查看 console日志是否匹配Zipkin链路ID
在这里插入图片描述

到此为止,我们配置好了A 用户User 微服务,并且它的 Http 是可以追踪的,要想实现Dubbo Rpc调用,我们还要调用 Order 的 微服务 ,看看TraceId 是否能从 项目A 用户微服务 串联到 B 订单微服务




3.配置 User 调用 Order 微服务
1)controller包中 新建 RpcController

RpcController中 注入 Dubbo 接口IOrderRpcService的消费者
@DubboReference(interfaceClass = IOrderRpcService.class)
private IOrderRpcService floorRpcService;

package com.jzj.user.controller;import com.jzj.order.client.IOrderRpcService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;@ResponseBody
@RestController
@RequestMapping("rpc")
public class RpcController {private static Logger log = LoggerFactory.getLogger(RpcController.class);@DubboReference(interfaceClass = IOrderRpcService.class)private IOrderRpcService floorRpcService;@RequestMapping("order")public Object order() {log.info("进入 controller order");String orderInfo = floorRpcService.getOrderInfo("10000");log.info("rpc调用结果 result:{}", orderInfo);return orderInfo;}
}
2)调用controller中的 rpc http接口

重启项目UserApplication ,看是否 发起Dubbo调用,并且 链路ID是否由 User微服务 ,串联到 Order微服务

Http请求,没问题
在这里插入图片描述
查看console日志,是否同一个traceId 从 user发起,串联到了 另一个微服务 order
在这里插入图片描述

查看Zipkin 当前链路信息
在这里插入图片描述

至此,我们实现了 SpringBoot Zipkin Dubbo Rpc 日志链路追踪完整流程 ,从一个微服务 User 的服务, 调用 Dubbo Rpc 接口 Order 的微服务,实现了 用户调用订单的需求 同一个链路串联不同的 微服务
大功告成,感谢大家支持


这篇关于SpringBoot Zipkin Dubbo Rpc 调用链路追踪完整流程 (二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965431

相关文章

Java中对象的创建和销毁过程详析

《Java中对象的创建和销毁过程详析》:本文主要介绍Java中对象的创建和销毁过程,对象的创建过程包括类加载检查、内存分配、初始化零值内存、设置对象头和执行init方法,对象的销毁过程由垃圾回收机... 目录前言对象的创建过程1. 类加载检查2China编程. 分配内存3. 初始化零值4. 设置对象头5. 执行

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程

《SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程》本文详细介绍了如何在虚拟机和宝塔面板中安装RabbitMQ,并使用Java代码实现消息的发送和接收,通过异步通讯,可以优化... 目录一、RabbitMQ安装二、启动RabbitMQ三、javascript编写Java代码1、引入

spring-boot-starter-thymeleaf加载外部html文件方式

《spring-boot-starter-thymeleaf加载外部html文件方式》本文介绍了在SpringMVC中使用Thymeleaf模板引擎加载外部HTML文件的方法,以及在SpringBoo... 目录1.Thymeleaf介绍2.springboot使用thymeleaf2.1.引入spring

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui