中文字幕人妻中文_99精品欧美一区二区三区综合在线_精品久久久久一区二区_色月丁香_免费福利在线视频_欧美大片免费观看网址_国产伦精品一区二区三区在线播放_污污污污污污www网站免费_久久月本道色综合久久_色69激情爱久久_尹人香蕉久久99天天拍_国产美女www_亚洲国产精品无码7777一线_五月婷婷六月激情_看免费一级片_精品久久久久久成人av_在线色亚洲_女人另类性混交zo_国产精品青青在线观看爽香蕉_人人澡人人添人人爽一区二区

主頁 > 知識庫 > 詳解MySQL連接掛死的原因

詳解MySQL連接掛死的原因

熱門標簽:催天下外呼系統(tǒng) 400電話辦理服務價格最實惠 html地圖標注并導航 400電話變更申請 武漢電銷機器人電話 北京金倫外呼系統(tǒng) 呂梁外呼系統(tǒng) 南太平洋地圖標注 大豐地圖標注app

一、背景

近期由測試反饋的問題有點多,其中關于系統(tǒng)可靠性測試提出的問題令人感到頭疼,一來這類問題有時候屬于“偶發(fā)”現象,難以在環(huán)境上快速復現;二來則是可靠性問題的定位鏈條有時候變得很長,極端情況下可能要從 A 服務追蹤到 Z 服務,或者是從應用代碼追溯到硬件層面。

本次分享的是一次關于 MySQL 高可用問題的定位過程,其中曲折頗多但問題本身卻比較有些代表性,遂將其記錄以供參考。

架構

首先,本系統(tǒng)以 MySQL 作為主要的數據存儲部件。整一個是典型的微服務架構(SpringBoot + SpringCloud),持久層則采用了如下幾個組件:

mybatis,實現 SQL -> Method 的映射

hikaricp,實現數據庫連接池

mariadb-java-client,實現 JDBC 驅動

在 MySQL 服務端部分,后端采用了雙主架構,前端以 keepalived 結合浮動IP(VIP)做一層高可用。如下:

說明

  • MySQL 部署兩臺實例,設定為互為主備的關系。
  • 為每臺 MySQL 實例部署一個 keepalived 進程,由 keepalived 提供 VIP 高可用的故障切換。實際上,keepalived 和 MySQL 都實現了容器化,而 VIP 端口則映射到 VM 上的 nodePort 服務端口上。
  • 業(yè)務服務一律使用 VIP 進行數據庫訪問。

Keepalived 是基于 VRRP 協議實現了路由層轉換的,在同一時刻,VIP 只會指向其中的一個虛擬機(master)。當主節(jié)點發(fā)生故障時,其他的 keepalived 會檢測到問題并重新選舉出新的 master,此后 VIP 將切換到另一個可用的 MySQL 實例節(jié)點上。這樣一來,MySQL 數據庫就擁有了基礎的高可用能力。

另外一點,Keepalived 還會對 MySQL 實例進行定時的健康檢查,一旦發(fā)現 MySQL 實例不可用會將自身進程殺死,進而再觸發(fā) VIP 的切換動作。

問題現象

本次的測試用例也是基于虛擬機故障的場景來設計的:

持續(xù)以較小的壓力向業(yè)務服務發(fā)起訪問,隨后將其中一臺 MySQL 的容器實例(master)重啟。按照原有的評估,業(yè)務可能會產生很小的抖動,但其中斷時間應該保持在秒級。

然而經過多次的測試后發(fā)現,在重啟 MySQL 主節(jié)點容器之后,有一定的概率會出現業(yè)務卻再也無法訪問的情況!

二、分析過程

在發(fā)生問題之后,開發(fā)同學的第一反應是 MySQL 的高可用機制出了問題。由于此前曾經出現過由于 keepalived 配置不當導致 VIP 未能及時切換的問題,因此對其已經有所戒備。

先是經過一通的排查,然后并沒有找到 keepalived 任何配置上的毛病。

然后在沒有辦法的情況下,重新測試了幾次,問題又復現了。

緊接著,我們提出了幾個疑點:

1.Keepalived 會根據 MySQL 實例的可達性進行判斷,會不會是健康檢查出了問題?

但在本次測試場景中,MySQL 容器銷毀會導致 keepalived 的端口探測產生失敗,這同樣會導致 keepalived 失效。如果 keepalived 也發(fā)生了中止,那么 VIP 應該能自動發(fā)生搶占。而通過對比兩臺虛擬機節(jié)點的信息后,發(fā)現 VIP 的確發(fā)生了切換。

2. 業(yè)務進程所在的容器是否發(fā)生了網絡不可達的問題?

嘗試進入容器,對當前發(fā)生切換后的浮動IP、端口執(zhí)行 telnet 測試,發(fā)現仍然能訪問成功。

連接池

在排查前面兩個疑點之后,我們只能將目光轉向了業(yè)務服務的DB客戶端上。

從日志上看,在產生故障的時刻,業(yè)務側的確出現了一些異常,如下:

Unable to acquire JDBC Connection [n/a]

java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.

    at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:669) ~[HikariCP-2.7.9.jar!/:?]

    at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:183) ~[HikariCP-2.7.9.jar!/:?] 

    ...

這里提示的是業(yè)務操作獲取連接超時了(超過了30秒)。那么,會不會是連接數不夠用呢?

業(yè)務接入采用的是 hikariCP 連接池,這也是市面上流行度很高的一款組件了。

我們隨即檢查了當前的連接池配置,如下:

//最小空閑連接數
spring.datasource.hikari.minimum-idle=10
//連接池最大大小
spring.datasource.hikari.maximum-pool-size=50
//連接最大空閑時長
spring.datasource.hikari.idle-timeout=60000
//連接生命時長
spring.datasource.hikari.max-lifetime=1800000
//獲取連接的超時時長
spring.datasource.hikari.connection-timeout=30000

其中 注意到 hikari 連接池配置了 minimum-idle = 10,也就是說,就算在沒有任何業(yè)務的情況下,連接池應該保證有 10 個連接。更何況當前的業(yè)務訪問量極低,不應該存在連接數不夠使用的情況。

除此之外,另外一種可能性則可能是出現了“僵尸連接”,也就是說在重啟的過程中,連接池一直沒有釋放這些不可用的連接,最終造成沒有可用連接的結果。

開發(fā)同學對"僵尸鏈接"的說法深信不疑,傾向性的認為這很可能是來自于 HikariCP 組件的某個 BUG…

于是開始走讀 HikariCP 的源碼,發(fā)現應用層向連接池請求連接的一處代碼如下:

public class HikariPool{

   //獲取連接對象入口
   public Connection getConnection(final long hardTimeout) throws SQLException
   {
      suspendResumeLock.acquire();
      final long startTime = currentTime();

      try {
         //使用預設的30s 超時時間
         long timeout = hardTimeout;
         do {
            //進入循環(huán),在指定時間內獲取可用連接
            //從 connectionBag 中獲取連接
            PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
            if (poolEntry == null) {
               break; // We timed out... break and throw exception
            }

            final long now = currentTime();
            //連接對象被標記清除或不滿足存活條件時,關閉該連接
            if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs  !isConnectionAlive(poolEntry.connection))) {
               closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
               timeout = hardTimeout - elapsedMillis(startTime);
            }
            //成功獲得連接對象
            else {
               metricsTracker.recordBorrowStats(poolEntry, startTime);
               return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);
            }
         } while (timeout > 0L);

         //超時了,拋出異常
         metricsTracker.recordBorrowTimeoutStats(startTime);
         throw createTimeoutException(startTime);
      }
      catch (InterruptedException e) {
         Thread.currentThread().interrupt();
         throw new SQLException(poolName + " - Interrupted during connection acquisition", e);
      }
      finally {
         suspendResumeLock.release();
      }
   }
}

getConnection() 方法展示了獲取連接的整個流程,其中 connectionBag 是用于存放連接對象的容器對象。如果從 connectionBag 獲得的連接不再滿足存活條件,那么會將其手動關閉,代碼如下:

void closeConnection(final PoolEntry poolEntry, final String closureReason)
   {
      //移除連接對象
      if (connectionBag.remove(poolEntry)) {
         final Connection connection = poolEntry.close();
         //異步關閉連接
         closeConnectionExecutor.execute(() -> {
            quietlyCloseConnection(connection, closureReason);
            //由于可用連接變少,將觸發(fā)填充連接池的任務
            if (poolState == POOL_NORMAL) {
               fillPool();
            }
         });
      }
   }

