• yum을 하였을 때 databases가 lock이 발생하여 yum으로 패키지 설치 불가
  • yum으로 설치가 불가능하면, 패키지 관리 및 서비스 운영에 문제 발생

yum database is locked 문제 발생

$ yum install -y sysstat
...생략...
Total size: 315 k
Installed size: 1.1 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Traceback (most recent call last):
  File "/bin/yum", line 29, in <module>
    yummain.user_main(sys.argv[1:], exit_code=True)
  File "/usr/share/yum-cli/yummain.py", line 375, in user_main
    errcode = main(args)
  File "/usr/share/yum-cli/yummain.py", line 281, in main
    return_code = base.doTransaction()
  File "/usr/share/yum-cli/cli.py", line 817, in doTransaction
    resultobject = self.runTransaction(cb=cb)
  File "/usr/lib/python2.7/site-packages/yum/__init__.py", line 1834, in runTransaction
    lastdbv = self.history.last()
  File "/usr/lib/python2.7/site-packages/yum/history.py", line 1271, in last
    ret = self.old([], 1, complete_transactions_only)
  File "/usr/lib/python2.7/site-packages/yum/history.py", line 1220, in old
    executeSQL(cur, sql, params)
  File "/usr/lib/python2.7/site-packages/yum/sqlutils.py", line 166, in executeSQLQmark
    return cursor.execute(query)
sqlite3.OperationalError: database is locked

yum database is locked 해결 명령어

  • /var/lib/yum/history 디렉토리 내용 확인

    $ ls /var/lib/yum/history/  
    2021-11-15/ history-2021-11-15.sqlite history-2021-11-15.sqlite-journal
  • /var/lib/yum/history 디렉토리 삭제

    $ rm -rf /var/lib/yum/history

해결 결과 → yum으로 설치 가능

  • yum으로 패키지 설치 가능

    $ yum install -y sysstat
    Loaded plugins: fastestmirror, product-id, search-disabled-repos, subscription-manager
    
    This system is not registered with an entitlement server. You can use subscription-manager to register.
    
    Loading mirror speeds from cached hostfile
    * base: mirror.kakao.com
    * epel: ftp.riken.jp
    * extras: mirror.kakao.com
    * updates: mirror.kakao.com
    Resolving Dependencies
    --> Running transaction check
    ---> Package sysstat.x86_64 0:10.1.5-19.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ============================================================================
    Package                    Arch                              Version                               Repository                            Size
    ============================================================================
    Installing:
    sysstat                    x86_64                           10.1.5-19.el7                      base                                     315 k
    
    Transaction Summary
    ============================================================================
    Install  1 Package
    
    Total size: 315 k
    Installed size: 1.1 M
    Downloading packages:
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
    Installing : sysstat-10.1.5-19.el7.x86_64                                                                                          1/1
    Verifying  : sysstat-10.1.5-19.el7.x86_64                                                                                          1/1
    
    Installed:
    sysstat.x86_64 0:10.1.5-19.el7
    
    Complete!

참고 URL : https://stackoverflow.com/questions/48037629/yum-database-is-locked

  • 패키지에 따라 의존성 문제로 되돌릴 수 없는 경우가 발생 → 주의 필요
  • 설정파일들은 패키지 설치/삭제 시 되돌리지 못할 수 있으므로 백업 필요

 

지금까지 설치한 yum 내용 확인

  • yum 명령을 사용해서 패키지를 설치하거나 업데이트를 하면 ID가 하나씩 증가
  • 각 항목의 세부사항을 알고 싶은면 info 옵션을 사용
    $ yum history
    Loaded plugins: fastestmirror
    ID     | Login user               | Date and time    | Action(s)      | Altered
    -------------------------------------------------------------------------------
      47 | root              | 2012-08-25 16:09 | Install        |    1
      46 | root              | 2012-08-20 17:00 | Install        |    1
      45 | root              | 2012-08-20 09:07 | Install        |    1
      44 | root              | 2012-08-20 09:06 | Install        |    3
      43 | root              | 2012-08-20 09:05 | Install        |    8
      42 | root              | 2012-08-05 15:51 | Install        |    1
      41 | root              | 2012-08-05 15:47 | Install        |    1
      40 | root              | 2012-08-05 15:41 | Install        |    2
      39 | root              | 2012-08-05 15:24 | Install        |    1
      38 | root              | 2012-08-05 15:18 | Install        |    1
      37 | root              | 2012-08-05 15:14 | Install        |    3
      36 | root              | 2012-08-05 14:53 | I, U            |  195 EE
      35 | root              | 2012-08-05 14:52 | Install        |    3
      34 | root              | 2012-01-19 11:20 | I, U            |   42 EE
      33 | root              | 2012-03-07 15:22 | Install        |    8
      32 | root              | 2011-12-26 14:04 | Install        |    1
      31 | root              | 2011-12-26 13:11 | Install        |   18
      30 | root              | 2011-12-26 11:31 | Install        |    1
      29 | root              | 2011-12-26 11:18 | Install        |   12 EE
      28 | root              | 2011-12-21 17:59 | Install        |    1

 

yum 명령을 사용해서 설치한 history의 세부 내용 출력

