라벨이 Java인 게시물 표시

macOS Catalina 버전부터 JDK의 System.loadLibrary 가 에러가 날 때

정말 오래간만에 자바 관련한 블로깅입니다. 불편한 사람들이 있을 것 같아서 정보 공유 차원에서 현재까지 파악한 이슈를 남깁니다. macOS Catalina(10.15.3) 버전부터 JDK의 System.loadLibrary를 통한 dylib 파일 로드가 실패합니다. 이와 관련해서는 크게 두 가지 문제가 관련되어 있습니다. 1. System.loadLibrary 버그 공식 JDK 관련 이슈는 다음 이슈에서 볼 수 있습니다. Java Bug System :  System.loadLibrary fails on Big Sur for libraries hidden from filesystem GitHub :  System.loadLibrary fails on Big Sur for libraries hidden from filesystem System.loadLibrary()를 통한 경로 찾기가 실패하는가 하고 여러 시도를 해보면 곧 System.load()를 통해 dylib 파일을 직접 읽어도 제대로 동작하지 않는다는 것을 알게 될 것입니다. JDK 라이브러리 로딩 버그의 원인(아직 미해결)을 옮겨봅니다. System.loadLibrary 실패 원인 문제 설명:  OSX Big Sur no longer ships with copies of the libraries on the filesystem and therefore attempts to load a native library via System.loadLibrary no longer works. 애플 페이지 내용: New in macOS Big Sur 11.0.1, the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem. C...

Java 15에 Biased Locking이 deprecate 된다.

이미지
최근 릴리스된 Java 15 버전의 new feature를 보다가 깜짝 놀람. JEP 374: Disable and Deprecate Biased Locking Biased locking은 실제로는 synchronized를 통해 lock을 쓰고 있으나 single thread에서 실행되는 경우가 더 많다고 가정하여 이 경우는 lock 오버헤드 없이 실행되도록 자바의 내부 스택에 상태 필드를 유지하는 방식의 최적화이다. 기존 JDK의 util 클래스들이 기본적으로 synchronized를 하도록 구현되어 있었기 때문인데 그후 sync 없는 클래스들이 API에 대부분 추가되었다. 하지만 여전히 java.io 패키지의 스트림 클래스들은 그대로이긴 한데 실제로는 IO를 하지 않는 ByteArray...Stream 같은 류는 biased locking의 여전한 수혜자이고 예전 API 기반으로 설계되어 Hashtable, Vector, Properties 같은 클래스를 인자로 받는 경우도 마찬가지이다. 물론 biased locking은 contentio n이 발생할 때에는 오버헤드가 있다. 이런 낙관적 최적화는 어느쪽이 더 전형적이냐가 분명할 때 효과가 있다. Java 15에서 biased locking을 제거하면 기존 코드들 중 이건 biased locking 덕분에 큰 차이가 없어 하고 넘어갔던 코드들이 모두 영향을 받을 것이다.  15년 가까이 biased locking을 전제로 decision을 했던 터라  약간 난감하다. 물론 가능하면 StringBuilder,ArrayList 등을 쓰는 건 당연했지만 약간 API적으로 선택이 모호한 경우에는 biased locking을 고려하여 lock free 모듈을 만들지 않고 넘어갔던 경우가 계속 떠오른다. (ByteArray stream 같은 경우는 별도로 Lite 클래스를 만들어 쓰긴 했지만 항상 그럴 수 있었던 건 아니다) 제거를 결정한 근거는 대부분 코드들이 lockfree new API로 옮겨갔다...

근래 최고의 Java 혁신은 GraalVM Native Image가 아닐까