注意到,只有當連接滿足下面條件中的其中一個時,會被執(zhí)行 close。

  • isMarkedEvicted() 的返回結果是 true,即標記為清除,如果連接存活時間超出最大生存時間(maxLifeTime),或者距離上一次使用超過了idleTimeout,會被定時任務標記為清除狀態(tài),清除狀態(tài)的連接在獲取的時候才真正 close。
  • 500ms 內沒有被使用,且連接已經不再存活,即 isConnectionAlive() 返回 false

由于我們把 idleTimeout 和 maxLifeTime 都設置得非常大,因此需重點檢查 isConnectionAlive 方法中的判斷,如下:

public class PoolBase{

   //判斷連接是否存活
   boolean isConnectionAlive(final Connection connection)
   {
      try {
         try {
            //設置 JDBC 連接的執(zhí)行超時
            setNetworkTimeout(connection, validationTimeout);

            final int validationSeconds = (int) Math.max(1000L, validationTimeout) / 1000;

            //如果沒有設置 TestQuery,使用 JDBC4 的校驗接口
            if (isUseJdbc4Validation) {
               return connection.isValid(validationSeconds);
            }

            //使用 TestQuery(如 select 1)語句對連接進行探測
            try (Statement statement = connection.createStatement()) {
               if (isNetworkTimeoutSupported != TRUE) {
                  setQueryTimeout(statement, validationSeconds);
               }

               statement.execute(config.getConnectionTestQuery());
            }
         }
         finally {
            setNetworkTimeout(connection, networkTimeout);

            if (isIsolateInternalQueries  !isAutoCommit) {
               connection.rollback();
            }
         }

         return true;
      }
      catch (Exception e) {
         //發(fā)生異常時,將失敗信息記錄到上下文
         lastConnectionFailure.set(e);
         logger.warn("{} - Failed to validate connection {} ({}). Possibly consider using a shorter maxLifetime value.",
                     poolName, connection, e.getMessage());
         return false;
      }
   }

}

我們看到,在PoolBase.isConnectionAlive 方法中對連接執(zhí)行了一系列的探測,如果發(fā)生異常還會將異常信息記錄到當前的線程上下文中。隨后,在 HikariPool 拋出異常時會將最后一次檢測失敗的異常也一同收集,如下:

private SQLException createTimeoutException(long startTime)
{
   logPoolState("Timeout failure ");
   metricsTracker.recordConnectionTimeout();

   String sqlState = null;
   //獲取最后一次連接失敗的異常
   final Throwable originalException = getLastConnectionFailure();
   if (originalException instanceof SQLException) {
      sqlState = ((SQLException) originalException).getSQLState();
   }
   //拋出異常
   final SQLException connectionException = new SQLTransientConnectionException(poolName + " - Connection is not available, request timed out after " + elapsedMillis(startTime) + "ms.", sqlState, originalException);
   if (originalException instanceof SQLException) {
      connectionException.setNextException((SQLException) originalException);
   }

   return connectionException;
}

這里的異常消息和我們在業(yè)務服務中看到的異常日志基本上是吻合的,即除了超時產生的 “Connection is not available, request timed out after xxxms” 消息之外,日志中還伴隨輸出了校驗失敗的信息:

Caused by: java.sql.SQLException: Connection.setNetworkTimeout cannot be called on a closed connection

    at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getSqlException(ExceptionMapper.java:211) ~[mariadb-java-client-2.2.6.jar!/:?]

    at org.mariadb.jdbc.MariaDbConnection.setNetworkTimeout(MariaDbConnection.java:1632) ~[mariadb-java-client-2.2.6.jar!/:?]

    at com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:541) ~[HikariCP-2.7.9.jar!/:?]

    at com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:162) ~[HikariCP-2.7.9.jar!/:?]

    at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:172) ~[HikariCP-2.7.9.jar!/:?]

    at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:148) ~[HikariCP-2.7.9.jar!/:?]

    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) ~[HikariCP-2.7.9.jar!/:?]

到這里,我們已經將應用獲得連接的代碼大致梳理了一遍,整個過程如下圖所示:

從執(zhí)行邏輯上看,連接池的處理并沒有問題,相反其在許多細節(jié)上都考慮到位了。在對非存活連接執(zhí)行 close 時,同樣調用了 removeFromBag 動作將其從連接池中移除,因此也不應該存在僵尸連接對象的問題。

那么,我們之前的推測應該就是錯誤的!

陷入焦灼

在代碼分析之余,開發(fā)同學也注意到當前使用的 hikariCP 版本為 3.4.5,而環(huán)境上出問題的業(yè)務服務卻是 2.7.9 版本,這仿佛預示著什么… 讓我們再次假設 hikariCP 2.7.9 版本存在某種未知的 BUG,導致了問題的產生。

為了進一步分析連接池對于服務端故障的行為處理,我們嘗試在本地機器上進行模擬,這一次使用了 hikariCP 2.7.9 版本進行測試,并同時將 hikariCP 的日志級別設置為 DEBUG。

模擬場景中,會由 由本地應用程序連接本機的 MySQL 數據庫進行操作,步驟如下:

1. 初始化數據源,此時連接池 min-idle 設置為 10;

2. 每隔50ms 執(zhí)行一次SQL操作,查詢當前的元數據表;

3. 將 MySQL 服務停止一段時間,觀察業(yè)務表現;

4. 將 MySQL 服務重新啟動,觀察業(yè)務表現。

最終產生的日志如下:

//初始化過程,建立10個連接

DEBUG -HikariPool.logPoolState - Pool stats (total=1, active=1, idle=0, waiting=0)

DEBUG -HikariPool$PoolEntryCreator.call- Added connection MariaDbConnection@71ab7c09

DEBUG -HikariPool$PoolEntryCreator.call- Added connection MariaDbConnection@7f6c9c4c

DEBUG -HikariPool$PoolEntryCreator.call- Added connection MariaDbConnection@7b531779

...

DEBUG -HikariPool.logPoolState- After adding stats (total=10, active=1, idle=9, waiting=0)

//執(zhí)行業(yè)務操作,成功

execute statement: true

test time -------1

execute statement: true

test time -------2

...

//停止MySQL

...

//檢測到無效連接

WARN  -PoolBase.isConnectionAlive - Failed to validate connection MariaDbConnection@9225652 ((conn=38652) 

Connection.setNetworkTimeout cannot be called on a closed connection). Possibly consider using a shorter maxLifetime value.

WARN  -PoolBase.isConnectionAlive - Failed to validate connection MariaDbConnection@71ab7c09 ((conn=38653) 

Connection.setNetworkTimeout cannot be called on a closed connection). Possibly consider using a shorter maxLifetime value.

//釋放連接

DEBUG -PoolBase.quietlyCloseConnection(PoolBase.java:134) - Closing connection MariaDbConnection@9225652: (connection is dead) 

DEBUG -PoolBase.quietlyCloseConnection(PoolBase.java:134) - Closing connection MariaDbConnection@71ab7c09: (connection is dead)

//嘗試創(chuàng)建連接失敗

DEBUG -HikariPool.createPoolEntry - Cannot acquire connection from data source

java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : 

Socket fail to connect to host:localhost, port:3306. Connection refused: connect

Caused by: java.sql.SQLNonTransientConnectionException: Socket fail to connect to host:localhost, port:3306. Connection refused: connect

    at internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:73) ~[mariadb-java-client-2.6.0.jar:?]

    ...

//持續(xù)失敗.. 直到MySQL重啟

//重啟后,自動創(chuàng)建連接成功

DEBUG -HikariPool$PoolEntryCreator.call -Added connection MariaDbConnection@42c5503e

DEBUG -HikariPool$PoolEntryCreator.call -Added connection MariaDbConnection@695a7435

//連接池狀態(tài),重新建立10個連接

DEBUG -HikariPool.logPoolState(HikariPool.java:421) -After adding stats (total=10, active=1, idle=9, waiting=0)

//執(zhí)行業(yè)務操作,成功(已經自愈)

execute statement: true