$ yum history info 47
Loaded plugins: fastestmirror
Transaction ID : 47
Begin time     : Sat Aug 25 16:09:43 2012
Begin rpmdb    : 586:e318ebe25b7f3c641234d8aec7f55b25e005ba00
End time       :                           (0 seconds)
End rpmdb      : 587:870ce250959935e6a5968fbb5928c1378daedda7
User           : root
Return-Code    : Success
Command Line   : install dosfstools
Transaction performed with:
    Installed     rpm-4.8.0-27.el6.x86_64                       @base
    Installed     yum-3.2.29-30.el6.centos.noarch               @base
    Installed     yum-plugin-fastestmirror-1.1.30-14.el6.noarch @base
Packages Altered:
    Install dosfstools-3.0.9-4.el6.x86_64 @base
history info

 

yum 명령어 실수로 rollback이 필요한 경우

  • ID 47에서 46으로 되돌림
    $ yum history rollback 46
    Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
    * base: centos.tt.co.kr
    * extras: centos.tt.co.kr
    * updates: centoso4.centos.org
    base                                                     | 3.7 kB     00:00
    extras                                                   | 3.5 kB     00:00
    nodejs-stable                                            | 2.9 kB     00:00
    updates                                                  | 3.5 kB     00:00
    updates/primary_db                                       | 4.0 MB     00:08
    Rollback to transaction 46, from Mon Aug 20 17:00:17 2012
     Undoing the following transactions: 47
       Install dosfstools-3.0.9-4.el6.x86_64 @base
    Resolving Dependencies
    --> Running transaction check
    ---> Package dosfstools.x86_64 0:3.0.9-4.el6 will be erased
    --> Finished Dependency Resolution
    Dependencies Resolved
    =======================================================================
    Package             Arch            Version               Repository      Size
    =======================================================================
    Removing:
    dosfstools          x86_64          3.0.9-4.el6           @base          197 k
    Transaction Summary
    =======================================================================
    Remove        1 Package(s)
    Installed size: 197 k
    Is this ok [y/N]: y
    Downloading Packages:
    Running rpm_check_debug
    Running Transaction Test
    Transaction Test Succeeded
    Running Transaction
     Erasing    : dosfstools-3.0.9-4.el6.x86_64                                1/1
     Verifying  : dosfstools-3.0.9-4.el6.x86_64                                1/1
    Removed:
     dosfstools.x86_64 0:3.0.9-4.el6
    Complete!

Fast Retransmit (빠른 재전송)

  • 타이머의 타임 아웃 기간이 상대적으로 너무 길어 타이머가 종료되기 전이라도 중복된(duplicate) ACK를 3번 받으면 바로 재전송을 하는 기능 → 수신측이 기다리는 순서번호의 세그먼트보다 큰 순서번호의 세그먼트가 3개 도착할 경우를 의미
  • 손실된 패킷을 재전송하기 전 발생하는 긴 지연시간을 줄여줌
  • Fast Retransmit는 또 다른 말로, Triple-Duplicate-ACK이라고 하며 3개의 중복된 ACK를 받으면 재전송하는 것
  • Duplicate ACK 수신을 통해 세그먼트가 손실되었음을 감지 → 손실된 경우 수신 측은 여러 중복 ACK들을 발생시킴
  • 송신자는 동일한 데이터에 대해 3개의 ACK를 수신하면 ACK된 데이터 이후의 세그먼트가 손실된 것으로 가정
    1. Duplicate ACK는 비정상적인 순서(out-of-order)의 패킷이 수신될 시 수신 측에서 발생시킴 → 현재까지 ACK가 완료된 패킷 다음 패킷이 손실 난 상태에서 다음 패킷들이 계속 수신되는 경우
    2. Host A에서 보낸 2번째 패킷이 손실되어 Host B는 3, 4, 5번째 패킷 수신 시에 duplicate ACK를 보내게 됨
    3. RTO 타이머가 종료되기까지 시간이 남았지만, Host A는 2번째 패킷이 손실된 것으로 가정하고 재전송함