이미지
GraalVM의 Native Image가 리눅스 컨테이너에서 Spring Boot 기반 서비스들을 실행하는 데 점점 더 많이 사용되는 이유 중 하나가 메모리 footprint가 기존 서버 JVM처럼 미리 Heap을 전체 할당하는 방식이 아니라는 것일듯. 참고 : Quarkus - SUPERSONIC SUBATOMIC JAVA A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.  GraalVM의 Native Image는 SubstrateVM이라는 유사 JVM(?)을 사용하는데 그야말로 기판에 사용되는 자바 모듈들을 AOT 방식으로 컴파일해서 붙여가는 방식이라서 이렇게 이름을 붙인듯. -Xmx 기본값이 unlimited 이다. 와우! SubstrateVM은 closed world라는 전제로 만들어졌는데 런타임에 사용되는 모듈들은 빌드 타임에도 알 수 있다는 전제이다. 그래서 동적으로 로드되는 자바 코드나 JNI 코드나 다 찾아서 빌드 타임에 미리 함께 빌드되도록 옵션 처리해줘야 한다. 한마디로 상당량의 삽질이 기본 전제된다. ㅠㅠ 그런데 점점 더 활용도가 높아져서 많이 쓰는 모듈들은 (JVM 런타임을 포함해서) 분명 누군가가 이 삽질들을 해놓았을 거라고 기대할 수 있다. 내가 짠 모듈들만 잘 챙기면 많은 경우 해결이 될 것이란 기대... 게다가 graalvm native image는 polyglot이다. 아직 실험적이지만 R과 python 코드를 컴파일할 수 있다. numpy와 pandas 패키지를 포함해서... 서버뿐 아니라 클라이언트 프로그램으로도 java를 좀더 잘 활용할 수 있게 되었다. 대부분 관심이 없겠지만(!) 이제 JavaFX로 작성한 프로그램을 GraalVM Native Image로 쉽게 컴파일할 수 있게 되었다. 윈도우에서 하나의 exe 바이너리로 쉽게 ...

Websocket Java spec에 대한 단상

이미지
WebSocket  프로토콜은   하나의  tcp ( 실제로는  http  확장   형태 )  소켓으로   여러   개의   논리적   연결인   세션  개념을   지원한다 . 그런데  tcp  레벨에서   같은   연결을   사용하기   때문에   논리   세션은   각   특성에   따라   효율적이기   어렵다 .  적당한   크기의   프레임이란   메시지   단위로   잘라서   여러   세션   메시지를   섞어   보내다보니   원래는   하나의   양방향   큐를   구성하는  tcp  연결을   다시   에뮬레이트해야 해서   오버헤드가   있다 . 자바   웹소켓   스펙을   보면   메시지   유형이   스트림이면   큰   메시지라고   간주하여   매   프레임별로   별도의   쓰레드로   보내고   그렇지   않으면   하나의   쓰레드로   보내게   되어있는데   나는   이   스펙은   지나친   쓰레드   모델과   메시지   유형의   커플링이라고   본다 . 오히려   큰   파일일수록   순서대로   하나의   쓰레드에   큐로   보내고   작은 ...

Spring Framework - an inversion of control container

이미지
 2015년 11월 17일에 발표했던 스프링 프레임웍 Spring Framework - Inversion of Control Container from Kyung Koo Yoon

[Java] Java 9의 모듈 시스템에 대한 단상

