美文网首页
SpringBoot3.x使用Druid

SpringBoot3.x使用Druid

作者: 言午日尧耳总 | 来源:发表于2024-03-09 19:32 被阅读0次

    SpringBoot3.x使用Druid

    起步

    安装

        <properties>
            <druid.version>1.2.21</druid.version>
        </properties>
    
        <dependencies>
    
            <dependency>
               <groupId>com.alibaba</groupId>
               <artifactId>druid-spring-boot-starter</artifactId>
               <version>${druid.version}</version>
            </dependency>
            
            <!-- SpringBoot3.x使用这个库,才能够开启Druid监控网页 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-3-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
          
        </dependencies>
    
    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource        # Druid连接池!
        
        # 以下注释内容与原数据库连接相同
        url: jdbc:mysql://***
        username: ***
        password: ***
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    • 其他连接池设置
    spring.datasource.druid.socket-timeout= 6000 # 请求超时时间(单位:毫秒)
    
    spring.datasource.druid.initial-size=
    spring.datasource.druid.max-active=
    spring.datasource.druid.min-idle=
    spring.datasource.druid.max-wait=
    spring.datasource.druid.pool-prepared-statements=
    spring.datasource.druid.max-pool-prepared-statement-per-connection-size= 
    spring.datasource.druid.max-open-prepared-statements= #和上面的等价
    spring.datasource.druid.validation-query=
    spring.datasource.druid.validation-query-timeout=
    spring.datasource.druid.test-on-borrow=
    spring.datasource.druid.test-on-return=
    spring.datasource.druid.test-while-idle=
    spring.datasource.druid.time-between-eviction-runs-millis=
    spring.datasource.druid.min-evictable-idle-time-millis=
    spring.datasource.druid.max-evictable-idle-time-millis=
    spring.datasource.druid.filters= #配置多个英文逗号分隔
    ....//more
    

    基础连接信息

    • 非必须,无聊看着玩的
    • 创建任意控制器和任意路径,返回Druid的连接信息
    @RestController
    @RequestMapping("/index")
    public class IndexController {
        @GetMapping("/druid-status")
        public Object druidStat(){
            return DruidStatManagerFacade.getInstance().getDataSourceStatDataList();
        }
    }
    
    • 响应示例如下
    [
      {
        "Identity": 1583082378,
        "Name": "DataSource-1583082378",
        "DbType": "h2",
        "DriverClassName": "org.h2.Driver",
        "URL": "jdbc:h2:file:./demo-db",
        "UserName": "sa",
        "FilterClassNames": [
          "com.alibaba.druid.filter.stat.StatFilter"
        ],
        "WaitThreadCount": 0,
        "NotEmptyWaitCount": 0,
        "NotEmptyWaitMillis": 0,
        "PoolingCount": 2,
        "PoolingPeak": 2,
        "PoolingPeakTime": 1533782955104,
        "ActiveCount": 0,
        "ActivePeak": 1,
        "ActivePeakTime": 1533782955178,
        "InitialSize": 2,
        "MinIdle": 2,
        "MaxActive": 30,
        "QueryTimeout": 0,
        "TransactionQueryTimeout": 0,
        "LoginTimeout": 0,
        "ValidConnectionCheckerClassName": null,
        "ExceptionSorterClassName": null,
        "TestOnBorrow": true,
        "TestOnReturn": true,
        "TestWhileIdle": true,
        "DefaultAutoCommit": true,
        "DefaultReadOnly": null,
        "DefaultTransactionIsolation": null,
        "LogicConnectCount": 103,
        "LogicCloseCount": 103,
        "LogicConnectErrorCount": 0,
        "PhysicalConnectCount": 2,
        "PhysicalCloseCount": 0,
        "PhysicalConnectErrorCount": 0,
        "ExecuteCount": 102,
        "ErrorCount": 0,
        "CommitCount": 100,
        "RollbackCount": 0,
        "PSCacheAccessCount": 100,
        "PSCacheHitCount": 99,
        "PSCacheMissCount": 1,
        "StartTransactionCount": 100,
        "TransactionHistogram": [
          55,
          44,
          1,
          0,
          0,
          0,
          0
        ],
        "ConnectionHoldTimeHistogram": [
          53,
          47,
          3,
          0,
          0,
          0,
          0,
          0
        ],
        "RemoveAbandoned": false,
        "ClobOpenCount": 0,
        "BlobOpenCount": 0,
        "KeepAliveCheckCount": 0,
        "KeepAlive": false,
        "FailFast": false,
        "MaxWait": 1234,
        "MaxWaitThreadCount": -1,
        "PoolPreparedStatements": true,
        "MaxPoolPreparedStatementPerConnectionSize": 5,
        "MinEvictableIdleTimeMillis": 30001,
        "MaxEvictableIdleTimeMillis": 25200000,
        "LogDifferentThread": true,
        "RecycleErrorCount": 0,
        "PreparedStatementOpenCount": 1,
        "PreparedStatementClosedCount": 0,
        "UseUnfairLock": true,
        "InitGlobalVariants": false,
        "InitVariants": false
      }
    ]
    

    Druid监控面板

    启用面板

    • Druid提供了大量监控数据,监控数据只保存在内存中,重启后会丢失,且无法集中查看
      • 面板中的"重置"按钮,指的是重置监控数据
    • 访问地址(在url-pattern配置):http://localhost:8080/druid
    • 可访问页面
      • 首页
      • 数据源
      • JSON API
    • IP转发问题
      • Nginx转发
        • 使用Nginx代理转发,原访问IP会被替换成Nginx的IP,所以allow需要设置成Nginx服务器的IP
        • 但是所有访问IP都被替换成Nginx的IP,所有请求都会放行,相当于allow失去了作用,记得使用账号
        • 最佳实践:外网Nginx直接屏蔽druid接口,开发机直接内网访问原始服务器地址,allow设置成开发机IP
      • k8s集群代理
        • k8s集群Ingress的IP是动态的,无法设置成准确IP,可以设置为"192.168.0.0/16,10.0.0.0/8"放行所有IP(同样有安全问题,记得增加账号密码)
        • 最佳实践:不要暴露druid接口,开发机使用"kubectl port-forward"或者"ktctl forward"命令将服务转到本地,再通过localhost访问
      • 其他
        • Nginx中设置"proxy_set_header Host $host;"的解决方案,在目前的最新版"1.2.21"中是无效的
    spring:
      datasource:
        druid:
          stat-view-servlet:
            enabled: true           # 启用Druid监控面板
            url-pattern: /druid/*   # 面板路径(默认"/druid/*")(Druid已做了处理,不会被自定义过滤器拦截)
            
            reset-enable: false     # 面板上的重置按钮(禁用后面板上重置按钮依然会显示和互动,但是不起作用) 
            
            login-username: admin   # 账号(默认不需要登录,设置了才需要)
            login-password: 123456  # 密码
            
            allow: 127.0.0.1        # 白名单,多个使用逗号隔开(不在白名单中不能访问,默认开启localhost/127.0.0.1)
            deny: 127.0.0.1         # 黑名单,多个使用逗号隔开
            # 使用Nginx转发导致访问IP丢失,allow、deny均失效,可将allow设置为 192.168.0.0/16,10.0.0.0/8 允许所有请求,注意使用账号保护
    

    SQL监控

    • 启用"SQL监控",未开启则面板无任何数据
    spring:
      datasource:
        druid:
          filter:
            stat:
              enabled: true           # 启动SQL语句监控,同时会影响其他面板中的SQL展示(如:影响"URI监控"中的jdbc数据)
              db-type: mysql          # 数据库类型(实测没啥用,会自动根据上面的连接自动识别)
    
              log-slow-sql: true      # 记录慢日志("SQL监控"面板中数值会标记为红色)
              slow-sql-millis: 3000   # 慢日志判定标准(单位:毫秒)
              slow-sql-log-level: ERROR # 自定义日志级别,默认日志级别"ERROR"
    

    SQL防火墙

    • 检查SQL语句,防止恶意操作
    • 同时记录每一次Select/Insert/Update/...等操作
    spring:
      datasource:
        druid:
          filter:
            wall:
              enabled: true               # 启用防火墙
              db-type: h2                 # 数据库类型(实测没啥用,会自动根据上面的连接自动识别)
              config:
                delete-allow: false       # 是否允许DELETE操作(报错异常:java.sql.SQLException:sql injection violation, dbType mysql, druid-version 1.2.21, delete not allow : DELETE FROM ...)
                drop-table-allow: false   # 是否允许DROP TABLE操作
    

    Web应用/URI监控/Session监控

    • 影响到"Web应用/URI监控/Session监控"面板
    spring:
      datasource:
        druid:
          web-stat-filter:
            enabled: true     # 启用"Web应用/URI监控/Session监控"面板
            url-pattern: /*   # 监控这里指定的路径
            exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.html,*.json   # 过滤路径
    
            # "Session监控"面板设置(RestFul纯后端没有session)
            session-stat-enable: true
            session-stat-max-count: 1000
            principal-session-name: xxc
            principal-cookie-name: xxc
            profile-enable: true
    

    Spring监控

    • 会记录该切面下的执行时间,Jdbc执行数据
      • 需要开启安装aop依赖
    spring:
      datasource:
        druid:
          aop-patterns: x.y.z.controller.* # Spring监控AOP切入点,多个用逗号分隔
    

    其他

    问题

    超时

    • 基本
    Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure...
    ...
    The last packet successfully received from the server was 11,034 milliseconds ago. The last packet sent successfully to the server was 20,386 milliseconds ago...
    
    LastErrorMessage:
    Communications link failure The last packet successfully received from the server was 11,034 milliseconds ago. The last packet sent successfully to the server was 20,386 milliseconds ago.
    
    LastErrorClass:
    com.mysql.cj.jdbc.exceptions.CommunicationsException
    
    LastErrorStackTrace:
    com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
    com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
    com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:912)
    com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:354)
    com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3462)
    com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:434)
    com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3460)
    com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.execute(PreparedStatementProxyImpl.java:158)
    com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:483)
    org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64)
    org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
    jdk.internal.reflect.GeneratedMethodAccessor43.invoke(Unknown Source)
    java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.base/java.lang.reflect.Method.invoke(Method.java:568)
    org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64)
    jdk.proxy2/jdk.proxy2.$Proxy170.query(Unknown Source)
    org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
    org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
    org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
    org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
    com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:81)
    org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62)
    jdk.proxy2/jdk.proxy2.$Proxy169.query(Unknown Source)
    org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
    org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145)
    org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
    ...
    
    spring:
      datasource:
        druid:
          socket-timeout: 60000 # 连接超时时间,60000毫秒(1分钟)
    

    相关文章

      网友评论

          本文标题:SpringBoot3.x使用Druid

          本文链接:https://www.haomeiwen.com/subject/efjuzdtx.html