Flow Control(흐름 제어)

  • TCP 송신자가 데이터를 너무 빠르게 또는 너무 많이 전송하여 수신버퍼가 오버플로우(Overflow)하는 것을 방지
  • Flow Control(흐름 제어)는 송신측과 수신측의 데이터처리 속도 차이를 해결하기 위한 기법
    1. 수신측이 송신측보다 속도가 빠른 것은 아무 문제가 되지 않음
    2. 송신측이 수신측보다 속도가 빠르면 문제가 발생
  • 수신측에서 수신된 데이터를 처리해서 윗 계층으로 서비스 하는 속도보다 송신측에서 보내는 데이터 속도가 더 빠르다면, 수신측에서 제한된 저장용량(일반적으로 큐)을 초과하여, 도착하는 데이터의 손실을 가져올 수있음
  • 속도 차이로 인해 발생한 데이터의 손실을 복구하기 위해 불필요하게 응답과 재전송의 데이터가 필요 → 다시 송신측과 수신측간에 이동
  • 수신측의 저장공간이 초과되어 발생하는 불필요한 재전송을 줄이기 위해 강제로 송신측의 데이터 전송을 줄임
  • Flow Control(흐름 제어)는 속도를 일치시키는 서비스 → 애플리케이션 프로세스의 읽는 속도 = 송신자가 데이터를 전송하는 속도
  • Receive Window(rwnd)

    1. 수신버퍼의 가용 바이트 수로, 송신 윈도우 크기를 결정

    2. 수신 버퍼보다 작아야함 → 초과하면 오버플로우 발생

      LastByteRcvd - LastByteRead <= RcvBuffer
      [밑에서 수신 받은 번호 - 위로 올려 보낸 번호 = 수신했지만 상위계층으로 전송되지 않은 데이터들]
      
      rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)
       = RcvBuffer - (수신했지만 상위 계층으로 전송하지 않은 데이터들)

  • 수신자는 TCP헤더에 수신버퍼안에 있는 여유공간(Receive Window, rwnd) 값을 포함함으로써 버퍼에 공간이 있음을 송신자에게 알림

  • 수신버퍼의 크기는 소켓의 옵션을 통해 설정되는데 디폴트 값이 4096바이트

1. Stop and wait 방식

  • 매번 전송한 패킷에 대해 확인응답을 받아야만 그 다음 패킷을 전송하는 방법

2. 슬라이딩 윈도우 기법

  • 수신 측에서 설정한 윈도우 크기만큼 송신 측에서 확인 응답 없이 세그먼트를 전송할 수 있게 하여 데이터 흐름을 동적으로 조절하여 제어하는 기법
  • 슬라이딩 윈도우 기법을 통하여 송신 버퍼의 범위는 수신 측의 여유 버퍼 공간을 반영하여 동적으로 바뀜으로써 흐름제어를 수행


Congestion control(혼합 제어)

  • 호스트와 네트워크 상의 데이터처리를 효율적으로 하기 위한 기법
  • 송신측의 데이터 전달과 네트워크의 처리속도 차이를 해결
  • 송신측의 데이터는 지역망이나 인터넷으로 연결된 대형 네트워크를 통해 전달 → 네트워크 상의 라우터가 항상 바쁜 상태임
  • 하나의 라우터에 데이터가 몰려 혼잡한 경우에, 라우터는 자신에게 온 데이터를 모두 처리할 수 없음
  • 호스트들은 라우터에서 손실된 데이터를 재전송을 하게 되고 결국 혼잡을 가중시켜 오버플로우나 데이터 손실을 발생
  • 네트워크의 혼잡을 피하기 위해 송신측에서 보내는 데이터의 전송 속도를 강제로 줄이게 됨

1. Slow start

  • 윈도우 크기를 2배로 늘림
  • 혼잡현상이 발생하면 창 크기를 1로 떨어뜨림
  • 혼잡현상이 발생했던 창 크기의 절반까지는 이전처럼 지수 함수 꼴로(2배로) 창 크기를 증가시키고 그 이후부터는 완만하게 1씩 증가시킴

2. Fast Recovery

  • 혼잡한 상태가 되면 창 크기를 1로 줄이지 않고 반으로 줄이고 선형 증가시키는 방식


참고 URL : https://pcmc.tistory.com/entry/190618-TCP-Retransmission
참고 URL : https://movefast.tistory.com/36
참고 URL : https://dlee0129.tistory.com/204

  • 링 버퍼(Ring Buffer)는 원형 큐로 약간의 개량해서 사용
  • 링 버퍼는 가변적인 데이터를 처리
  • 기본적으로 네트워크의 처리 단위 : 1/1000 초
  • 기본적으로 CPU의 처리 단위 : 1/1000000 초 이하
  • 네트워크와 CPU는 처리 속도가 수 백에서 수 만 배 차이 발생
  • 네트워크의 통신에서 패킷의 크기가 고정되어 있으면 처리가 쉬움
  • 필요 없는 데이터까지 포함한 가변적인 크기를 가진 패킷을 사용하는데 가변 크기를 가진 패킷을 저장하기 위한 링 버퍼(Ring Buffer)라는 자료구조가 사용 → 필요 없는 데이터까지 입/출력에 포함되어 있어서, 가변 데이터를 처리할 때 네트워크의 성능을 떨어짐
  • 링 버퍼는 분해된 패킷을 합치거나 완성되지 않은 자투리 패킷을 완전한 패킷으로 만들 수 있는데 편리
  • 링 버퍼는 Byte 단위로 저장할 공간만 있으면 동작함.
  • FIFO 기반의 일반적인 선형 큐의 메모리가 꽉 차게되면 Overflow가 발생 하지만 링 버퍼(Ring Buffer)는 head와 tail이 붙어 있는 형태의 큐를 구성으로 dropped 되어 유실되는 packet을 방지 가능