우여곡절 끝에 자바 9에 jigsaw 즉, Java Platform Module System이 포함되어 출시되었다. 오래동안 사용되던 ClassLoader 기반의 OSGi와 다르게 Java Platform Module System은 JDK 내부적으로 module을 지원한다. 이를 위해 java.lang.ClassLoader 등의 클래스가 module 관련 선언에 있는 내용대로 접근성이 허용되는지를 내부적으로 체크하도록 JDK 코드가 수정되었다. 그 외에도 모듈에 선언된 것 외에는 타 모듈의 클래스를 액세스할 수가 없는데 Class.forName(...)을 통해 Class 객체는 구할 수 있지만 newInstance 등을 통해 인스턴스 객체를 만들려고 시도하는 순간 에러가 나게 된다. 이 점은 기존 코드와 심각하게 비호환되게 하는데 이를 완화하기 위해 java.util.ServiceLoader를 통해서 객체를 만들 수 있도록 하고 있다. (이게 가능하려면 해당 제공 모듈에서 provides를 선언해야만 한다.) 기존의 자바는 클래스로더의 자유도를 기반으로 모듈화를 저해하는 일들을 많이 하는 일들을 많이 해왔다. 특히 프레임웍들은 그러한 형태를 권장해왔다. 모듈에 대한 제어가 없고 이를 통해 더 많은 기능을 제공할 수 있으니까. 자바 9 이후부터는 이러한 모듈화를 저해하는 것들이 많이 줄어들 것 같다. 아니, 새로 작성되는 프로그램들은 자바 9과 쉽게 호환할 수 있도록 자바 코드를 모듈화하여 분리시키는 설계를 항상 선행하여야 할 것 같다. OSGi는 표준 Java API를 기반으로 사용하므로 특별히 JPMS 기준의 타 모듈에 액세스하지 않는 한 잘 동작할 것이다. 현재로서는 JPMS는 같은 모듈의 멀티 버전을 지원하지 않는다. 그리고 동적 업데이트나 동적 unload도 지원하지 않는다. 엔터프라이즈 환경에서 동적 업데이트/unload는 여러 가지 상황에서 필요하다. 이 글에서 언급한 것처럼 IoT만 필요한 것은 아니다. 물론 클라...

[Java] IBM JDK에서 native out of memory가 발생하는 이유와 해결책

이미지
IBM JDK를 사용할 때 (gc policy는 보통 gencon) 물리 메모리가 많이 남아있는 경우에도 native out of memory (NOOM)가 발생하는 경우가 있다. NOOM이 발생하지 않았더라도 global gc 가 자주 발생하여 성능에 영향을 주기도 한다. verbose gc 로그를 보면 sys-start reason="native out of memory" 라는 이유로 global gc가  실행되는 것을 볼 수 있다. 이렇게 global gc가 자주 발생하면 자바의 가장 큰 골치거리인 Stop-The-World 현상이 발생하여 순간적으로 멈춰서게 되어 매우 불안정하게 되는데 이 문제의 원인은 무엇인지 알아보자. 이 문제가 발생하는 경우는 IBM JDK (버전 6 이후)를 사용하고 64비트 JVM, 전체 Java Heap 크기를 4GB 이상 25GB 이하로 줬을 때이다. -Xmx 값이 4GB~25GB이면 IBM 64bit JVM은 기본값으로 -XcompressedRefs 옵션을 켠 것과 동일한 방식으로 동작한다. 자바의 객체들은 JVM 내부에서 2-word 크기의 헤더를 가지는데 32bit JVM에서는 2-word는 8byte이며, 64bit JVM에서는 2-word가 16byte가 된다. 64bit 방식으로 자바 객체를 addressing하게 되면 사용할 수 있는 메모리 영역은 훨씬 더 커지겠지만 메모리를 과다 사용하고 OS의 page cache fault 등의 문제로 성능적으로도 느려질 수밖에 없다. 그래서 64bit JVM에서도 32bit 방식으로 자바 객체 주소를 addressing하는 방식이 바로 compressed reference라는 개념이다. compressed reference 방식으로는 최대 32GB까지 주소를 나타낼 수 있다. 이 경우 Java Heap에 있는 자바 객체들에 대한 주소는 shift 연산을 통해 32bit 주소의 한계인 4GB를 넘어서 최대 32GB까지 참조할 ...

태양의 유산