從日志上看,hikariCP 還是能成功檢測到壞死的連接并將其踢出連接池,一旦 MySQL 重新啟動,業(yè)務操作又能自動恢復成功了。根據這個結果,基于 hikariCP 版本問題的設想也再次落空,研發(fā)同學再次陷入焦灼。

撥開云霧見光明

多方面求證無果之后,我們最終嘗試在業(yè)務服務所在的容器內進行抓包,看是否能發(fā)現一些蛛絲馬跡。

進入故障容器,執(zhí)行tcpdump -i eth0 tcp port 30052進行抓包,然后對業(yè)務接口發(fā)起訪問。

此時令人詭異的事情發(fā)生了,沒有任何網絡包產生!而業(yè)務日志在 30s 之后也出現了獲取連接失敗的異常。

我們通過 netstat 命令檢查網絡連接,發(fā)現只有一個 ESTABLISHED 狀態(tài)的 TCP 連接。

也就是說,當前業(yè)務實例和 MySQL 服務端是存在一個建好的連接的,但為什么業(yè)務還是報出可用連接呢?

推測可能原因有二:

  • 該連接被某個業(yè)務(如定時器)一直占用。
  • 該連接實際上還沒有辦法使用,可能處于某種僵死的狀態(tài)。

對于原因一,很快就可以被推翻,一來當前服務并沒有什么定時器任務,二來就算該連接被占用,按照連接池的原理,只要沒有達到上限,新的業(yè)務請求應該會促使連接池進行新連接的建立,那么無論是從 netstat 命令檢查還是 tcpdump 的結果來看,不應該一直是只有一個連接的狀況。

那么,情況二的可能性就很大了。帶著這個思路,繼續(xù)分析 Java 進程的線程棧。

執(zhí)行 kill -3 pid 將線程棧輸出后分析,果不其然,在當前 thread stack 中發(fā)現了如下的條目:

"HikariPool-1 connection adder" #121 daemon prio=5 os_prio=0 tid=0x00007f1300021800 nid=0xad runnable [0x00007f12d82e5000]

   java.lang.Thread.State: RUNNABLE

    at java.net.SocketInputStream.socketRead0(Native Method)

    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)

    at java.net.SocketInputStream.read(SocketInputStream.java:171)

    at java.net.SocketInputStream.read(SocketInputStream.java:141)

    at java.io.FilterInputStream.read(FilterInputStream.java:133)

    at org.mariadb.jdbc.internal.io.input.ReadAheadBufferedStream.fillBuffer(ReadAheadBufferedStream.java:129)

    at org.mariadb.jdbc.internal.io.input.ReadAheadBufferedStream.read(ReadAheadBufferedStream.java:102)

    - locked 0x00000000d7f5b480> (a org.mariadb.jdbc.internal.io.input.ReadAheadBufferedStream)

    at org.mariadb.jdbc.internal.io.input.StandardPacketInputStream.getPacketArray(StandardPacketInputStream.java:241)

    at org.mariadb.jdbc.internal.io.input.StandardPacketInputStream.getPacket(StandardPacketInputStream.java:212)

    at org.mariadb.jdbc.internal.com.read.ReadInitialHandShakePacket.init>(ReadInitialHandShakePacket.java:90)

    at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.createConnection(AbstractConnectProtocol.java:480)

    at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1236)

    at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:610)

    at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:142)

    at org.mariadb.jdbc.Driver.connect(Driver.java:86)

    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)

    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)

    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)

    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)

這里顯示HikariPool-1 connection adder這個線程一直處于 socketRead 的可執(zhí)行狀態(tài)。從命名上看該線程應該是 HikariCP 連接池用于建立連接的任務線程,socket 讀操作則來自于 MariaDbConnection.newConnection() 這個方法,即 mariadb-java-client 驅動層建立 MySQL 連接的一個操作,其中 ReadInitialHandShakePacket 初始化則屬于 MySQL 建鏈協議中的一個環(huán)節(jié)。

簡而言之,上面的線程剛好處于建鏈的一個過程態(tài),關于 mariadb 驅動和 MySQL 建鏈的過程大致如下:

MySQL 建鏈首先是建立 TCP 連接(三次握手),客戶端會讀取 MySQL 協議的一個初始化握手消息包,內部包含 MySQL 版本號,鑒權算法等等信息,之后再進入身份鑒權的環(huán)節(jié)。

這里的問題就在于 ReadInitialHandShakePacket 初始化(讀取握手消息包)一直處于 socket read 的一個狀態(tài)。

如果此時 MySQL 遠端主機故障了,那么該操作就會一直卡住。而此時的連接雖然已經建立(處于 ESTABLISHED 狀態(tài)),但卻一直沒能完成協議握手和后面的身份鑒權流程,即該連接只能算一個半成品(無法進入 hikariCP 連接池的列表中)。從故障服務的 DEBUG 日志也可以看到,連接池持續(xù)是沒有可用連接的,如下:

DEBUG HikariPool.logPoolState --> Before cleanup stats (total=0, active=0, idle=0, waiting=3)

另一個需要解釋的問題則是,這樣一個 socket read 操作的阻塞是否就造成了整個連接池的阻塞呢?

經過代碼走讀,我們再次梳理了 hikariCP 建立連接的一個流程,其中涉及到幾個模塊:

  • HikariPool,連接池實例,由該對象連接的獲取、釋放以及連接的維護。
  • ConnectionBag,連接對象容器,存放當前的連接對象列表,用于提供可用連接。
  • AddConnectionExecutor,添加連接的執(zhí)行器,命名如 “HikariPool-1 connection adder”,是一個單線程的線程池。
  • PoolEntryCreator,添加連接的任務,實現創(chuàng)建連接的具體邏輯。
  • HouseKeeper,內部定時器,用于實現連接的超時淘汰、連接池的補充等工作。

HouseKeeper 在連接池初始化后的 100ms 觸發(fā)執(zhí)行,其調用 fillPool() 方法完成連接池的填充,例如 min-idle 是10,那么初始化就會創(chuàng)建10個連接。ConnectionBag 維護了當前連接對象的列表,該模塊還維護了請求連接者(waiters)的一個計數器,用于評估當前連接數的需求。

其中,borrow 方法的邏輯如下:

public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException
   {
      // 嘗試從 thread-local 中獲取
      final ListObject> list = threadList.get();
      for (int i = list.size() - 1; i >= 0; i--) {
         ...
      }

      // 計算當前等待請求的任務
      final int waiting = waiters.incrementAndGet();
      try {
         for (T bagEntry : sharedList) {
            if (bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
               //如果獲得了可用連接,會觸發(fā)填充任務
               if (waiting > 1) {
                  listener.addBagItem(waiting - 1);
               }
               return bagEntry;
            }
         }

         //沒有可用連接,先觸發(fā)填充任務
         listener.addBagItem(waiting);

         //在指定時間內等待可用連接進入
         timeout = timeUnit.toNanos(timeout);
         do {
            final long start = currentTime();
            final T bagEntry = handoffQueue.poll(timeout, NANOSECONDS);
            if (bagEntry == null || bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
               return bagEntry;
            }

            timeout -= elapsedNanos(start);
         } while (timeout > 10_000);

         return null;
      }
      finally {
         waiters.decrementAndGet();
      }
   }

注意到,無論是有沒有可用連接,該方法都會觸發(fā)一個 listener.addBagItem() 方法,HikariPool 對該接口的實現如下:

public void addBagItem(final int waiting)
   {
      final boolean shouldAdd = waiting - addConnectionQueueReadOnlyView.size() >= 0; // Yes, >= is intentional.
      if (shouldAdd) {
         //調用 AddConnectionExecutor 提交創(chuàng)建連接的任務
         addConnectionExecutor.submit(poolEntryCreator);
      }
      else {
         logger.debug("{} - Add connection elided, waiting {}, queue {}", poolName, waiting, addConnectionQueueReadOnlyView.size());
      }
   }
PoolEntryCreator 則實現了創(chuàng)建連接的具體邏輯,如下:
public class PoolEntryCreator{
     @Override
      public Boolean call()
      {
         long sleepBackoff = 250L;
         //判斷是否需要建立連接
         while (poolState == POOL_NORMAL  shouldCreateAnotherConnection()) {
            //創(chuàng)建 MySQL 連接
            final PoolEntry poolEntry = createPoolEntry();
 
            if (poolEntry != null) {
               //建立連接成功,直接返回。
               connectionBag.add(poolEntry);
               logger.debug("{} - Added connection {}", poolName, poolEntry.connection);
               if (loggingPrefix != null) {
                  logPoolState(loggingPrefix);
               }
               return Boolean.TRUE;
            }
            ...
         }

         // Pool is suspended or shutdown or at max size
         return Boolean.FALSE;
      }
}