Network Ring Buffer Size 설정

  • Ring Buffer는 네트워크 카드의 버퍼 공간
  • 스위치에서 서버로 전달된 패킷의 전달 과정
    1. 네트워크 카드 내 Ring Buffer 에 보관 (NIC 카드 → Ring Buffer)
    2. 커널의 Socket RCV Buffer로 이동 (Ring Buffer → Socket RCV Buffer)
    3. User Application의 read 함수를 통해 전달 (Socket RCV Buffer → Application의 read()가 값 읽음)
  • Kernel의 Socket RCV Buffer가 여유가 있더라도 Ring Buffer Size가 작다면 중간 병목(bottleneck)이 발생 → Ring Buffer는 가능하다면 Maximum 값으로 설정해주는 것이 권장

  • 리눅스에서는 패킷 송수신시 1계층 물리적 케이블을 통하여 NIC로 packet이 수신 되면 가장 먼저 Ring Buffer 라는 영역에 보관한 뒤에 처리


  • Linux 상에서 NIC의 Ring Buffer(Current, Maximum) 값은 ethtool -g 명령어를 통해 확인 가능

    1. eth1 maximum으로 처리 가능한 ring buffer size는 4096임

    2. eth1 Current으로 처리 가능한 ring buffer size는 512으로 설정

    3. 리눅스 상에서packet 의 drop 과 error 를 줄이기 위해서 maximum 과 Current 동일하게 설정하는 것이 좋음

      # interface의 경우 최대 값이 4,096이지만 현재 설정 값은 512
      $ ethtool -g em1
      Ring parameters for em1:
      Pre-set maximums:
      RX:             4096
      RX Mini:        0
      RX Jumbo:       0
      TX:             4096
      Current hardware settings:
      RX:             512
      RX Mini:        0
      RX Jumbo:       0
      TX:             512

  • ethtool -G 명령어에 해당 파라미터를 maximum 값과 동일하게 설정한 뒤 설정 값을 변경

    # ethtool -G 명령어를 통해 ring buffer를 최대 값으로 설정
    $ ethtool -G em1 rx 4096
    $ ethtool -G em1 tx 4096
    
    # 변경된 ring buffer 내용 확인
    $ ethtool -g em1
    Ring parameters for em1:
    Pre-set maximums:
    RX:             4096
    RX Mini:        0
    RX Jumbo:       0
    TX:             4096
    Current hardware settings:
    RX:             4096
    RX Mini:        0
    RX Jumbo:       0
    TX:             4096



Network Ring Buffer Size 확대 영구적으로 등록

  • 대부분의 Linux 설정과 같이 명령어는 현재 메모리 상의 값을 변경하기 때문에 재부팅 시에는 이전 값으로 원복됨

  • 영구적으로 변경하기 위해서는 Network script 내 해당 Interface에 관련 설정 값을 추가해주는 것이 필요

  • 아래와 같이 스크립트 파일 내 ETHTOOL_OPTS 옵션을 추가한 후 해당 설정 값을 입력 → rx/tx의 최대 값을 확인 후 작성 필요

    $ cat /etc/sysconfig/network-scripts/ifcfg-em1
    TYPE=Ethernet
    BOOTPROTO=static
    DEFROUTE=yes
    NAME=em1
    DEVICE=em1
    ONBOOT=yes
    IPADDR=1.255.156.21
    NETMASK=255.255.255.224
    GATEWAY=1.255.156.1
    ETHTOOL_OPTS="-G ${DEVICE} rx 4096 ; -G {$DEVICE} tx 4096"

  • 재부팅시에 Network Ring Buffer Size 확대 명령어 실행 → rc-local.service 사용

    $ vi /etc/rc.local
    # 아래의 값이 등록
    ethtool -G eth1 rx 4096
    ethtool -G eth1 tx 4096



※ rc-local.service를 실행하는 방법

  1. rc-local.service를 실행할 수 있는 환경 적용
    $ echo -e "\n[Install]\nWantedBy=multi-user.target" >> /usr/lib/systemd/system/rc-local.service
    $ chmod u+x /etc/rc.d/rc.local
  1. rc-local.service 실행

    /bin/systemctl daemon-reload
    /bin/systemctl restart rc-local.service
    /bin/systemctl enable rc-local.service
    
    # rc-local.service가 rebooting에도 실행되는 지 확인
    /bin/systemctl list-unit-files | grep rc.local

  • TCP는 신뢰성 있는 통신을 위해 자신이 보낸 패킷에 대해 ACK 확인 → 보낸 쪽에서는 반드시 받는 쪽이 잘 받았다는 신호를 주어야 다음 전송을 하게 됨

  • TCP는 송신에 대한 응답이 오지않는 경우 일정시간을 대기 후에 다시 재전송함

  • 송신자는 패킷을 송신하고 나면 별도로 정의된 Timer를 시작 → Timer의 시간이 만료되면 다시 패킷을 전송


  • TCP Retransmission과 RTO(Retransmission Timeout)과 RTT(Round Trip Time)를 학습하는 이유

    1. 서버와 네트워크 장비의 성능이 좋은 환경에서는 사실 200ms의 RTO_MIN 값은 너무 큰 값일 수 있음
    2. RTO_MIN이 너무 작으면 재전송이 너무 자주 일어나게 됨 → 재전송이 자주 발생하면, 부하를 일으켜 시스템의 성능과 서비스 응답 속도에 악영향을 끼칠 수 있음
    3. 서버와 네트워크 환경에 따라서 RTO 값을 조절 필요


  • ACK 패킷 손실에 따른 재전송
    1. Client가 보낸 SYN에 대한 ACK를 받지 못하면 보냈던 SYN을 다시 보내게 됨
    2. Retransmission Timer라는 커널 타이머에 의해 동작 SYN 재전송 시간 결정