태양과 두 가지 사건 얼마 전인 6월 16일 삼성전자가 미국 실리콘밸리에 있는 클라우드 스타트업인 Joyent를 인수했다는 소식이 들려왔다. 국내에서는 소프트웨어 조직을 축소하고 있는 삼성전자가 실리콘밸리의 기업을 인수하고 현지 연구소를 강화하는 모습을 보이는 교차하면서 우리나라 소프트웨어 산업의 문제는 과연 무엇일까 하는 생각이 들었다. 그보다 조금 앞선 5월 26일 구글과 오라클의 자바 저작권 침해 소송에서 캘리포니아 북부 연방지원 배심원단은 구글이 자바 저작권을 침해한 것은 API 호환을 통한 기술 경쟁 보장이라는 공정 사용(Fair Use)에 해당한다고 구글의 손을 들어줬다. 이전 저작권 침해 심의 항소심에서는 미 법무부에서 안드로이드의 자바 API 부분 사용은 호환을 목적으로 한 것이 아니므로 공정 사용에 해당하지 않는다는 의견을 제출한 바 있다. 언뜻 상관없어 보이는 두 개의 사건은 모두 지금은 오라클에 인수되어 사라진 기술회사인 선마이크로시스템즈의 기술 유산을 둘러싼 사건이라는 점에서 공통점이 있다. 선마이크로시스템즈 사(이하 선 사)는 '네트웍이 컴퓨터'(The Network is The Computer)라는 캐치프레이즈로 운영체제로부터 가상머신, 미들웨어 등 시스템 소프트웨어와 네트웍 기반 컴퓨팅 하드웨어를 만드는 회사였다. 네트웍이 바로 컴퓨터라는 사상은 지금 전 세계를 휩쓸고 있는 클라우드 컴퓨팅의 현실을 예언한 핵심 아이디어이다. 프로세서 칩과 스토리지 장비, 유닉스 머신 등과 솔라리스 운영체제, 자바 언어 등 핵심 기술을 보유했던 이 회사는 닷컴 버블 이후 점점 더 심해지는 유닉스 시장의 경쟁을 이기지 못하고 또, 미래 가치를 크게 평가받았던 자바 기술로 별다른 수익을 창출할 방법을 찾지 못해 결국 소프트웨어 전문 기업인 오라클에게 인수되고 말았다. 구글은 자바 기술을 안드로이드 플랫폼에 일부를 무단 복제하여 사용하여 엄청난 흥행을 거둠으로써 사실상 선 사가 자바 기술로 수익을 내지 못하는 직접적...

[Java] Java 관련한 간단한 테스트

문득 생각나서 몇 가지 간단한 Java  테스트 1. private static method의 코드 블록 크기가 작을 경우 javac는 가볍게 inline 시켜줌. (즉, 해당 method는 바이트코드에서 사라져버리고 caller method에 inline됨.) 2. instanceof 연산자가 getClass()를 ==비교하는 것보다 훨씬 빠름. (instanceof는 child class여부까지 체크해야 함에도 불구하고) 3. instanceof 연산을 할 때 exact class에 대해 호출하는 것이 parent class나 interface에 대해 호출하는 것보다 더 빠름. (당연!) 4. java.lang.Object의 clone() 메소드를 사용하여 객체를 shallow copy하는 것은 그다지 효율적으로 구현되지 않아서 직접 copy() 메소드를 구현하여 멤버값들을 복사해주는 것이 대부분 더 빠름. (자바는 C의 struct처럼value object 개념이 없어 메모리 복사만으로 clone할 수 없으므로)

[Java] Java G1 GC의 특성에 따른 Full GC 회피 튜닝 방법