由此可見,AddConnectionExecutor 采用了單線程的設計,當產生新連接需求時,會異步觸發(fā) PoolEntryCreator 任務進行補充。其中 PoolEntryCreator. createPoolEntry() 會完成 MySQL 驅動連接建立的所有事情,而我們的情況則恰恰是MySQL 建鏈過程產生了永久性阻塞。因此無論后面怎么獲取連接,新來的建鏈任務都會一直排隊等待,這便導致了業(yè)務上一直沒有連接可用。

下面這個圖說明了 hikariCP 的建鏈過程:

好了,讓我們在回顧一下前面關于可靠性測試的場景:

首先,MySQL 主實例發(fā)生故障,而緊接著 hikariCP 則檢測到了壞的連接(connection is dead)并將其釋放,在釋放關閉連接的同時又發(fā)現連接數需要補充,進而立即觸發(fā)了新的建鏈請求。
而問題就剛好出在這一次建鏈請求上,TCP 握手的部分是成功了(客戶端和 MySQL VM 上 nodePort 完成連接),但在接下來由于當前的 MySQL 容器已經停止(此時 VIP 也切換到了另一臺 MySQL 實例上),因此客戶端再也無法獲得原 MySQL 實例的握手包響應(該握手屬于MySQL應用層的協議),此時便陷入了長時間的阻塞式 socketRead 操作。而建鏈請求任務恰恰好采用了單線程運作,進一步則導致了所有業(yè)務的阻塞。

三、解決方案

在了解了事情的來龍去脈之后,我們主要考慮從兩方面進行優(yōu)化:

  • 優(yōu)化一,增加 HirakiPool 中 AddConnectionExecutor 線程的數量,這樣即使第一個線程出現掛死,還有其他的線程能參與建鏈任務的分配。
  • 優(yōu)化二,出問題的 socketRead 是一種同步阻塞式的調用,可通過 SO_TIMEOUT 來避免長時間掛死。

對于優(yōu)化點一,我們一致認為用處并不大,如果連接出現了掛死那么相當于線程資源已經泄露,對服務后續(xù)的穩(wěn)定運行十分不利,而且 hikariCP 在這里也已經將其寫死了。因此關鍵的方案還是避免阻塞式的調用。

查閱了 mariadb-java-client 官方文檔后,發(fā)現可以在 JDBC URL 中指定網絡IO 的超時參數,如下:

具體參考:https://mariadb.com/kb/en/about-mariadb-connector-j/

如描述所說的,socketTimeout 可以設置 socket 的 SO_TIMEOUT 屬性,從而達到控制超時時間的目的。默認是 0,即不超時。

我們在 MySQL JDBC URL 中加入了相關的參數,如下:

spring.datasource.url=jdbc:mysql://10.0.71.13:33052/appdb?socketTimeout=60000connectTimeout=30000serverTimezone=UTC

此后對 MySQL 可靠性場景進行多次驗證,發(fā)現連接掛死的現象已經不再出現,此時問題得到解決。

四、小結

本次分享了一次關于 MySQL 連接掛死問題排查的心路歷程,由于環(huán)境搭建的工作量巨大,而且該問題復現存在偶然性,整個分析過程還是有些坎坷的(其中也踩了坑)。的確,我們很容易被一些表面的現象所迷惑,而覺得問題很難解決時,更容易帶著偏向性思維去處理問題。例如本例中曾一致認為連接池出現了問題,但實際上卻是由于 MySQL JDBC 驅動(mariadb driver)的一個不嚴謹的配置所導致。

從原則上講,應該避免一切可能導致資源掛死的行為。如果我們能在前期對代碼及相關配置做好充分的排查工作,相信 996 就會離我們越來越遠。

以上就是詳解MySQL連接掛死的原因的詳細內容,更多關于MySQL連接掛死的原因的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • Mysql掛掉后無法重啟報pid文件丟失的解決方法
  • MySQL之高可用集群部署及故障切換實現
  • MySQL數據庫實現MMM高可用群集架構
  • 詳解MySQL高可用MMM搭建方案及架構原理
  • MySQL數據庫的高可用方案總結
  • MySQL下高可用故障轉移方案MHA的超級部署教程
  • MySQL高可用MMM方案安裝部署分享
  • MySQL死鎖的產生原因以及解決方案
  • 一個mysql死鎖場景實例分析

標簽:麗水 南充 自貢 西寧 迪慶 龍巖 無錫 徐州