Retransmission 종류

  • Retransmission이 발생하는 3가지 상황에서 공통점 → "Timeout 시간 안에 ACK를 받지 못했다."
  • Retransmission이 발생하는 경우에 TCP Protocol이 할 수 있는 최선의 방법은 Timeout 시간을 정의하는 것
    1. Timeout 시간이 지나치게 짧으면 재전송 패킷의 낭비 발생
    2. Timeout 시간이 지나치게 길면 패킷이 손실되었을 때 에도 기다려야하는 시간이 너무 길어짐
  • Timeout 기간에 대한 기준을 정의할 때 적절한 기준 시간 → RTO(Rtransmission Timeout)라는 개념을 사용

1. Retransmission : Packet lost

  • 재전송이 발생할 수 있는 첫 번째 상황
  • 송신자는 패킷을 보냈지만, 어떤 이유에서인지 중간에 유실되어 수신측에 도달하지 못함
  • 수신측은 당연히 패킷이 도착하지 않았으므로 ACK를 보내줄리가 없고, 송신자의 Timer는 만료됨

2. Rertransmssion : ACK lost

  • 재전송이 발생할 수 있는 두 번째 상황
  • 송신자가 패킷을 보냈고, 수신 측 또한 응답으로 ACK를 보냄
  • 수신자의 ACK 응답이 중간에 유실되어 송신자에게 도착하지 못하고, 송신자의 Timer는 만료됨

3. Retransmission : Early Timeout

  • 재전송이 발생할 수 있는 세 번째 상황.
  • 송신자가 패킷을 보냈고, 수신 측에서 응답으로 ACK를 보냄
  • 네트워크 지연이 발생해서 송신자의 Timer가 만료되어버린 후에 ACK가 송신자에게 도착함


RTO(Retransmission Timeout)과 RTT(Round Trip Time)

  • RTO(Retransmission Timeout) → 타이머가 작동하는 시간을 의미

  • RTT(Round Trip Time) → 네트워크 통신을 하는 두 노드 간에 패킷이 전달되는데 소요된 시간을 의미

  • 종단 간 거리가 멀면 멀수록 RTT 값을 커지게 됨

  • RTT는 RTO의 값을 결정하는데 아주 중요한 요소가 됨


  • RTO는 내부적으로 복잡한 계산식을 거친 후 동적으로 설정 → RTT 값을 기반으로 계산함

    1. 두 종단 간 통신이 이루어지는 첫 번째 SYN 패킷에 대한 RTO는 어떻게 결정되는가?
    2. TCP Handshake를 하기 위한 첫 번째 SYN 패킷은 상대방과의 RTT에 대한 정보가 전혀 없기 때문에 계산이 불가능 → 지정된 값을 사용
    3. 최초의 RTO 값을 InitRTO이라고 부름 → OS 마다 값이 조금씩 다르지만, Linux에서는 1초로 되어 있음
    4. 1초 → 2초 → 4초 이런 식으로 InitRTO 값은 2의 제곱수로 늘어남
    5. RTO는 운영체제 커널에 정의 → 운영체제 별로 초기값을 갖고 있지만, 모든 네트워크 상황은 다르므로 RTO는 동적으로 변함
    6. RTO 참고 자료 → https://www.rfc-editor.org/rfc/rfc6298.txt

1. SRTT(SampleRTT)

  • RTO는 RTT에 의해서 변하는데, RTT는 호스트 간 송신에 대한 응답을 받기까지 걸리는 시간을 의미
  • SampleRTT를 측정된 RTT → 송신자의 Original Transmission에 대한 ACK를 받기까지의 시간을 SampleRTT로 설정
  • ACK 받기까지 시간이 오래 걸려 재전송이 발생했을 경우, 응답해온 ACK가 초기 응답인지 재전송에 대한 응답인지 구분하기가 어렵움 → Retranmission에 대한 ACK인지 송신자는 판단 불가

2. Karn / Partridge Algorithm

  • RTO Timer가 만료되면 RTO 값을 2배로 늘어남 → Exponential Backoff 라고함
  • SampleRTT는 송/수신이 완료된 전송에 대해서만 값을 기록
  • SampleRTT 값을 Computed RTO를 도출하는 데 사용



애플리케이션 타임아웃

  • InitRTO의 경우는 1초로 설정되어 있기 때문에 애플리케이션의 타임아웃은 1초보다 큰 값으로 설정 필요 (InitRTO는 TCP의 시간)
  • 세션이 연결된 상황에서 재전송은 RTT를 기반으로 생성되기 때문에 대부분 1초를 넘기지 않음
  • 세션이 연결되어 있지 않는 상황에서는 TCP Handshake를 맺는 과정에서의 재전송은 최소 1초 소요되기 때문에 애플리케이션에서 타임아웃을 1초로 설정한다면 재전송으로 커버 가능한 통신을 타임아웃 에러로 끊어 버리게 됨
  • 커넥션 풀 방식으로 네트워크 세션을 미리 만들어 두고 통신하는 경우에는 InitRTO가 발생할 일이 없기 때문에 더 작은 값으로 설정해도 됨