Java 6 중반부터 G1 GC가 나오면서 이 새로운 Java VM GC 정책을 두고 성능 튜닝을 어떻게 할지 고민이 많은 것 같다. 일단 생소하기 때문에 어렵다. 그런데 경험들이 조금씩 쌓이면서 문제점도 꽤 발견되는 것 같다. 먼저 G1GC를 이해하는 데 유용한 사이트이다. Garbage-First Collector Getting Started with the G1 Garbage Collector Understanding G1 GC Logs Tuning Garbage Collection for Mission-Critical Java Applications Controlling GC pauses with the GarbageFirst Collector G1: One Garbage Collector To Rule Them All Garbage First (G1) Garbage Collection Options compare JVM options for public 메일 :  G1 GC clean up time is too long JDK 7부터 기본이 된 G1(garbage first) GC는 JVM의 Heap 메모리를 1MB 정도 크기의 region들로 나눠서 region별로 generation을 지정하여 상당히 효율이 좋지만 튜닝하는 게 까다롭다. (새로운 메모리 처리 구조에 대한 튜닝 경험도 많이 부족해서 더욱 까다롭게 느껴지는 것 같다.) 지금까지 널리 알려진 문제로는 첫째, perm generation collection을 full gc때만 하는 문제가 있다. 즉, 클래스 언로딩을 full gc때만해서 자주 재배포가 발생하는 코드가 있는 경우 문제가 될 수 있다. 앞으로는 perm generation을 완전히 없애도록 JVM의 방향을 잡고 있기 때문에 당분간 이 문제는 해결하지 않을 것으로 보인다. 둘째, G1 GC에서 거대 객체(humongous object)라고 부르는 메모리 사용량이 큰 객체들...

[자바] FileChannel에서 map을 하면 내부적으로 unmap은 언제 일어날까? Finalizer를 PhantomReference가 대체할 수 있나?

1. java.nio.FileChannel에서 map을 호출한 다음에 unmap은 언제 이루어질까? 언뜻 생각해보면 FileChannel에서 mmap을 호출하므로 FileChannel을 close할 때 명시적으로 unmap을 해주는 게 효율적인 구현이 아니었을까 생각이 들긴 합니다.. 하지만, 실제 JDK 구현은 그렇게 하지 않았습니다. openjdk v6 코드를 보면 {openjdk6}/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java 에 해당 구현이 되어 있습니다. channel을 close하면 내부적으로 implCloseChannel 메소드가 호출이 되는데 여기에서는 mmap 관련한 일은 행하지 않습니다. 명시적으로 unmap을 하는 경우는 transferTo나 transferFrom이 호출된 경우 일시적으로 사용된 mmap을 바로 munmap해줍니다. 실제 MappedByteBuffer는 Unmapper라는 unmap을 위한 객체를 매번 따로 만들어서 해당 MappedByteBuffer에 대한 참조가 없으면 PhantomReference 방식으로 청소를 해줍니다. 코드를 쫓아가보면 결과적으로 {openjdk6}/jdk/src/share/classes/sun/misc/Cleaner.java 객체에 Unmapper 객체를 넘겨주는 형태입니다. 그냥 MappedByteBuffer 클래스에 finalize() 메소드를 구현하지 않고 PhantomReference 방식으로 복잡하게 처리한 것은 finalize() 메소드를 호출하는 Finalizer 쓰레드의 오버헤드를 줄이기 위한 것으로 보입니다. Finalizer 쓰레드에서 JNI 통해 munmap 시스템 콜을 하는 게 부담스러웠던 것입니다. 다시 문제로 돌아가서 왜 file channel을 close할 때 unmap을 하지 않았을까 생각해보면 원래 유닉스 시스템 콜에서도 fd를 close() 하는 것과 파일의 영역을 가상 메모리에...

[Java] Class.forName 과 ClassLoader.loadClass의 동작 차이