巨人網絡通訊聲明:本文標題《詳解MySQL連接掛死的原因》,本文關鍵詞  詳解,MySQL,連接,掛,死的,;如發(fā)現本文內容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內容系統(tǒng)采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《詳解MySQL連接掛死的原因》相關的同類信息!
  • 本頁收集關于詳解MySQL連接掛死的原因的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 广州市广花包装机械有限公司 | 宁波佳诚机械有限公司| 山推楚天工程机械有限公司| 马鞍山钢铁有限公司| 昆山北钜机械有限公司| 鞍山机械重工有限公司| 上海钢铁交易中心有限公司 | 青岛凯机械有限公司| 建荣精密机械有限公司| 苏州信能精密机械有限公司| 南京神鹏机械设备有限公司| 涿州北方重工设备设计有限公司| 宁波博旺机械有限公司| 诸城市铭威食品机械有限公司| 机械有限公司 张家港| 安阳市赛尔德精工机械有限公司| 北京永创通达机械设备有限公司| 上海申越包装机械制造有限公司 | 无锡万华机械有限公司| 四川久进机械制造有限公司 | 昆明机械制造有限公司| 济南升降机械有限公司| 东莞市金拓机械有限公司 | 涿州北方重工设备设计有限公司| 昆山机械 有限公司| 江苏八达重工机械有限公司 | 四川华为钢铁有限公司| 杭州定江机械有限公司| 东莞市机械制造有限公司| 江阴福鑫机械有限公司| 江阴荣兴机械有限公司| 沈阳三重机械有限公司| 淄博联泰机械有限公司| 恒联食品机械有限公司| 漳州南方机械有限公司| 东莞新宇机械有限公司| 河南 机械设备有限公司| 宁波恒阳机械有限公司| 潍坊市通用机械有限公司| 沈阳德恒机械制造有限公司| 潍坊圣川机械有限公司| 东莞元渝机械有限公司| 常州市锦益机械有限公司| 山鑫机械制造有限公司| 河北大恒重型机械有限公司| 无锡精密机械有限公司| 郑州天龙机械有限公司| 常州英来机械有限公司| 河南省矿山起重机制造有限公司| 深圳市 机械有限公司| 宣城 机械有限公司| 江苏苏盐阀门机械有限公司| 大连橡塑机械有限公司| 苏州毕特富精密机械有限公司| 徐州徐工基础工程机械有限公司 | 上海科纳机械有限公司| 张家港市家源机械有限公司| 常州市机械有限公司| 陕西金奇机械电器制造有限公司 | 威海行雨化工机械有限公司| 山东诚铭建设机械有限公司| 苏州鼎木机械设备有限公司| 靖江机械制造有限公司| 青岛铸造机械有限公司| 张家港市贝尔机械有限公司| 广州嘉银机械有限公司| 瑞安市天晟包装机械有限公司| 华鑫机械制造有限公司| 济宁市福瑞得机械有限公司| 陕西鑫辉钢铁有限公司| 重庆捷灿机械有限公司| 沈阳世润重工有限公司| 山东造纸机械厂有限公司| 南京神鹏机械设备有限公司| 昆山铭世特精密机械有限公司 | 莱州华汽机械有限公司| 东莞%机械%有限公司| 唐山九江钢铁有限公司| 成都 食品机械有限公司| 杰西博工程机械有限公司| 广州惠德机械有限公司| 东莞迅得机械有限公司| 郑州市昌利机械制造有限公司 | 科瑞森机械有限公司| 上海钊凯包装机械有限公司| 杭州丽伟电脑机械有限公司| 无锡创能机械制造有限公司| 宜兴永康机械有限公司| 江苏源德机械有限公司| 南京竣业过程机械设备有限公司| 旭田包装机械有限公司| 江苏威鹰机械有限公司| 速技能机械有限公司| 上海台新食品机械有限公司 | 河南江瀚机械制造有限公司| 烟台精密机械有限公司| 广州起重机械有限公司招聘| 济南精密机械有限公司| 宁波翔博机械有限公司| 晋工机械有限公司官网| 徐州工程机械有限公司| 天宇机械制造有限公司| 佛山市宝陶机械设备有限公司| 太仓悦凯精密机械有限公司| 江苏仁达机械有限公司怎么样 | 常州艾隆精密机械有限公司| 营口嘉晨钢铁有限公司| 常州腾睿机械有限公司| 浙江建机工程机械有限公司| 河北工程机械有限公司| 德州联合石油机械有限公司| 安瑞科气体机械有限公司| 浙江名瑞机械有限公司| 绵阳机械制造有限公司| 河北冠能石油机械制造有限公司 | 张家港机械制造有限公司| 常州包装机械有限公司| 江苏沃得农业机械有限公司| 北京大森长空包装机械有限公司 | 佛山丰堡精密机械有限公司| 旭东机械昆山有限公司| 中山自动化机械有限公司| 台州博州机械有限公司| 台州宏汇机械有限公司| 诚泰精密机械有限公司| 哈尔滨纳诺机械设备有限公司| 昆山市贝纳特机械设备有限公司 | 河北大恒重型机械有限公司| 上海松精机械制造有限公司| 江苏方圣机械有限公司| 天津机械设备有限公司| 安徽远鸿机械有限公司| 鞍山重工机械有限公司| 青岛悦工机械有限公司| 基伊埃机械设备天津有限公司| 常州都可机械有限公司| 徐州恒辉编织机械有限公司| 苏州苏安起重吊装有限公司| 山东冠成机械有限公司| 格润德机械制造有限公司| 威海新元化工机械有限公司| 中山机械制造有限公司| 苏州苏鹰机械制造有限公司| 研精舍上海精密机械加工有限公司 | 扬州诺亚机械有限公司| 昆山精密机械有限公司| 广州市机械有限公司| 湖州卓信机械有限公司| 马鞍山市机械有限公司| 常州市雪龙机械制造有限公司| 迁安九江钢铁有限公司| 机械有限公司 英文| 青岛如隆机械有限公司| 浙江兴盛机械有限公司| 佛山市科机械有限公司| 佛山精诚机械有限公司| 南京海威机械有限公司| 柳州高华机械有限公司| 友隆精密机械有限公司| 浙江凯岛起重机械有限公司| 上海宁金钢铁有限公司| 江阴宏达机械有限公司| 东莞高恩机械有限公司| 山东博杰重型工程机械有限公司 | 广州永晋机械有限公司| 河南省新乡市矿山起重机有限公司 | 佛山市松川机械设备有限公司 | 白鸽食品机械有限公司| 曼透平机械有限公司| 扬州 机械 有限公司| 江苏华粮机械有限公司| 江苏正合重工有限公司| 济南新思路机械设备有限公司| 佛山市机械设备有限公司| 济南东泰机械制造有限公司| 芜湖 机械有限公司| 苏州德扬数控机械有限公司| 盐城海德机械制造有限公司| 东莞科雄机械有限公司| 蓬莱大金海洋重工有限公司| 山东起重机有限公司| 顺德富华工程机械制造有限公司| 湖北铁正机械有限公司| 上海凯机械有限公司| 东莞市瑞沧机械设备有限公司| 常熟 机械有限公司| 台林机械有限公司 -| 宁波博信机械制造有限公司| 山东利丰机械有限公司| 安阳三一机械有限公司| 河南共威机械设备有限公司| 珠海华亚机械有限公司| 山西建龙钢铁有限公司地址| 上海长江服装机械有限公司| 佛山市浩铭达机械制造有限公司 | 齐鲁石化机械制造有限公司招聘 | 中山市信元铝门窗机械制造有限公司| 张家港市鑫港机械有限公司| 泰安鑫杰机械有限公司| 南昌矿山机械有限公司| 天津达亿钢铁有限公司| 山东华珠机械有限公司| 上海斯特克沃森重工设备有限公司| 沧州卓鑫机械设备制造有限公司| 上海华预机械制造有限公司| 张家港市机械制造有限公司| 郑州市联华机械制造有限公司 | 武汉贝瑞克机械制造有限公司| 长沙力诺机械有限公司| 厦门工业机械有限公司| 上海派协包装机械有限公司 | 唐山文丰钢铁有限公司| 江苏谷登工程机械装备有限公司 | 钦州力顺机械有限公司| 首钢凯西钢铁有限公司| 上海泓阳机械有限公司| 上海中远海运重工有限公司| 重工机械制造有限公司| 大连西格机械工具有限公司| 宁波美亚特精密机械有限公司| 无锡光良塑料机械有限公司| 郑州万谷机械有限公司| 广州科盛隆纸箱包装机械有限公司| 潍坊凯德塑料机械有限公司| 新乡高服筛分机械有限公司| 福建机械工业有限公司| 芜湖中安重工自动化装备有限公司| 青岛谊金华塑料机械有限公司| 广州嘉银机械有限公司| 南通国盛精密机械有限公司| 广州惠辉机械设备有限公司| 昆山市贝纳特机械设备有限公司| 新金山钢铁有限公司| 济南庚辰钢铁有限公司| 苏州市机械制造有限公司| 湖北华伟石化机械设备制造有限公司| 浙江杰豹机械有限公司| 工程机械有限公司经营范围 | 宁波市鸿博机械制造有限公司 | 群韵饮料机械有限公司| 宁夏瑞光机械有限公司| 莱州行星机械有限公司| 咸阳恒佳机械有限公司| 江苏柳工机械有限公司| 沂南县宏发机械有限公司| 瑞安市华东包装机械有限公司| 哈尔滨纳诺机械设备有限公司| 上海德耐尔压缩机械有限公司| 南京嘉诚机械有限公司| 四平现代钢铁有限公司| 捷泰克机械有限公司| 三马起重机有限公司| 机械租赁有限公司名字| 华群数控机械有限公司| 青岛西城铸造机械有限公司| 台州万州机械有限公司| 泉州得力农林机械有限公司| 浙江工程机械有限公司| 唐山利军机械有限公司| 浙江建设机械有限公司| 山西天巨重工机械有限公司 | 山东战尔机械有限公司| 快克数控机械有限公司| 青岛鲁耕农业机械有限公司| 起重设备(上海)有限公司| 张家港同大机械有限公司| 航星洗涤机械(泰州)有限公司| 杭州凯邦机械有限公司| 鲁山万通通机械制造有限公司| 缙云县机械有限公司| 上海三都机械有限公司| 辽阳喜旺机械制造有限公司| 南京利晨机械有限公司| 徐州凯工机械有限公司| 广西徐重机械有限公司| 石家庄工程机械有限公司| 沈阳沈飞航宇机械制造有限公司| 山鑫矿山机械有限公司| 山东 重工有限公司| 浙江双环传动机械有限公司 | 大华机械制造有限公司| 纺织机械制造有限公司| 常州经编机械有限公司| 湖北 机械制造有限公司| 武汉 机械制造有限公司| 汕头市机械有限公司| 威海盛世机械有限公司| 湖州惠盛机械有限公司| 浙江瑞德森机械有限公司| 厦门升正机械有限公司| 珠海三麦机械有限公司| 上海轶鹰起重机械有限公司| 湖南运想重工有限公司| 上海起重电机厂有限公司| 常州远见机械有限公司| 邹平 机械有限公司| 东莞市科环机械设备有限公司| 鸡西煤矿机械有限公司| 普惠环保机械有限公司| 株洲机械制造有限公司| 佛山市浩铭达机械制造有限公司| 贵州华泰机械设备租赁有限公司| 上海鑫水机械有限公司| 泰安正阳机械有限公司| 唐山东方钢铁有限公司| 机械有限公司 招聘| 上海陆达包装机械制造有限公司| 萧山天成机械有限公司| 浙江建机工程机械有限公司| 宜昌 机械有限公司| 德州液压机械有限公司| 天津亨旺机械有限公司| 徐工基础工程机械有限公司| 永裕昌机械有限公司| 东莞市全永机械制造有限公司| 苏州久富农业机械有限公司| 辽宁亿丰钢铁有限公司| 龙南福鑫钢铁有限公司| 河北金维重工有限公司| 石家庄工程机械有限公司| 河南兴邦重工机器有限公司| 青岛西城铸造机械有限公司| 四川机械制造有限公司| 上海众德机械有限公司| 济南东泰机械制造有限公司| 云南昆鼎机械设备有限公司 | 江苏苏盐阀门机械有限公司| 浙江豪盛印刷机械有限公司| 潍坊广德机械有限公司| 昆玉钢铁有限公司招聘| 上海得力起重索具有限公司| 上海松精机械制造有限公司| 山东天路重工有限公司| 无锡锡洲机械有限公司| 首都航天机械有限公司| 上海机械工程有限公司| 济宁 机械有限公司| 无锡东元精密机械有限公司| 河北途盟机械制造有限公司| 台州通宇变速机械有限公司| 苏州苏鹰机械制造有限公司| 重庆德运机械制造有限公司| 合肥方圆机械有限公司| 佛山丰堡精密机械有限公司| 维美德造纸机械技术有限公司| 深圳印刷机械有限公司| 藏不起服饰有限公司| 广东金凯锐机械技术有限公司 | 重庆中容石化机械制造有限公司| 青岛金福鑫塑料机械有限公司| 常州光明包装机械有限公司| 苏州恒升机械有限公司| 浙江正润机械有限公司| 上海香宝机械设备有限公司| 山东济宁机械有限公司| 上海起泽起重机械有限公司 | 西安工程机械有限公司| 上海齐耀螺杆机械有限公司 | 新乡市金原起重机械有限公司| 郑州明瑞机械设备有限公司| 杭州通绿机械有限公司| 上海重型机械有限公司| 州东方机械有限公司| 旭英机械有限公司招聘| 泰安正阳机械有限公司| 上海景林包装机械有限公司| 江 诚机械有限公司| 扬州 机械 有限公司| 上海炬钢机械制造有限公司| 江苏羚羊机械有限公司| 凹凸精密机械有限公司| 福建省 机械有限公司| 枣庄金正钢铁有限公司| 郑州正科机械有限公司| 唐山港陆钢铁有限公司| 四川宏华友信石油机械有限公司| 蚌埠柳工机械有限公司| 临沂金立机械有限公司| 南京竣业过程机械设备有限公司| 潍坊华星机械有限公司| 济南章力机械有限公司| 武汉四方圆机械设备有限公司| 邢工机械制造有限公司| 江苏电能机械有限公司| 北京起重机械有限公司| 旭众食品机械有限公司| 上海恒启机械设备有限公司| 无锡机械制造有限公司| 江苏东钢钢铁有限公司| 上海达和荣艺包装机械有限公司 | 东莞培锋精密机械有限公司| 海宁弘德机械有限公司| 鞍山机械重工有限公司| 宁波顺兴机械制造有限公司| 江苏钢锐精密机械有限公司| 柳溪机械设备有限公司| 纸箱机械制造有限公司| 上海世邦机械有限公司| 浙江青山钢铁有限公司| 宜昌 机械设备有限公司| 石家庄博锐食品机械有限公司| 江苏新美星包装机械有限公司| 厦门 机械有限公司| 浙江濠泰机械有限公司| 天工机械制造有限公司| 深圳机械院建筑设计有限公司| 山东良鑫机械有限公司| 船舶机械制造有限公司| 上海捷舟工程机械有限公司| 河南宏基矿山机械有限公司 | 河北石阀机械设备有限公司| 天津起重机械有限公司| 保东农业机械有限公司| 宜兴市机械有限公司| 上海戴服特包装机械有限公司| 四川工程机械有限公司| 海瑞克隧道机械有限公司| 张家港市塑机械有限公司| 瑞安正博机械有限公司| 台州宏汇机械有限公司| 烟台宏兴机械有限公司| 江苏钢锐精密机械有限公司| 河南力神机械有限公司| 扬州市天发试验机械有限公司| 大连东拓工程机械制造有限公司 | 湖南汇杰机械设备有限公司| 南通力威机械有限公司| 东莞协鑫机械有限公司| 泰州机械制造有限公司| 上海瀚艺冷冻机械有限公司| 九江益鑫机械有限公司| 台州中茂机械有限公司| 无锡创能机械制造有限公司| 济南北斗星机械设备有限公司 | 常德烟草机械有限公司| 无锡鹰贝机械有限公司| 上海紫光机械有限公司| 泉州市闽达机械制造有限公司| 厦门工业机械有限公司| 常州曼恩机械有限公司| 广濑精密机械有限公司| 江苏汉庭机械制造有限公司| 浙江乐江机械有限公司| 伟拓压铸机械有限公司| 湖南湘船重工有限公司| 扬州福尔喜果蔬汁机械有限公司| 常州华威起重工具有限公司| 苏州典艺精密机械有限公司| 青岛沃隆花生机械有限公司| 青岛精密机械有限公司| 山东峻峰起重机械有限公司| 仕诚塑料机械有限公司| 广州市汇格机械设备有限公司 | 烟台市石油机械有限公司| 台州工交机械有限公司| 潍坊威尔顿机械设备有限公司| 曲阜艾特机械有限公司| 北京雄伟京发机械加工有限公司| 鹤壁市双信矿山机械有限公司| 济南 液压机械有限公司| 廊坊中建机械有限公司| 常州机械制造有限公司| 河钢乐亭钢铁有限公司| 昆山总馨机械有限公司| 衡水机械制造有限公司| 济南建筑机械有限公司| 上海得力起重索具有限公司| 无锡诺德传动机械有限公司| 瑞安 机械有限公司| 重庆红江机械有限公司| 金旺机械设备有限公司| 辽宁三君工程机械有限公司| 山东神力起重机械有限公司| 江阴机械制造有限公司怎么样 | 乙盛机械工业有限公司| 重工机械制造有限公司| 浙江陀曼精密机械有限公司| 上海精密机械制造有限公司| 山东诸城机械有限公司| 广州市天烨食品机械有限公司| 焦作市虹起制动器有限公司| 湖州机械制造有限公司| 廊坊德基机械有限公司| 精雕精密机械有限公司| 浙江亿森机械有限公司| 工程机械配件有限公司| 杭州东田机械有限公司| 志高机械有限公司官网| 临沂胜代机械有限公司| 丽驰精密机械有限公司| 临沂华星机械有限公司| 长沙中传机械有限公司| 无锡杨佳机械有限公司| 洛阳起重机厂有限公司| 广州市天烨食品机械有限公司| 洛阳泰红农业机械有限公司| 山东临工工程机械有限公司招聘| 深圳步先包装机械有限公司| 郑州机械制造有限公司| 青岛诺机械有限公司| 沈阳冶金机械有限公司| 东莞大禹机械有限公司| 上海益达机械有限公司| 山东钢铁日照有限公司| 上海长空机械有限公司| 中山自动化机械有限公司| 恒昌机械制造有限公司| 宁波思进机械有限公司| 杭州高福机械制造有限公司 | 诸城市博康机械有限公司| 东莞培锋精密机械有限公司| 汕头市伟力塑料机械厂有限公司| 浙江志高机械有限公司| 烟台金鹏矿业机械有限公司| 济南章力机械有限公司| 山东通佳机械有限公司| 上海服装机械有限公司| 欧诺机械 有限公司| 上海机械成套设备有限公司| 新乡市利尔机械有限公司| 洛阳重型机械有限公司| 石家庄食品机械有限公司| 东莞兆恒机械有限公司| 安徽富鑫钢铁有限公司| 河北雪龙机械制造有限公司| 新昌华亿机械有限公司| 通达塑料机械有限公司| 天津英德诺机械设备有限公司| 泰而勒食品机械贸易(上海)有限公司 | 常州精密机械有限公司| 南京创力传动机械有限公司| 杰西博工程机械有限公司| 上海嘉亿机械有限公司| 河南宏基矿山机械有限公司 | 南通 机械有限公司| 苏州鸿本机械制造有限公司| 合肥亿恒机械有限公司| 唐山利丰机械有限公司| 江苏洪流化工机械有限公司| 鑫达机械设备有限公司| 瀚乐电子机械有限公司| 台州博州机械有限公司| 无锡金球机械有限公司| 泉州群峰机械有限公司| 宁波达峰机械有限公司| 康铖机械设备有限公司| 杭州卡塞尔机械有限公司| 苏州同大机械有限公司| 东莞智荣机械有限公司| 中泰机械设备有限公司| 常州工程机械有限公司| 浙江绿峰机械有限公司| 五莲县机械有限公司| 山东枭隆机械有限公司| 中山市凌宇机械有限公司| 东莞丰堡精密机械有限公司| 安特精密机械有限公司| 上海玉兆精密机械有限公司| 青岛工程机械有限公司| 厦门珀挺机械有限公司| 陕西鑫辉钢铁有限公司| 济南梓鑫机械有限公司| 长兴诺力机械有限公司| 江阴古川机械有限公司| 东莞精密机械有限公司| 河南明天机械有限公司| 宇进注塑机械有限公司| 机械有限公司 招聘| 桂林中天机械有限公司| 广州市汇格机械设备有限公司| 昆山富邦机械有限公司| 江苏隆达机械设备有限公司| 广州联冠机械有限公司| 诸城市铭威食品机械有限公司| 漳州震东机械有限公司| 郑州一本机械设备有限公司| 东莞市永乐机械有限公司| 海德机械设备有限公司| 珠海市机械有限公司| 台州市四海机械有限公司| 比力特机械有限公司| 青岛高通机械有限公司| 沧州凯德机械有限公司| 诚辉机械制造有限公司| 诸城市放心食品机械有限公司 | 重庆江增船舶重工有限公司| 泉州市恒兴工业机械有限公司 | 常州欧鹰焊割机械有限公司| 东莞市腾机械有限公司| 南京拓源钢铁有限公司| 洛阳中收机械装备有限公司招聘| 宏强机械设备有限公司| 同向兴业机械有限公司| 深圳电子机械有限公司| 江苏华澄重工有限公司| 上海国翔包装机械制造有限公司 | 徐州恒辉编织机械有限公司| 安丘瑞源机械制造有限公司| 湖南博长钢铁贸易有限公司| 上海霏润机械设备有限公司| 湖南中旺工程机械设备有限公司| 上海全驰机械有限公司| 杭州青达机械有限公司| 济南数控机械有限公司| 上海服装机械有限公司| 嘉诚机械制造有限公司| 河南华北起重吊钩有限公司| 成都 精密机械有限公司| 扬州恒润海洋重工有限公司| 东莞宏起塑胶电子有限公司| 高密永和精密机械有限公司招聘网| 锋机械设备有限公司| 无锡威华机械有限公司| 上海东芝机械有限公司| 上海开隆冶金机械制造有限公司 | 青岛青宏机械制造有限公司| 广州汉牛机械设备有限公司| 南阳 机械制造有限公司| 牛力机械制造有限公司| 常州杰和机械有限公司| 曲阜天阳机械有限公司| 光大机械厂有限公司| 威士重工机械有限公司| 江阴市科盛机械有限公司| 张家港同大机械有限公司| 广州新成机械技术有限公司| 江门市机械有限公司| 沈阳工程机械有限公司| 无锡盛达机械制造有限公司| 常州嘉耘机械有限公司| 佛山市松川包装机械有限公司| 哈尔滨 机械 有限公司| 温州博宇机械有限公司| 广州市华劲机械有限公司| 宁波美亚特精密机械有限公司| 河北圣禹水工机械有限公司| 运输有限公司起名大全| 武汉机械制造有限公司| 山东新纪元重工有限公司| 扬州恒润钢铁有限公司| 上海齐耀重工有限公司| 佛山市宝捷精密机械有限公司| 常州机械制造有限公司| 鞍山源鑫钢铁有限公司| 南通铁军机械有限公司| 重庆阿德耐特动力机械有限公司 | 济南天助升降机械有限公司| 武汉环卫机械有限公司| 常州华机械有限公司| 郑州机械制造有限公司| 河北澳金机械设备有限公司| 昆山塑料机械有限公司| 河南机械设备制造有限公司| 淄博捷达机械有限公司| 杭州精工机械有限公司| 凯格精密机械有限公司| 江苏机械制造有限公司| 无锡润和机械有限公司| 抚顺新钢铁有限公司| 力顺源机械有限公司| 福建泉工机械有限公司| 上海恒启机械设备有限公司 | 东营 机械制造 有限公司| 万则盛机械有限公司| 河北鑫达钢铁有限公司| 江苏恒悦机械有限公司| 上海善能机械有限公司| 沈阳高新机械有限公司| 常州先电机械有限公司| 南京凯驰机械有限公司| 维特根机械有限公司| 江西协旭机械有限公司| 浙江保龙机械有限公司| 河北宏发机械有限公司| 广东星联精密机械有限公司| 浙江晨雕机械有限公司| 广西南宁机械有限公司| 富世华机械有限公司| 河南通达重工有限公司| 大连 重工有限公司| 焦作市机械制造有限公司| 东莞市卓越机械有限公司招聘| 河南钢铁贸易有限公司| 河北德欧机械有限公司| 江苏恒械机械有限公司| 长江液压机械有限公司| 纸箱机械制造有限公司| 山东力强机械有限公司| 机械设备有限公司经营范围| 鑫磊机械制造有限公司| 河南 机械制造有限公司| 广州机械租赁有限公司| 河南胜飞石油机械有限公司 | 河北裕华钢铁有限公司| 菏泽瑞康机械有限公司| 珠海仕高玛机械设备有限公司| 泰安华伟重工有限公司| 郑州市联华机械制造有限公司| 威海达盛机械有限公司| 宝鸡忠诚制药机械有限公司| 泰上机械设备有限公司| 西帕机械杭州有限公司| 郑州宇通重工有限公司| 广东顺发起重设备有限公司| 泰安东岳重工有限公司| 河南起重机器有限公司| 潍坊坊通机械有限公司| 三菱重工海尔空调机有限公司| 丹阳市华泰制药机械有限公司 | 人科机械设备有限公司| 爱克苏州机械有限公司| 安徽宇华机械制造有限公司| 同向精密机械有限公司| 莱州日进机械有限公司| 河北永洋钢铁有限公司| 机械(昆山)有限公司| 鑫泰数控机械有限公司| 浙江顺得机械有限公司| 威海新元化工机械有限公司| 新乡市长城机械有限公司| 德州市启泰机械设备有限公司| 昆山博通机械设备有限公司| 潍坊二川机械有限公司| 哈尔滨机械制造有限公司| 广州市金王机械设备有限公司| 晋江力达机械有限公司| 青岛特固机械有限公司| 缙云县机械有限公司| 莱州 机械有限公司| 迈安德食品机械有限公司| 武汉鑫金泽机械有限公司| 苏州机械制造有限公司| 合肥浩凯机械有限公司| 苏州市大华精密机械有限公司 | 浙江瑞浦机械有限公司| 上海振华重工有限公司| 大连起重矿山机械有限公司| 江苏鑫林钢铁有限公司| 长沙威沃机械制造有限公司| 上海昶旭包装机械有限公司| 上海嘉歆包装机械有限公司| 威海祥光机械有限公司| 徐工辽宁机械有限公司| 大连滨海起重机吊具有限公司| 邢台正佳机械制造有限公司| 苏州拓博机械设备有限公司| 中交天和机械设备制造有限公司| 玻璃设备机械有限公司| 湖南华菱湘潭钢铁有限公司| 保定锐腾机械制造有限公司| 宁波天辉机械有限公司| 苏州德扬数控机械有限公司| 襄阳博亚机械有限公司| 输送机械制造有限公司| 漳州三宝钢铁有限公司| 洛阳中收机械装备有限公司| 石家庄工程机械有限公司| 衡阳沃力机械有限公司| 徐州机械制造有限公司| 东莞市益彩机械有限公司| 海德机械设备有限公司| 徐州明文机械有限公司| 杭州驰耐传动机械有限公司| 南通恩派特机械有限公司| 浙江印刷机械有限公司| 河北春耕机械制造有限公司 | 宁波拓诚机械有限公司| 广东富华机械装备制造有限公司| 昆山台一精密机械有限公司| 无锡海龙机械有限公司| 大连胜龙包装机械有限公司| 新兴移山天津重工有限公司| 广东力特工程机械有限公司 | 河北农哈哈机械有限公司| 山东机械铸造有限公司| 上海钊凯包装机械有限公司| 夹江水工机械有限公司| 江苏润山机械有限公司| 江苏申特钢铁有限公司| 青岛南牧机械设备有限公司| 东莞市今塑精密机械有限公司| 建湖县液压机械有限公司| 上海起泽起重机械有限公司| 洛阳大华重型机械有限公司| 唐山众达机械轧辊有限公司| 临沂园林机械有限公司| 宁波恒威机械有限公司| 济宁山矿机械有限公司| 山东兴田机械有限公司| 重庆工程机械有限公司| 芜湖电工机械有限公司| 湖北华伟石化机械设备制造有限公司 | 咸阳恒佳机械有限公司| 四川川宏机械有限公司| 江阴市华夏包装机械有限公司| 江苏鑫锋重工机床有限公司| 山东日发纺织机械有限公司| 迁安荣信钢铁有限公司| 兴虎动力机械有限公司| 张家港亿塑机械有限公司| 临沂市机械有限公司| 迪砂常州机械有限公司| 宁波钛龙机械有限公司| 郑州宇机械有限公司| 杭州同创顶立机械有限公司 | 上海航空机械有限公司| 宏力机械设备有限公司| 平煤机械设备有限公司| 随州盛星机械有限公司| 鑫成机械设备有限公司| 宏机械铸造有限公司| 深圳市安格斯机械有限公司| 曲阜圣泰机械有限公司| 无锡东晨机械有限公司| 大连华锐重工有限公司| 江阴博纬机械有限公司| 中山市包装机械有限公司| 东莞市金拓机械有限公司| 南海区机械设备有限公司| 山东大汉建设机械有限公司| 江西省机械有限公司| 曲靖呈钢铁有限公司| 佛山钢铁贸易有限公司| 潞城兴宝钢铁有限公司| 河南嵩山重工有限公司| 广州精密机械有限公司| 山东日发纺织机械有限公司| 淮南凯盛重工有限公司| 四川宏华友信石油机械有限公司| 沁阳宏达钢铁有限公司| 江阴精力机械有限公司| 广州新麦机械有限公司| 山东讴神机械制造有限公司| 青岛武船重工有限公司| 重庆双腾机械制造有限公司| 南京明瑞机械设备有限公司| 新乡市海纳筛分机械制造有限公司| 杭州双龙机械有限公司| 南京凯驰机械有限公司| 东莞市康旭机械有限公司| 威图电子机械技术上海有限公司| 新乡市机械有限公司| 信息技术有限公司起名| 兖矿大陆机械有限公司| 武汉千里马工程机械有限公司| 濮阳市机械有限公司| 海安机械制造有限公司| 广东鸿业机械有限公司| 济宁五创机械有限公司| 泰安恒大机械有限公司| 江西钧天机械有限公司奔驰| 广东力丰机械有限公司| 江苏同力机械有限公司| 安宁市永昌钢铁有限公司| 广州恒联食品机械有限公司| 海南建设工程机械施工有限公司 | 食品机械(上海)有限公司| 山东腾机械有限公司| 济南包装机械有限公司| 海瑞克隧道机械有限公司| 杭州西恒机械有限公司| 上海长江服装机械有限公司| 淄博宙灿机械有限公司| 兖州大华机械有限公司| 河南 机械设备有限公司| 青岛唐宇机械制造有限公司| 铭诚机械制造有限公司| 青岛德利机械有限公司| 张家港市饮料机械有限公司| 芜湖机械制造有限公司| 贵阳闽达钢铁有限公司| 河北雪龙机械制造有限公司| 东芝机械上海有限公司| 荏原机械烟台有限公司| 浙江嘉益机械有限公司| 南京拓源钢铁有限公司| 眉山千层弹花机械有限公司| 安徽工程机械有限公司| 江苏新益机械有限公司| 欧克机械制造有限公司| 上海合劲传动机械有限公司| 泰安古河机械有限公司| 兴世机械制造有限公司| 三门峡化工机械有限公司| 无锡奥野机械有限公司| 佛山机械制造有限公司| 山东金亿机械制造有限公司| 郑州海特机械有限公司| 烟台金元矿业机械有限公司| 湛江恒润机械有限公司| 淄博捷达机械有限公司| 杭州鸿机械有限公司| 济南卓恒膨化机械有限公司| 常州宝菱重工机械有限公司| 河南旭矿机械有限公司| 广州市善友机械设备有限公司| 衡阳华意机械有限公司| 北京晨光兴业机械有限公司| 财益机械工业有限公司| 扬州扬工机械有限公司| 大连蓝德机械有限公司| 山东三牛机械有限公司| 安徽威萨重工机械有限公司| 曲阜广鑫机械有限公司| 江西凯奥机械有限公司| 江阴戎辉机械设备制造有限公司| 石家庄美迪机械有限公司| 沈阳世润重工有限公司| 上海盛普机械制造有限公司| 无锡烨隆精密机械有限公司| 佛山陶瓷机械有限公司| 江阴博纬机械有限公司| 扬州金威机械有限公司| 郑州昌利机械制造有限公司| 盐城中热机械有限公司| 天津 起重有限公司| 烟台建筑机械有限公司| 柳州富达机械有限公司官网| 工程机械有限公司经营范围| 青岛慧洋梳理机械有限公司| 江阴韩一钢铁有限公司| 上海轩特机械设备有限公司 | 诸城市志诺机械有限公司| 东台富康机械有限公司| 捷赛机械苏州有限公司| 山东硕诚机械有限公司| 苏州市机械制造有限公司| 山东传洋钢铁有限公司| 福州协展机械有限公司| 山东金奥机械有限公司| 张家港精密机械有限公司| 固精密机械有限公司| 深圳龙润彩印机械设备有限公司| 江苏先电机械有限公司| 南通江华机械有限公司| 山西 机械设备有限公司| 东莞市今塑精密机械有限公司 | 昆山富邦机械有限公司| 广东明华机械有限公司| 友隆精密机械有限公司| 青岛欣鑫数控精密机械有限公司 | 武汉 机械制造有限公司| 苏州奥天诚机械有限公司| 匹思通机械有限公司| 三联传动机械有限公司| 安徽金庆龙机械制造有限公司 | 唐山龙润机械有限公司| 昆山胜代机械有限公司| 上海 包装机械有限公司| 东莞通盛机械有限公司| 成都神钢建设机械有限公司| 山东液压机械有限公司| 上海嘉倍德塑胶机械有限公司 | 郑州谷丰机械设备有限公司| 南皮县中顺环保机械有限公司| 扬州市天发试验机械有限公司| 江苏新瑞机械有限公司| 青岛诺恩包装机械有限公司| 上海国翔包装机械制造有限公司| 上海盛普机械制造有限公司| 天津钢铁销售有限公司| 东莞市力华机械设备有限公司| 上海航空机械有限公司| 无纺布机械有限公司| 诸城市华邦机械有限公司| 上海合劲传动机械有限公司| 深圳市高士达精密机械有限公司 | 南通艾迈特机械有限公司| 珠海仕高玛机械设备有限公司| 宁波工程机械有限公司| 徐州随车起重机有限公司| 溧阳机械制造有限公司| 念朋机械设备有限公司| 无锡锡州机械有限公司| 重庆海迅机械制造有限公司| 浙江伟焕机械制造有限公司| 佛山市科机械有限公司| 河北德林机械有限公司| 徐州徐工随车起重机有限公司| 江西鑫通机械有限公司| 泉州泉丰机械有限公司| 东莞共荣精密机械有限公司| 浙江华球机械制造有限公司| 广州市台展机械有限公司| 大连军峰机械有限公司| 济南天宝钢铁有限公司| 蓬莱禄昊化工机械有限公司 | 北京机械制造有限公司| 温州市顺达服装机械有限公司| 湖北三六重工有限公司| 建筑工程机械租聘有限公司| 马钢合肥钢铁有限公司| 广州轻工机械有限公司| 昆山乔地精密机械有限公司| 常州宝菱重工机械有限公司| 天马电子机械有限公司| 宏达机械制造有限公司| 泉州得力农林机械有限公司| 濮阳 机械有限公司|