RTO_MIN

  • RTO 값에 영향을 주는 다른 요소 → RTO_MIN 값으로 RTO의 최솟값을 의미

  • 별도로 설정하지 않았다면, RTO_MIN의 기본 값은 200ms로 되어 있음 → RTT가 아무리 작아도 RTO값은 200ms 밑으로 내려갈 수 없음을 의미

  • RTO_MIN 변경 URL : https://unix.stackexchange.com/questions/210367/changing-the-tcp-rto-value-in-linux

  • 현재 설정되어 있는 RTO값 확인 → Linux에서는 ss -i 명령을 이용해서 현재 통신 중인 세션의 RTO 값을 확인 가능(RTO 값이 235)

    $ ss -i
    tcp    ESTAB      0      2384                                                        211.212.37.175:snapenetio                                                                 1.214.216.250:linktest-s
           cubic wscale:8,7 rto:235 rtt:34.161/18.592 ato:40 mss:1460 rcvmss:1168 advmss:1460 cwnd:8 ssthresh:7 bytes_acked:25341 bytes_received:11268 segs_out:275 segs_in:383 send 2.7Mbps lastsnd:2 lastrcv:6 lastack:6 pacing_rate 5.5Mbps unacked:8 retrans:0/1 rcv_space:29200

  • RTO_MIN 변경은 ip route 명령어를 통해 변경 → 100ms로 RTO_MIN을 변경한 후에 ss -i 명령으로 RTO 값이 변해있는 것을 확인(RTO값이 120)

    1. ip route 명령어를 통해 기존 게이트웨이 rto_min 확인
      $ ip route
      default via 211.212.37.161 dev eno3 proto static metric 100
      172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
      192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
      211.212.37.160/27 dev eno3 proto kernel scope link src 211.212.37.175 metric 100
    2. ip route 명령어를 통해 기존 게이트웨이의 rto_min 변경
      # 형식 : ip route change default via <default gw> dev <ethernet> rto_min 100
      $ ip route change default via 211.212.37.161 dev eno3 proto static metric 100 rto_min 100ms
    3. ip route를 통해 게이트웨이 RTO_MIN 추가 확인
      $ ip route
      default via 211.212.37.161 dev eno3 proto static metric 100 rto_min lock 100ms
      172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
      192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
      211.212.37.160/27 dev eno3 proto kernel scope link src 211.212.37.175 metric 100
    4. RTO_MIN이 100ms으로 변경하였기에 RTO 값이 기본 RTO_MIN값인 200ms보다 떨어져 있음을 확인
      $ ss -i
      tcp    ESTAB      0      1168                                                        211.212.37.175:snapenetio                                                                 1.214.216.250:linktest-s
        cubic wscale:8,7 rto:145 rtt:44.372/5.203 ato:40 mss:1460 rcvmss:1168 advmss:1460 cwnd:6 ssthresh:5 bytes_acked:103277 bytes_received:63924 segs_out:1502 segs_in:2153 send 1.6Mbps lastrcv:8 pacing_rate 3.2Mbps unacked:5 retrans:0/2 rcv_rtt:535816 rcv_space:29364

참고 URL : https://pcmc.tistory.com/entry/190618-TCP-Retransmission
참고 URL : https://brunch.co.kr/@alden/15

  • 이더넷 인터페이스 기능 중에 TOE(TCP offload engine)가 있음
  • TOE는 NIC(Network Interface Cards)에서 사용되는 기술로, 보통 운영체제 상에서 처리되는 TCP/IP 스택을 네트워크 컨트롤러로 내려서 처리
  • 네트워크 처리가 크게 필요한 기가비트나 10G 기가비트같은 고속네트워크에서 유용하게 사용
  • 처음 TCP는 저속의 네트워크 속도에서 이용되었는데, 지금의 통신속도와 비교해 보면 통신속도는 크게 증가
  • 시스템에서 동작할 수 있는 여유자원은 상당히 제한적


TCP 프로토콜을 처리하는데 있어서 오버헤드를 가져오는 요소

  1. 3 way 핸드쉐이크 과정을 통한 연결
  2. 체크섬, 시퀀스 넘버 계산
  3. Packet acknowledgement 와 congestion 제어를 위한 슬라이딩 윈도우 계산
  4. 연결 해제