오늘 회의 때 나온 Class.forName 과 ClassLoader.loadClass의 중요한 동작 차이. Class.forName(String clazzName, boolean init, ClassLoader loader) 은 지정한 ClassLoader를 통해 해당 ClassLoader가 define하지 않은 Class라 할지라도 JVM에서 해당 ClassLoader에 캐시하게 되어 있고.. ClassLoader.loadClass(String clazzName) 은 무조건 defineClass를 실행한 ClassLoader에만 해당 Class를 캐시. 아래 블로그 참고. Class.forName caches defined class in the initiating class loader 결과적으로 Class.forName을 사용하면 경우에 따라 효과적인 클래스  캐시를 구현할 수도 있다는 것. (불필요한 user classloader cache 없이..) 참고로 ClassLoader.loadClass(String clazzName, boolean resolve)에서 두번째 인자인 resolve는 원래 의도하기에는 클래스 로딩 시에 참조하는 클래스들에 대한 linking을 실행하기 위한 것이나 (eager linking) 한번도 JVM에서 구현된 적이 없으므로 무시한다. Java에서는 아직까지는 항상 lazy linking만 지원하는 셈. P. S 1) resolveClass 구현 즉, eager linking 구현 코드 ClassLoader에서 resolveClass를 실행해도 아무 일도 일어나지 않길래 왜 그러나 봤더니.. (resolveClass는 지정한 Class의 바이트코드에 선언된 link해야 할 Class들을 모두 link해주는 역할을 해야 함) Hotspot JVM에서 구현을 하지 않았을 뿐임 ㅠ_ㅠ; 즉, Hotspot JVM에서는 link가 해당 클래스를 항상 처음 사용할 때(즉, 메소드 호출을 하는...

컬럼: 전환기의 미들웨어

사보에 실었던 컬럼(2012년 4월호)을 블로그로 포스팅합니다. 한계가 컸던 웹서비스 지난 10 여년간 컴퓨팅 패러다임을 바꿀 것으로 기대했던 흐름 중 하나는 웹서비스였다 . 1998 년 마이크로소프트 사에서 정의한 SOAP (Simple Object Access Protocol) 스펙에 기원을 둔 웹서비스는 마이크로소프트 , IBM, BEA( 지금은 Oracle 에 인수됨 ) 3 사의 엄청난 지원에 힘입어 국제 표준으로 자리잡았으며 , 플랫폼과 프로그래밍 언어에 독립적인 XML 의 장점과 원격 프로세스 호출 (RPC) 아키텍처를 결합한 서비스 중심 아키텍처 (SOA) 라는 IT 패러다임을 만들었다 . 하지만 웹서비스는 기대했던만큼 혁신적인 변화를 가져오지 못했다 . 기업은 웹서비스 도입을 꺼려했고 , 컨설팅 주도로 부풀려진 SOA 아키텍처는 기대했던 유연성과 확장성을 가져오지 못했다 . 오히려 성능 저하 , 처리 능력 저하 , 하드웨어 비용 증가의 문제를 일으켰다 . 웹서비스의 실패와 이에 따른 SOA 기피 현상은 기업 주도로 만들어진 인위적인 새로운 흐름의 문제점을 보여주었다 . 가장 큰 문제는 CPU 과다 사용이었는데 XML 자체의 파싱 오버헤드도 있었지만 SOAP 규격이 정의한 Enveloping 오버헤드 문제 , XML namespace 규격의 불필요한 prefix 오버헤드 문제 등 표준 규격 진행 과정에서 성능을 고려하지 않은 부분들이 스스로의 한계를 규정하고 말았다고 볼 수 있다 . 클라우드 컴퓨팅 뜬구름 같은 이야기 , 클라우드 컴퓨팅은 웹서비스의 한계를 여러 측면에서 반성하면서 탄성 있는 확장성과 관리 비용 절감 등을 내세우며 아마존 , 구글과 같은 웹 중심 기술 기업에서 구현하여 제시하고 있는 새로운 컴퓨팅 스택이다 . 클라우드 컴퓨팅은 컴퓨팅 리소스의 위치에 따라 public cloud 와 private cloud 로 구분할 수 있다 . Public cloud 의 ...

Open(공개)과 Commercialization(상업화). 함께 발전할 수 있을까?

플랫폼 API 공개가 국내에서도 바람처럼 불고 있다. SKT가 자사의 서비스들 API를 전면 공개하겠다고 선언하고 그 후속 작업에 들어갔다. Open이 SKT의 생존과 직결된 문제로 인식하고 전사적인 지원에 나섰다는 점에서 약간 늦은 감은 있지만 결정에 박수를 보내지 않을 이유가 없다. API 공개와 소스 공개 소프트웨어 관련하여 Open(공개)을 두 가지로 크게 분류해볼 수 있는데 하나는 연결 방법 즉 인터페이스를 공개하는 것이다. API(Application Programming Interface)는 프로그래밍을 통한 연결 방법을 뜻한다. 또다른 하나는 소스 공개 즉, 오픈 소스(Open Source)이다. 오픈 소스의 경우에는 소유권과 사용권의 수준과 방법이 라이센스에 따라 많이 다르다. GPL처럼 철저하게 공공재로서만 사용되고 사적 이해를 위해 사용할 수 없는 라이센스부터 BSD나 아파치 라이센스와 같이 어떤 목적에도 사용할 수 있는 최소한의 제약만 있는 라이센스. 그리고, 특정 기업이 소스를 공개하면서 자사만 사적 이해를 위해 사용할 수 있도록 한 GPL과 Commercial License의 이중 라이센스 방식 등이 있다. API 제공은 플랫폼 위에서 새로운 서비스를 만들 수 있는 수단을 제공하지만, 또 서비스의 관점에서 보면 특정 플랫폼에 종속되는 결과를 낳기도 한다. 이를 보통 lock-in 효과라고 부르는데 Facebook이 자사의 핵심 자산인 개인별 소셜 관계 그래프를 API를 통해 제공하고 좋은 서비스의 자유로운 발전이 자연스럽게 Facebook 자체의 성장이 되도록 하는 것은 놀라운 공생의 비즈니스 모델로 보인다. 플랫폼을 제공하는 방법 역시 이렇게 API 수준에서 공개하는 것 외에 소스를 오픈하는 방법도 있다. 이 경우엔 서비스를 제공하려는 기업 관점에서 보면 오픈 소스 플랫폼의 관리와 운영에 대한 책임을 가져가야 하는 부담이 있는 반면, 특정 기업에 lock-in되는 문제를 피할 수가 있다. 오픈 소스 CMS ...

[Java] Concurrent Processing : Actor Model

actor model에 대한 개념을 정리하려 했는데 간결하지 못하고 장황해져 버렸다. actor model을 둘러싼 이슈에 대한 공유 정도로 읽어주기 바란다. Concurrent Computing multi-core CPU가 개인 PC에 일반화되고, 서버 환경에서도 8 CPU 서버는 흔하게 볼 수 있는 게 오늘날의 컴퓨팅 환경이다. 운영체제에서 다중 쓰레드를 지원하는 것은 기본인 데다가, 서버 소프트웨어를 운영하다 보면 발생 확률이 매우 낮을 것 같은 동시성 처리 관련 버그가 몇 달이 못가 심각한 운영 장애의 원인으로 발견되기도 한다. 또, 클라우드 환경에서는 수천대의 컴퓨터를 연결하여 연산을 동시에 분산 처리하여 빠른 결과를 가져오는 것이 일반화된 기술이 되고 있다. 단일 노드, 단일 CPU에서는 발생하기 어렵던 문제들이 서버쪽 소프트웨어에서는 매우 critical한 이슈로 매일 접하게 되었다. 흔히 concurrent programming 이라고 부르는 비동기적이고 동시적인 연산 처리 기법이 이미 보편화되어 있다. concurrent programming을 위한 여러 가지 모델 중에서 OS 에서 제공하는 thread와 locking을 사용하여 직접 구현하는 방법 외에 수학적 기반에 출발한 처리 모델들이 몇 가지 있다. 많이 사용되는 concurrency 고려 모델에는 여기 소개할 actor model 외에 단방향 그래프 방식으로 워크플로우 구현에 많이 사용되어온 petri-net, WS-BPEL 표준의 수학적 근거로 알려진 pi-calculus(π-calculus)가 있다. 아주 간단하게 설명하자면 Petri Net은 place와 transition으로 구성된 그래프에 token의 이동을 통해 흐름을 제어하는 모델로 동시에 여러 개의 token이 존재할 수 있어 동시성을 표현한다. Petri Net은 token이 현재의 실행 위치를 나타내므로 제어 흐름을 직관적으로 표현하는 장점이 있지만, 데이터 흐름은 고려할 ...