안녕하세요.

오늘은 자주 사용되는 String과 StringBuilder, StringBuffer에 대해서 포스팅해보겠습니다.

 

 


 

# 공간적 차이

- String

String은 값 변경 시, Heap영역에 공간이 새로 생성됩니다. 추후에 GC에 의해 제거됩니다.

 

- StringBuilder, StringBuffer

이 둘은 값 변경 시, Stack공간에 값을 저장해 값만 바꿔씁니다.

 

-> 따라서 값이 자주 변경된다면 String보다는 StringBuilder, StringBuffer 사용을 권장합니다.

 

 

 

# 시간적 차이

 

글보단 시간측정을 해보겠습니다.

	public static void main(String[] args) throws Exception{
		
        // 1. StringBuilder 시간 측정
		long time1 = System.currentTimeMillis();
		StringBuilder builder = new StringBuilder();
		for(int i=0;i<100000000;i++) {
			builder.append("a");
		}
		long time2= System.currentTimeMillis();
		System.out.println("StringBuilder ::: " + (time2 - time1));
		
        // 2. StringBuffer 시간 측정
		long time3 = System.currentTimeMillis();
		StringBuffer buffer = new StringBuffer();
		for(int i=0;i<100000000;i++) {
			buffer.append("a");
		}
		long time4= System.currentTimeMillis();
		System.out.println("StringBuffer ::: " + (time4 - time3));
		
        // 3. String 시간 측정
		long time5 = System.currentTimeMillis();
		String str = "";
		for(int i=0;i<500000;i++) {
			str += "a";
		}
		long time6= System.currentTimeMillis();
		System.out.println("String ::: " + (time6 - time5));
		
	}

StringBuilder와 StringBuffer는 각각 1억건의 연산을 했을 때,

String은 Heap사이즈가 초과해서? 오래걸려서? 그런지 1억건으로 하니 측정이 안되서 50만건 연산했을 때

각각의 속도를 측정해보았습니다.

 

 

- 결과

결과가 보이시나요? 비교적 적은 50만건만 연산한 String의 속도가 현저히 느린 것을 확인할 수 있었습니다.

1억건씩 연산한 StringBuilder와 StringBuffer는 StringBuilder가 현저히 빠른 것을 볼 수 있었습니다.

 

"? 그러면 StringBuffer는 언제쓰는거지?" 라는 의구심이 들어 찾아보았습니다.

 

StringBuffer는 StringBuilder와 다르게 동기화를 지원하여, 멀티 쓰레드 환경에서 안정성을 가지고 있습니다.

 

 

- 결론

문자열 단순 조회 용도 = String

연산이 (추가,삭제 등 ) 자주 일어날 때에, 단일 쓰레드 환경 -> StringBuilder

연산이 (추가,삭제 등 ) 자주 일어날 때에, 멀티 쓰레드 환경 -> StringBuffer

 

 


자주 사용되는 문자열을 저장하는 객체들에 대해서 알아보았습니다.

보통은 단일 쓰레드환경에서 자주 사용하니 StringBuilder를 잘 기억해놓아야겠네요!

 

감사합니다.

'Java' 카테고리의 다른 글

[Java] 추상 클래스 vs 인터페이스  (0) 2021.09.03
[Java] 접근 제한자란?  (0) 2021.09.02
[Java] Garbage Collector  (0) 2021.08.25
[Java] JVM이란? 정의 및 동작 방식  (0) 2021.08.22
[Java] 특징 1. 객체지향 프로그래밍  (0) 2021.08.21

안녕하세요~ 오늘은 Oracle에서 row를 N개만 추출하는 법에 대해서 알아보겠습니다.

Rownum으로 하는 방법밖에 없는 줄 알았는데 좋은 함수를 발견해서 기록용으로 작성합니다.

Oracle 12c 이상에서만 사용할 수 있다고 합니다.

 


 

1. rownum 

 

현재 테이블의 상태는 다음과 같습니다., rownum을 통해 행 번호를 매길 수 있습니다.

 

SELECT * FROM (
	SELECT rownum rw, sp.* 
	FROM SHOPS.S_PRODUCT sp
    )
	WHERE rw = 1;

한 번 묶고, rownum의 조건절을 통해 n개의 Row를 추출할 수 있습니다.

 

 

2. FETCH FIRST 1 ROWS ONLY

- Oracle 12c 이상에서만 사용할 수 있다고 합니다.

SELECT * 
FROM SHOPS.S_PRODUCT sp
fetch first 1 rows only;

fetch first n rows only 를 통해 더 간단하게 N건의 데이터를 추출할 수 있습니다.

 

 