TCP 프로토콜의 오버헤드 기능을 전용 하드웨어 구현 → TCP offload engine

  • CPU 는 다른 작업을 할 수 있도록 여유를 줌
  • 과거에는 몇몇 제한적인 NIC 만이 TOE 를 지원하였지만 지금은 대부분 NIC에서 TOE를 지원
  • TOE 구현은 오프로드 정도에 따라 부분적 오프로딩과 전체(Full offloading)오프로딩으로 구분
    1. 전체 오프로딩
      • TCP/IP 패킷을 처리하기 위한 TCP연결설정, 타임아웃,오류처리 등과 같이 TCP/IP 스택을 하드웨어로 구현
    2. 부분적 오프로딩
      • 체크섬 및 데이터 송수신 관련한 기능만을 구현
  • 일반적으로 TCP/IP 의 1bit/s 를 처리하는데는 CPU 1 헤르츠가 필요
  • 5Gbit/s (메가로 환산하면 625MB/s) 네트워크 트래픽을 처리하기 위해서는 5GHz CPU 가 필요
  • 5Gbit/s 를 처리하기 위해서는 2.5GHz 듀얼코어 CPU 가 필요
  • TOE 기능을 이용해 CPU 자원 사용을 줄여주게 되어 TCP/IP 처리가 많은 경우에는 TOE 를 지원하는 기능이 그렇지 않은 경우보다 더 많은 작업(시스템 관점에서)을 처리 가능


기본적으로 리눅스 커널에서는 TOE 하드웨어를 지원 X

  • 커널상에서 직접 지원하지 않는 이유
    1. 보안적 이슈 → TOE 펌웨어는 소스가 공개되어 있지 않아, 보안적으로 문제가 발생할 경우 해결할 방법이 없음
    2. 복잡성도 증가
    3. 하드웨어적인 여러 제약 발생

참고 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=hymne&logNo=220945826028

점보프레임(Jumbo Frame)

  • 기본적으로 사용하는 MTU(Maximum Transmission Unit) 값은 1500 바이트
  • 실제 전송시에는 프레임 헤더를 붙이면 18 바이트가 추가되어 기본적으로는 1518 바이트가 됨 → 이더넷 헤더가 18 바이트(Link Layer)
  • 점보프레임은 프레임 크기를 크게 늘려주는 것으로, 9000 바이트까지 MTU를 확장시켜 줌
  • 처음 이더넷 프레임으로 1500 바이트가 사용된 것은 과거 낮은 통신속도와 비교적 높게 발생되었던 에러 비율 때문임 → 데이터를 전송하다가 에러가 발생되면 단지 1500 바이트 부분만 에러를 정정하여 재전송하면 됨
  • 각 프레임은 네트워크 하드웨어와 소프트웨어적으로 프로세싱하는 것이 필요 → 프레임 사이즈가 커진다면 시스템에서 전송하기 위해 사용되는 처리 CPU가 더 줄어듬
  • 9000 바이트 이상으로 커진다면 데이터를 자르는 기준이 적어지므로 빠른 속도로 전달 가능 → 한번에 1500 바이트가 아닌 9000 바이트를 전송
  • 하드웨어 성능은 워낙 좋아졌기 때문에 점보프레임으로 인한 성능 향상은 그리 크지 않음
  • 점보프레임이 2000년대 초에는 어느 정도 효과를 볼 수 있었을지 몰라도 빠르게 발전하는 하드웨어 속도에 비하면 프레임을 나누기 위한 CPU 사용은 적음
  • 점보프레임(Jumbo Frame)을 사용할 때 효율적인 성능 향상를 얻을 수 있는 방법은 좋은 하드웨어를 사용하지 않는 것 → 현재 하드웨어 발전 상황에서는 큰 차이 X
  • 점보프레임을 사용하기 위해서는 스위치, NIC 카드등에서 지원 필요 → 요즘 사용되는 장비들은 대부분 지원


점보프레임이 설정된 패킷을 덤프

  • 데이터 크기가 8920 바이트나 되는 것을 확인 가능

시스템상에서의 설정은 MTU 값을 변경

  • 설정 전에는 MTU가 1500
  • 리눅스의 경우 커널 2.6.17 이상이면 지원됨
  • ip route 명령어를 통해 MTU 확인

    $ ip route get 111.6.0.25
    111.6.0.25 dev bond1  src 111.6.0.30
      cache  mtu 1500 advmss 1460 hoplimit 64

  • ifconfig 명령어를 통해 MTU 확인

    $ ifconfig eth6
    eth6      Link encap:Ethernet  HWaddr [삭제]
            UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
            RX packets:2892 errors:0 dropped:0 overruns:0 frame:0
            TX packets:2728 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000
            RX bytes:256450 (250.4 KiB)  TX bytes:2785780 (2.6 MiB)
            Interrupt:32 Memory:d8000000-d8012800

  • ifconfig 명령어를 통해 인터페이스의 MTU를 변경

    $ ifconfig eth6 mtu 9000

  • ip route 명령어를 통해 MTU 확인

    $ ip route get 111.6.0.25
    111.6.0.25 dev bond1  src 111.6.0.30
      cache  mtu 9000 advmss 8960 hoplimit 64

  • ifconfig 명령어를 통해 MTU 확인

    $ ifconfig eth6
    eth6      Link encap:Ethernet  HWaddr [삭제]
            UP BROADCAST RUNNING SLAVE MULTICAST  MTU:9000  Metric:1
            RX packets:2892 errors:0 dropped:0 overruns:0 frame:0
            TX packets:2728 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000
            RX bytes:256450 (250.4 KiB)  TX bytes:2785780 (2.6 MiB)
            Interrupt:32 Memory:d8000000-d8012800



