배치 작업을 할때, 이용할 수 있는 도구는 많지만 개인적으로 가장 손꼽는 프로그램은 Linux 에서 기본적으로 제공해주는 크론탭(Crontab) 이라고 생각한다. 사용하기도 쉽고 강력한 스케줄링 기능을 할 수 있다.


다음은 크론탭의 사용방법이다.


- crontab -e : 크론탭 편집기 실행. VI 가 기본으로 실행된다.

- crontab -i : 크론탭의 내용 조회


- 크론탭 작성 방법


*                *                    *                *                *

분(0-59)       시간(0-23)       일(1-31)       월(1-12)       요일(0-7)


- 매분 실행

* * * * * /home/script/test.sh


- 특정 시간 실행

# 매주 월요일 오전 5시에 test.sh 실행

0 5 * * 5 /home/script/test.sh


- 반복 실행

# 매일 매시간 0분, 20분, 40분에 test.sh 실행

0, 20, 40 * * * * /home/script/test.sh


- 범위 실행

# 매일 1시 10분 부터 30분까지 매분 test.sh 실행

10-30 1 * * * /home/script/test.sh


* 크론탭은 한줄에 한 명령어만 작성해야 하며 #을 통해 주석을 달 수 있다.


또한 실행하는 쉘에 Redirection (>) 을 연결함으로써 출력을 리다이렉트할 수 있으며 이를 통해 로깅이 가능하다.



TCP/IP 전송제어 프로토콜은 신뢰성에 초점을 맞추고 데이터가 신뢰성있게 올바른 순서로 유실되지 않게 빨리 전송할 수 있도록 설계된 프로토콜이다.


TCP 의 기본적인 작동 원리는 다음과 같다.

<TCP hand shake >

<출처 : https://wiki.mikrotik.com/wiki/Manual:Connection_oriented_communication_(TCP/IP)>


TCP 는 통신을 위해 3 way handshake 란 방식을 이용한다. 먼저 통신이 가능한지 SYN 을 보내고, 통신이 가능하다는 SYN-ACK을 받는다. 이 과정에서 문제가 없으면 이제 통신하고자 하는 메시지를 보내고, 양방향 통신이 된다. 이 과정을 3-WAY Handshake 라 하며, 이 과정은 TCP 매 통신 시마다 적용이 되며, 통신이 끝날때에는 SYN 대신 FIN 을 보내서 서로 확인을 받는다. 이러한 과정을 통해 TCP 는 무조건 메시지가 잘 전달되었으며 잘 도착했다는 확인을 받게 되고, 신뢰성을 보장받게 된다. 이러한 특성으로 TCP는 주로 전화에 비견된다. 이러한 TCP 통신을 위한 헤더는 다음과 같다.



위의 헤더 정보에는 보내는 메시지의 목적지 주소와, 순서 보장을 위한 일련 번호(Sequence Number), 에러 체크를 위한 Checksum 정보 등이 포함된다.

그 외에 사용하는 TCP 알고리즘 별로 슬라이딩 윈도우 정보 등 다양한 정보가 포함될 수 있다.


 슬라이딩 윈도우는 패킷의 흐름을 제어하기 위한 메모리 버퍼(Window) 로, 다양한 경우에 대비해서 사용된다. 가령 3WAY Handshaking 중 네트워크 장애 발생이나, 받은 메시지가 중간에 누락이 된 경우 해당 패킷의 재전송이 필요하다. 다음 패킷의 전송을 멈추고 이전 패킷의 전송을 기다리는 Stop And Wait 방식 보다, 훨씬 효율적일 수 있다.


<슬라이딩 윈도우 송신 측>


 위의 그림 처럼 슬라이딩 윈도우는 이미 전송하고 확인이 완성된 부분, 전송했지만 확인되지 않은 부분, 보내지 않았지만 수신자가 수신 준비 된부분, 수신준비 되지 않았으며 송신하지 않은 부분으로 영역을 나누어 네트워크 상황에 따라 포인터를 관리한다.


<슬라이딩 윈도우 수신 측>


 위의 그림은 수신측이다. 받았고 승인한 버퍼를 갖고 있으며 ( 이 버퍼는 나중에 다른 패킷으로 덮어써진다.) 수신자가 아직 받지 못한 부분, 수신준비되지 않았으며 수신하지 않은 부분으로 나뉘며 전송 상태에 따라 포인터를 조정한다.