Oracle에서 N개의 데이터를 추출하는 방법에 대해서 알아봤습니다.

 

감사합니다.

안녕하세요. 오늘은 마이크로서비스의 Service Discovery 역할을 하는 Eureka Server에 대해서 알아볼까 합니다.

 

 


 

Eureka Server란, 

AWS와 같은 Cloud 시스템에서 로드 밸런싱과 실패 처리 등을 유연하게 처리하는 서버입니다.

 

MSA의 핵심 원칙 중 하나인 Service Discovery의 역할을 수행합니다.

Service Discovery란, 어떤 서비스가 특정 서비스를 호출할 때 특정 서비스의 위치(IP, Port)를 알려주는 역할을 말합니다.

 

MSA에서는 Service의 IP 및 Port가 지속적으로 변화하기 때문에 정보를 수동으로 입력하는 것은 비효율적입니다.

 

 

Eureka Server의 동작 과정은 다음과 같습니다.

1. Eureka Client들은 본인의 정보 ( IP, Port, AppName 등 )을 Eureka Server로 전달합니다.

2. Eureka Server에서 필요한 Client의 정보를 Fetch하여 통신합니다.

 

Eureka Client는 등록되면 30초를 주기로 Eureka Server에 heartbeat를 보냅니다.

만약 90초동안 heartbeat를 받지 못하면 Server가 저장한 해당 Client의 정보가 제거됩니다.

 

 


"등록된 서비스들의 정보를 담고 있는 서버로, 서버들 사이에서 로드밸런싱 역할을 한다" 라고 알고 있으면 될 것 같습니다.

아래 참조 글을 거의 참조했으니 참고하시길 바랍니다.

 

참조:

https://sabarada.tistory.com/61?category=822738

'IT 지식' 카테고리의 다른 글

REST, REST API란?  (0) 2021.09.08
HTTP란 ?  (0) 2021.09.07
[MicroService] MSA란? Micro Service Architecture  (1) 2021.08.28

안녕하세요~ 오늘은 MSA 에 대해서 글을 작성해보겠습니다.

 


 

MicroService가 발생하게 된 배경은 보통의 프로젝트 형태인 Monolithic Architecture는 프로젝트 규모가 커질수록, 빌드 시간이 길어지고 유지보수가 힘들다는 특징이 있습니다. 이를 보완하기 위해서 MicroService의 형태가 발생하게 되었습니다.

 

MicroService란,

어플리케이션을 이루는 서비스들을 기능 단위로 쪼개서 구축하는 것을 말하며 각 서비스들은 REST API를 통해 통신합니다.

 

 

장점

1. 수정 사항 및 추가사항이 있는 서비스만 빌드, 배포가 가능합니다.

2. 해당 서비스에 더 적절한 서로 다른 언어나 기술을 사용할 수 있습니다.

 

단점

1. 모니터링이 힘들고, 개발 및 테스트가 까다롭습니다.

2. 모놀로식에 비해 구축 난이도가 어렵습니다.

 

 

보통의 프로젝트 형태인 Monolithic Architeture의 형태는 다음과 같습니다.

MicroService와 반대되는 개념으로, 하나의 서버에서 모든 서비스가 동작하는 것을 말합니다.

 

장점

1. 아키텍처가 단순하고 모든 서비스의 개발환경이 같아 개발이 용이합니다.

2. End-to-End Test(사용자 입장에서의 테스트)가 용이합니다.

 

단점

1. 조금만 수정해도 전체를 다시 빌드하고 재배포해야 합니다.

2. 프로젝트 규모가 커짐에 따라 빌드 시간이 증가하고 유지보수가 힘듭니다.

3. 일부 서비스의 오류가 전체 서비스에 영향을 줍니다.

 

 

MicroService에 장점만 있는건 아니기 때문에, 상황에 따라 적절하게 서비스를 구축해야합니다.

출처: https://wonit.tistory.com/487?category=854727

MSA를 사용하는 대표적인 기업으로는 아마존과 Netflix가 있습니다.

넷플릭스는 2007년 데이터 베이스 손상으로 인해 3일간 서비스 장애를 겪고 나서 고가용성, 유연한 확장성, 빠르고 쉬운 배포 의 장점을 가진 MSA 구조를 채택했습니다. 이 과정에서 경험한 노하우 및 문제 해결 방법을 오픈소스로 공개했습니다.

# Spring Cloud

Spirng Cloud는 Springboot를 기반으로 MSA 구축에 특화된 라이브러리들의 집합입니다. Spring Cloud에는 Eureka, Zuul(springboot 2.4? 2.5 부터 지원안함> Spring Cloud Gateway로 대체) , Histrix, Ribbon 등 많은 넷플릭스 OSS(Open Source Software) 가 통합되어 있습니다.