tcpdump 명령어로 트래픽을 캡쳐 설정

  • 캡쳐 크기를 늘려줘야 패킷을 캡처할 수 있기에, -s 옵션으로 9000 바이트를 지정
  • tcpdump 명령어는 기본 MTU이 1500임으로 점보 프레임을 패킷 캡처를 위해서는 MTU 9000으로 변경 필요
    $ tcpdump -i bond1 -s 9000 -n -w jumbo.pcap
    tcpdump: listening on bond1, link-type EN10MB (Ethernet), capture size 9000 bytes


tshark 명령어로 프레임 크기 확인

  • 1500 바이트 이상의 크기가 많이 보이는 것을 확인 가능
    $ tshark -i bond1 -e frame.len -Tfields
    9014
    9014
    66
    9014
    9014
    66
    9014
    430
    66
    114
    4210
    66
    114
    9014
    7550
    66
    114
    114
    66
    4210
    9014
    66
    9014
    9014
    66
    6038
    114
    9014
    ^C1947 packets captured


네트워크 인터페이스에 MTU=9000으로 지정

  • CentOS, 레드햇 계열은 /etc/sysconfig/network-script/ifcfg-eth0 파일에 MTU=9000으로 설정 추가 후 네트워크 재실행
    $ vi /etc/sysconfig/network-script/ifcfg-eth0
    # 중략
    # 맨 아래에 추가
    MTU=9000

참고 : http://www.packetinside.com/2012/03/jumbo-frame.html

  • 패킷 덤프를 하다보면 MTU 이상의 패킷 사이즈를 보는 경우가 있음
  • 10G 네트워크 링크에서 MTU가 1500 바이트이면 대략 초당 800,000개 패킷 통신 → 패킷처리를 위해 CPU 오버헤드를 발생 가능
  • 오버헤드를 줄이기 위해 MTU 증가 필요 → 점보프레임인 9000 바이트로 늘리면 한번에 더 큰 패킷을 처리 가능하지만, 인터넷에 연결되어 있는 모든 구간이 MTU 값을 9000 바이트로 사용 X
  • 보통 일반적인 네트워크는 MTU를 1500 바이트로 사용 → 내부 네트워크라면 모르지만 인터넷 구간에서는 현실적으로 점보프레임을 사용이 힘듬
  • 네트워크 어뎁터에서 TCP 세그먼테이션 오프로드 기능 사용→ TSO(TCP Segmentaion Offload)
  • TSO 호환 가능 어뎁터를 통해 커널상에서 아웃바운드 데이터(밖으로 패킷)를 보낼때 데이터를 재-세그먼트 하여 작게 보냄 → 호스트 컴퓨터의 CPU 자원 사용면에서도 효율적
  • TSO 외에 GSO(Generic segmentation offload)도 있음
  • GSO는 TCP에만 한정을 두지 않는다는 장점이 있지만 데이터 전송에서만 동작하고 받는쪽에서는 동작 X
  • 추가적으로 LRO(Large Receive Offload)도 있음 → 들어오는 패킷에 대해 한번에 Merge를 진행 (리눅스 기반의 10G 드라이버들이 LRO 를 넓게 사용)


TOE(TCP Offload Engine)이란

  • MTU 이상의 크기와 연관 있는 기능 → generic-receive-offload가 on

  • generic-receive-offload가 on으로 오프로드 기능이 동작하여 패킷을 덤프할 시에 패킷의 사이즈가 다르게 보임

  • GRO(generic-receive-offload)을 ON하면 네트워크 어뎁터에서 패킷을 처리해 주기에, 패킷 캡쳐 프로그램에서는 크기가 큰 패킷 사이즈를 확인 가능


  • ethtool 명령어에 -k 옵션을 통해 네트워크 인터페이스의 정보를 확인

    $ ethtool -k eth0
    Offload parameters for eth0:
    rx-checksumming: on
    tx-checksumming: off
    scatter-gather: off
    tcp-segmentation-offload: off
    udp-fragmentation-offload: off
    generic-segmentation-offload: off
    generic-receive-offload: on
    large-receive-offload: off
    rx-vlan-offload: on
    tx-vlan-offload: on
    ntuple-filters: off
    receive-hashing: off

1. GRO (generic-receive-offload) 기능 ON

  • GRO 기능이 On 되어 있는 경우는 아래 그림과 같이 패킷 사이즈가 2762, 4017, 3538 과 같이 MTU 값 이상으로 출력

2. GRO (generic-receive-offload) 기능 OFF

  • gro 기능을 off 하고 패킷 캡쳐를 다시 해보면 패킷 데이터 전송크기가 1414로 동일

    # ethtool -K eth0 gro off
    # ethtool -k eth0
    Offload parameters for eth0:
    rx-checksumming: on
    tx-checksumming: off
    scatter-gather: off
    tcp-segmentation-offload: off
    udp-fragmentation-offload: off
    generic-segmentation-offload: off
    generic-receive-offload: off
    large-receive-offload: off
    rx-vlan-offload: on
    tx-vlan-offload: on
    ntuple-filters: off
    receive-hashing: off

  • GRO 기능 off 그림


참고 : http://www.packetinside.com/2013/02/mtu-1500.html

+ Recent posts