(관련 내용의 예시를 잘 정리한 블로그는 다음을 참조하기 바란다. http://blog.naver.com/donjobani/30110435544)



 위의 내용들을 바탕으로 한 TCP 의 특징을 정리하자면 다음과 같다.


(1) Connection Oriented : 2개의 endpoint간 연결을 먼저 맺고 데이터 통신을 한다.


(2) Bidirectional byte stream : 양방향 Data stream(Byte stream)


(3) In-order delivery : 송신자가 보낸 순서대로 수신하며 Segment의 데이터 순서 표시를 위한 32비트의 정수를 사용한다.


(4) Reliability through ACK : 송신자는 수신자가 ACK 보내는 것을 체크하고 보내지 않은 데이터를 보관한다.


(5) Flow control : 송신측과 수신측의 처리 속도 차이를 해결하기 위해(특히 수신측이 느린 경우) 지원하는 제어 방식으로 흐름 제어라 불린다. 속도 차이로 전송 누수가 생기는 것을 방지하기 위해서 수신자는 받을 수 있는 버퍼의 크기(Receive window)를 송신자에 전달하여 송신자가 보내는 양을 제어하게 한다.


(6) Congestion control : 통신시 한 Router에 데이터가 몰려 혼잡할 경우, 호스트 들이 데이터 유실 때문에 재전송을 하게 되고 결국 혼잡이 더 늘어나는 악순환이 생긴다. 이를 막기 위해 송신측에서는 Congestion window가 존재하여 허용하는 만큼만 전송하게 하여 혼잡을 제어한다. TCP Vegas, BIC, CUBIC 등의 알고리즘을 사용한다.



 반면 UDP는 이러한 Hand shaking 과정이 없다. UDP 의 통신과정은 단순하다. 단순히 명시받은 IP 주소와 포트로 메시지를 UDP 헤더를 담은 메시지를 보낸다. UDP 헤더가 담긴 메시지를 받으면, 어플리케이션은 해당 메시지를 해독해서 로직을 처리한다. UDP 헤더는 다음과 같다. TCP 헤더보다 많이 단순한 모양이다.


 하지만 TCP 와 다르게 UDP 는 응답값을 기대하면 안된다. 신뢰성이 보장되지 않기 때문에, 중간에 네트워크 이슈로 인해 데이터가 손실되더라도 이를 알아차릴 방법이 없다. 그렇게 때문에 UDP 는 편지에 비유되며, 상대방 IP 주소의 포트에 메시지를 놓고온다고 이해하면 쉽다.


 정리하자면, TCP의 경우 좀 더 시간이 오래 걸리는 무거운 프로토콜이지만 신뢰성이 보장되며 UDP 의 경우 가볍지만 신뢰성을 보장할 수는 없다. 이런 특징 때문에 신뢰성이 중요한 메시지 들은 TCP로, 몇몇 패킷이 누락되어도 상관없는, 가령 이미지나 실시간 스트리밍 들은 UDP 로 구현이 된다.

 물론 몇몇 서비스의 경우에는 비즈니스 로직에 따라 UDP 로 구현하되, 헤더를 커스터마이즈하여 특정 조건에서 신뢰성을 갖으면서 가볍고 빠른 자체 프로토콜을 만들어 서비스 품질을 높이는 경우가 많다.





 Java에서 모든 클래스의 부모 클래스인 Object 클래스는 toString을 비롯해 equals hashCode라는 메서드를 갖고 있다.

즉, 모든 클래스는 toString 과, equals, hashCode 를 갖고 있다고 볼 수 있으며 이는 자바 객체들의 특징이라고 할 수 있다.

여기에서 헷갈리는 부분이 equals와 hashCode 의 차이이며, 아래는 그 내용을 정리한 글이다.



 Equals는 두 객체의 내용이 같은지 동등성(equality)을 비교하며 hashCode는 두 객체가 같은 객체인지 동일성(identity)을 비교하는 역할을 한다.


 즉 hashCode를 사용하면 두 객체의 참조 비교를 하며 완전히 같은지를 판단한다.

 참고로 Java Map put 당시의 hashCode를 기록하므로 hashCode함수를 오버라이딩하여 구현할 시 중간에 값의 변경으로 hashCode가 변경되지 않도록 유의해야 한다.


 다음은 hashCode() 와 관련해서 정의된 규약이다.


-      equals()로 비교시 두개의 오브젝트가 같다면 hashCode() 값도 같아야 한다.


-      Equals()로 비교시 false라면 hashCode() 값은 같을수도 다를수도 있다. 성능을 위해서는 hashCode() 값이 다른 것이 낫다.


-      hashCode() 값이 같다고 해서 equals() true인 것은 아니다. 해싱 알고리즘 문제로 같은 해시값이 나올 수 있다.

 

: 다음은 equals() 와 관련된 규약이다.


-      Reflexive : Object는 그 자신과 항상 equals해야 한다.


-      Symmetric : a.equals(b) 일때 b.equals(a) 는 성립해야 한다.


-      Transitive : a.equals(b) 이고 b.equals(c) 라면 c.equals(a) 는 성립한다.


-      Consistent : equals의 호출은 객체가 변하지 않는 이상 항상 같은 결과를 반환해야 한다.


-      Null comparison : null과의 equals 비교는 NPE가 아닌 false를 반환해야 한다.



위 내용은 다음 블로그를 많이 참조 하였다. 

(http://anster.tistory.com/160, http://iilii.egloos.com/4000476)



+ Recent posts