# Eureka - Service Discovery Server

MSA를 이루는 서비스들은 동적으로 확장 및 축소되는데, 이 인스턴스의 상태를 동적으로 관리하는 서버를 말합니다.

새로운 서비스 인스턴스는 시작될 때 IP, 포트번호 등을 스스로 전송합니다. 이로 인해 운영자들은 서비스를 수평 확장할 때 IP를 신경쓸 필요가 없게됩니다.

# Zuul - API GateWay

API 게이트웨이는 사용자의 Request에 맞는 서비스로 라우팅시켜주는 역할을 합니다. Client 와 Server의 중간다리역할을 한다고 생각하면 됩니다. 사용자에게는 API GateWay만 노출되게 됩니다.

이유로는 적절한 사용자의 요청인지 확인하는 인증, 각 서비스에 대한 요청을 로그로 기록하는 로깅, 요청사항을 구분하는 필터 등을 통해 모든 요청에 대한 관리를 수월하게 하기 위해 필요합니다.

# Ribbon - Client Side Load Balancer

Ribbon은 Cilent에 탑재하는 소프트웨어 로드밸런서입니다.

# Hystrix - Circuit Breaker

특정 서비스에 과부화가 걸려 장애가 발생하면, 전체 서비스에 장애를 전파하는 경우가 있습니다. 이와 같은 현상을 막아주는 역할을 하는 것이 서킷 브레이커입니다. Hystrix는 각 서비스의 오류 상태 및 복구 상태, 오류 내용을 파악하며 장애가 발생하면 통신을 즉시 중단시키고 문제가 발생한 서비스를 격리시킵니다. 문제가 해결될 때 까지 호출을 제한합니다.

또한 정해진 시간내에 호출이 실패하면 대신 동작하는 예외 처리인 Fallback을 지원해 시스템 장애로부터 유연하게 대처할 수 있습니다.

 


 

MicroService에 대해서 알아보았습니다. 감사합니다.

 

 

참고한 사이트

https://wonit.tistory.com/497?category=854728

https://www.samsungsds.com/kr/insights/msa_and_netflix.html

 

'IT 지식' 카테고리의 다른 글

REST, REST API란?  (0) 2021.09.08
HTTP란 ?  (0) 2021.09.07
[MicroService] Eureka Server  (0) 2021.08.29

안녕하세요.

오늘은 Garbage Collection(Collector)에 대해서 포스팅해보려고 합니다.

 

 


 

JVM의 Heap Area에 남은 더 이상 사용하지 않는 인스턴스를 Garbage라고 하며,

이 Garbage를 효과적으로 처리하는 작업을 Garbage Collection. 이를 수행하는 프로그램을 Garbage Collector 라고 합니다.

 

예를 들면 아래와 같은 코드가 있을 때.. 

// 지역 변수일 때
String text1 = "hello";

text1 = "Java";

이전 포스팅에서 알아본 바에 따르면, 위 코드는

 

 

text1은 Stack 영역에 저장이 되고 "hello" 문자열은 Heap 영역에 저장이 됩니다.

text1은 Heap영역의 주소 값을 가지고 있으며 그 주소 값은 hello를 가르키게 됩니다.

이후에 text1이 가르키는 주소 값을 "Java"로 변경했습니다. 

 

그러면 Heap 영역에 저장된 "hello" 값은 어떻게 될까요??

이게 바로 Garbage가 됩니다.

지금은 하나지만, 프로젝트가 규모가 커질수록 쌓이는 Garbage들이 많아질텐데, 이를 관리 안해주면 메모리를 많이 차지하고 있겠죠?

이를 자동으로 관리해주는 프로그램을 Garbage Collector라고 합니다.

 

Garbage Collector는 두 가지의 가설을 전제로 만들어졌습니다.

1. 대부분의 객체는 금방 unreachable 상태가 된다. < 금방 garbage 상태가 된다. >

2. Old 객체가 Young 객체를 참조하는 일은 아주 적게 일어난다. 

 

쉽게 설명하자면 "대부분의 객체가 금방 아무도 참조하지 않는 상태가 되며", "생성된 지 오래된 객체가 최근에 생성된 객체를 참조하는 일은 아주 적게 일어납니다."

라는 것을 전제로 설계되어 만들어 졌다는 뜻입니다.

 

Garbage Collection의 동작 방식을 알아보기 전에 Mark and Sweep, Stop the World 작업에 대해서 알아보겠습니다.

 

- Mark: 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업. ( Reachable 상태와 Unreachable 상태 식별 )

- Sweep: Mark 단계에서 식별된 사용되지 않는 메모리를 제거하는 작업.

- Stop the World: GC 실행을 위해 GC 쓰레드를 제외한 모든 쓰레드의 작업을 멈추는 것을 말합니다. Application이 잠깐 중지되며, GC 알고리즘의 종류에 따라 STW 시간이 다릅니다.

- Compact: GC 알고리즘의 종류에 따라서 존재하는 작업으로, Sweep 후 분산되어 있는 객체들을 Heap의 한 곳(시작 주소)로 모아 메모리의 분산화를 막아줍니다.

 

 

Java 8 버전을 기준으로, Heap영역은 Young Generation과 Old Generation. 이 두 영역으로 나누어집니다.

 

- Young Generation: 새롭게 생성된 객체가 할당되는 영역으로, 이 영역에 대한 GC를 Minor GC라고 합니다.

- Old Generation: Young 영역에서 Reachable 상태를 유지해 살아남은 객체가 복사되는 영역으로, 이 영역에 대한 GC를 Major GC라고 합니다. 

 

# Garbage Collector 동작 과정

1. 새로운 객체는 Eden 영역에 할당됩니다.

 

2. Eden 영역이 꽉차면 Minor GC가 발생하여 Mark and Sweep 과정이 일어납니다.

 

3. Unreachable로 식별된 객체들은 삭제되며 Reachable 상태로 식별된(마킹된) 객체들은 survivor 영역으로 이동하며  Age값이 증가합니다.

< 규칙 :: survivor0 영역에 객체가 있으면, survivor1 영역은 무조건 비워져있어야 합니다. 반대도 마찬가지. >

- 다음 Minor GC가 발생하면 반대편 survivor 영역으로 이동합니다.

 

4. 2~3의 과정이 반복되어, 객체의 AGE값이 특정 값. 임계치에 도달하게 되면 Old Generation으로 이동하게 됩니다. 이를 Promotion이라고 합니다.

 

5. Old Generation이 꽉 차면 Major GC가 발생합니다.

 

 

GC의 종류(알고리즘의 종류)는 다음과 같습니다.

 

1. Serial GC

- GC를 처리하는 쓰레드가 1개라서 다른 GC에 비해 STW 시간이 깁니다.

- Mark and Sweep 후 Compact 과정이 포함됩니다. 

 

2. Parallel GC

- Java 8의 Default GC로, Young 영역의 GC를 멀티 쓰레드로 수행합니다.

- Serial GC에 비해 STW 시간이 짧습니다.

 

3. Parallel Old GC

Parallel GC를 개선한 것으로, Old 영역에서도 멀티 쓰레드로 GC를 수행합니다.

- Mark-Summary-Compact 알고리즘을 수행합니다.

< Sweep: 단일 쓰레드, Summary: 멀티 쓰레드 >

 

4. Concurrent Mark Sweep GC

- STW 시간을 줄이기 위해 고안된 방법으로, 다음 4단계를 거칩니다.

1) Initial Mark: GC Root에서 참조하는 객체들만 식별합니다.

2) Conccurent Mark: 이전 단계에서 식별된 객체들이 참조하는 모든 객체를 추적합니다.

3) Remark: 이전 단계에서 식별한 객체들을 다시 추적하여, 추가되거나 끊긴 객체를 확정합니다.

4) Concurrent Sweep: 최종적으로 Unreachable 객체를 삭제합니다.

- 과정이 많기 때문에 CPU의 부하가 커진다는 단점이 있습니다.

 

5. G1 GC (Garbage First)

- Concurrent를 개선한 것으로, 이전 GC들은 큰 용량의 메모리 적합하지 않습니다. ( Root Set 부터 탐색하기때문에 용량이 크면 탐색 시간이 길어짐 )

- 큰 Heap 메모리에서 짧은 GC 시간을 보장하는 데에 목적이 있습니다.

- Heap 메모리를 물리적인 영역(Young-Old Generation)으로 나눈게 아니라, Region이라는 일정한 크기의 영역으로 나눕니다.

- Region은 최대 2048개로 나뉠 수 있으며, 각각 1~32MB의 크기를 가집니다.

- 핵심은 Heap을 동일한 크기의 Region으로 나누고, Garbage가 많은 Region에 대해 우선적으로 GC를 수행하는 것 입니다.

 

 


 

Garbage Collector가 무엇인지, 어떻게 동작하는지, 종류로는 어떤 것이 있는 지에 대해 알아봤습니다.

 

 

참고 사이트

https://mangkyu.tistory.com/119

https://www.youtube.com/watch?v=Fe3TVCEJhzo

+ Recent posts