'온라인 서버 제작자 모임'(주로 온라인 게임 서버 개발자가 많습니다)에서 오래만에 세미나를 합니다.


온라인 서버 제작자 모임 회원이 아니라도 참석할 수 있으니 관심 있는 분들은 신청해 주세요^^


신청은 아래의 링크를 통해서 하면 됩니다.

http://onoffmix.com/event/83434



1. 최흥배: Pokemon Go의 Server에 사용된 기술(외부자료를 통해 알아보는)


2. 이지현: 게임 개발에서 눈여겨 볼 AWS 서비스들


3. 초보대왕: ‘Windows와 리눅스 (네트워크 프로그래밍)호환 이야기 10탄’

저작자 표시
신고
by 흥배 2016.11.21 08:00

아래 코드를 linqpad로 실행하면

void Main()

{

           Test t = new Test();

    var y = t.aaa();

   

           System.Console.WriteLine(y);

}

 

class Test {

    public int aaa() {

        int x = 1;

 

        try {

            return (x += 1);

        } catch (Exception e) {

 

        } finally {

            x += 3;

        }

        return x;

    }

 }

 

출력은 2가 된다.

 

위 코드의 출처는 http://www.pixelstech.net/article/1474892842-try-%7B-return-%7D-finally-%7B%7D 이다

언어는 java를 대상으로 했지만 c#도 비슷한 것 같다.

 


출력이 2가 나오는 이유는 (java의 경우) 다음과 같다JVM 문서를 보면


만약 try 절에서 return을 실행할 경우 컴파일 된 코드는 다음과 같은 처리를 한다.

- 로컬 변수에 반환 값을(만일 존재하는 경우)을 저장한다.

- finally절 코드까지 jsr를 실행한다.

- finally절의 return에서 로컬 변수에 저장된 값을 반환한다.

 

return ++x가 실행되면 JVM++x의 값을 임시 변수에 저장하고, finally 블록을 계속 실행한다. finally가 실행된 뒤 임시 변수에 저장되어 있는 값을 메서드의 호출자에게 돌려준다.

 

저작자 표시
신고
by 흥배 2016.11.18 08:00

드디어(?) mac용으로 비주얼스튜디오가 나온다.

https://msdn.microsoft.com/magazine/mt790182

 

정식 발표는 connect(); 2016(https://connectevent.microsoft.com/) 이라는 행사에서 발표된다고 한다.

 

기본 베이스는 windows Visual Studio가 아닌 Xamarin Studio를 바탕으로 했다고 한다.

 

현재 프로그래밍 언어는 C#, F#을 지원한다고 한다. 정식 발표 때 C++도 지원될지는 아직은 모르겠다(만약 정식에는 나오지 않더라도 멀지 않은 기간에 업데이트로 지원할 것 같다).

 

Xamarin을 사용할 있으므로 iOS, Android, macOS 대응 앱을 개발할 수 있으면 .NET Core를 사용하는 서버 앱도 개발할 수 있다.

 

 

그리고 참고로 Visual Studio 차기 버전은 Visual Studio 2017로 결정 되었다고 한다 내년 초에 나올 예정인 것 같다.

저작자 표시
신고
by 흥배 2016.11.15 08:00

RDBMS의 SP처럼 MongoDB에는 Java Script로 저장 함수를 만들어서 사용 할 수 있다.

각 데이터베이스의 Function에 만들고, eval() 함수로 호출해서 사용한다.


db.system.js.save(

                   { _id: "echoFunction",

                     value : function(x) { return x; }

                   }

                 )


db.eval( "echoFunction( 'test' )" )



- 2.4 버전까지는 성능 상의 문제로 추천하지 않는다.

http://docs.mongodb.org/manual/tutorial/store-javascript-function-on-server/

http://stackoverflow.com/questions/15660161/why-is-it-not-recommended-to-use-server-side-stored-functions-in-mongodb


- 이유는 eval를 사용하면 자바스크립트 코드로 동작하고, 이 SP가 호출 후 끝날 때까지 lock이 걸려서 다른 작업을 할 수 없게 된다.

- 지금은 비추하는 기능이지만 근래 MongoDB의 자바스크립트 라이브러리가 V8 엔진으로 바뀌어서 장래에는 쓸만하지 않을까 예상한다.

- 게임 서비스 도중에는 사용하기 부담스럽겠지만 서비스 이외에 관리 측면에서는 자주 사용하는 기능을 Function으로 만들어 놓고 사용하면 편리 할 것 같다.

- 당연하지만 SP에서 컬렉션 조작도 할 수 있다.


db.eval( function(name, incAmount) {

    var doc = db.myCollection.findOne( { name : name } );

    doc = doc || { name : name , num : 0 , total : 0 , avg : 0 };


    doc.num++;


    doc.total += incAmount;


    doc.avg = doc.total / doc.num;


    db.myCollection.save( doc );


    return doc;

 },


 "eliot", 5 );





Mongo Shell 에서 사용하기


같은 database에 있는 function을 호출 할 수 있다.



MongoDB의 쿼리 명령어도 사용 할 수 있다.





저작자 표시
신고
by 흥배 2016.11.14 08:00

linux에 redis 설치 

http://cs-arthur.tistory.com/113

http://misoin.tistory.com/1

http://blog.outsider.ne.kr/763


Windows용 Redis를 닷넷에서 사용

http://www.codeproject.com/Articles/636730/Distributed-caching-using-Redis-server-with-Net-Cs



Redis 연구 노트

http://kerocat.tistory.com/1


Commands - key편

http://blog.saltfactory.net/66


콘솔 명령어 정리

http://blog.naver.com/forioso/10173379225


Redis v2.2.12 맛보기

http://www.slideshare.net/knight1128/redis-8896084

저작자 표시
신고
by 흥배 2016.11.11 08:00

좀 오래된 기사인데 며칠 전에 알게 되었다.

(MS SQL Server는 2008까지만 사용해봤고, 요즘 게임 업계 분위기가 2012는 라이센스 비용 등의 문제로 사용하지 않는 추세라서..)


MS SQL Server2012까지만 SQL ServerOLE DB 드라이버를 제공한다고 한다.

https://blogs.msdn.microsoft.com/sqlnativeclient/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access/

 

OLE DB 자체가 사라진 것은 아니고 이 기술을 만든 MS가 자신들의 DB 서버에서는 2012 버전까지만(최신은 2016) OLE DB로 접속할 수 있다고 한다.


MySQL 등에서는 아직 지원하지 않는다는 이야기를 들어본 적은 없지만 아마 장래에는 지원하지 않을 것 같다.

 

장래에도 DB 코드가 문제 없이 돌아가기를 바란다면 OLE DB는 사용하지 않는 것이 좋을 것 같다.

저작자 표시
신고
by 흥배 2016.11.09 08:00

출처: http://qiita.com/ryotanatsume/items/018cae5c5be8faba367a



KISS

Keep It Simple, Stupid

간단하게 해 어리석은 놈아


코드를 쓸 때 "단순성"이나 "간결성"을 최대 중요 항목으로 한다.


코드는 자연에 맡겨 수정해 가면 무 질서하게 되고 복잡해진다. 

그 결과, 읽기 어렵고 수정하기 어려워진다.

코드를 간단하게 유지하는 것으로 수정하기 쉬워 진다.


구체적으로는 프로그래밍할 때 "동작하기 위해서 가장 단순한 것은 무엇인가"라고 자주 물어보는 것이 필요하다.



DRY

Don't Repeat Yourself.

되풀이하지 마라.


같은 코드를 중복해서 쓰지 말라는 것.


왜냐하면, 코드의 개선이 어려워지기 때문이다.

우선 같은 코드가 여럿 있는 것으로 양적으로 "더 많은" 질적으로 "보다 복잡한 "이 되기 때문에 코드를 읽는 작업이 어려워진다.

또 수정할 때도 하나 고칠 때도 중복해서 쓴 코드에 대해서도 빠짐없이 고쳐야 하니 큰일이다.


구체적으로는 처리의 모음은 "함수화" "모듈화"를 하고 데이터는 이름 있는 정수를 정의하는 것이 중요하다.



YAGNI

You Aren't Going to Need it.

그것은 꼭 필요하게 되지 않는다


코드를 필요 최저한으로 한다.


미리 여러가지 사태에 대비하여 코드를 써도 결국은 이용되지 않는 것이 많다.

그리고 그것에 의해서 코드에 "쓸데없는" 복잡성을 담아 버리게 되는, KISS에 사상에도 역행한다.

즉, 예상이 빗나간 경우 시간이 헛되게 사용하는 것에 더해 방해도 되는 것이다.

그리고 단순 코드가, 범용성이 높다.

구체적으로는 보편성보다는 단순성을 생각하는 것이 중요. 

코드는 "지금" 필요한 것만 하기.



PIE

Program Intently and Expressively

의도를 표현하는 프로그래밍을 해라


코드는 의도를 분명히 표현하게 써야 한다는 것이다.


코드가 "사람"이 읽기 위한 것이며 코드만이 소프트웨어의 동작을 "정확히" "완전히" 알기 위한 단서이다.

따라서 소프트웨어의 동작을 파악하는 데는 쉬운 코드를 쓰고 코드에서 의도를 전하는 수밖에 없다.


구체적으로는 코드를 쓸 때는 "쓰기 쉬움" 보다 "읽기 쉬움"을 중시하는 것.

코드는 "쓰는 것" 보다 "읽는 것"이 더 많은 것이기 때문이다.



SLAP

Single Level of Abstraction Principle

추상화 수준의 통일


코드를 쓸 때 높은 수준의 추상화 개념과 낮은 수준의 추상화 개념을 분리하도록 할 것.


왜냐하면, 코드가 수준에 어울리는 함수로 분할됨으로써 "요약성" "열람성"을 동시에 충족시킬 수 있다.

같은 곳에는 같은 추상도의 처리와 같이 코드가 통일됨으로써 코드는 거침 없이 흐르고 이해하기 쉽다.


구체적으로는 함수를 구조화하는 것이 중요하다.

하나의 함수에서 어느 부분에서는 데이터베이스 접속은 저 수준의 처리를 하고 다른 부분에서는 비즈니스 로직의 실행이라는 높은 수준 처리를 하도록 하지 않는 것이 중요하다.



저작자 표시
신고
by 흥배 2016.11.07 08:00

잘못된 SqlConnection

// 코드 1

using (var connection = new SqlConnection("접속문자열"))

{

    connection.Open();

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}


<코드 1>을 실행하면 크래쉬가 발생

이유는 간단 SqlConnection가 스레드 세이프 하지 않기 때문.


위의 코드를 올바르게 수정하려면 아래와 같이 변경.

// 코드 2

Parallel.For(1, 1000, x =>

{

    using (var connection = new SqlConnection("접속문자열"))

    {

        connection.Open();

        var _ = connection.Query<DateTime>("select current_timestamp").First(); // Dapper

    }

});



<코드 2>는 안전하지만 아마 위 방식은 원하는 방식이 아닐 것이다.



ThreadLocal

위의 문제를 ThreadLocal을 사용하여 해결해 보자


// 코드 3

using (var connection = new ThreadLocal<SqlConnection>(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }))

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}



성능 테스트를 해보면 싱글 스레드를 사용하면 16초, <코드 2>는 5초, <코드 3>은 2초



<코드 3>은 안전한가?

<코드 3>은 위험한 코드.

이유는 연결한 후 Dispose 하지 않기 때문.

ThreadLocal의 Dispose는 어디까지는 ThreadLocal의 Dispose이기 때문에 그 안의 객체를 Dispose 해주지 않는다.


이 문제는 trackAllValues 라는 옵션을 사용하여 간단하게 해결 가능!



// 코드 4

using (var connection = new ThreadLocal<SqlConnection>(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }

    , trackAllValues: true)) // ThreadLocalの.Values 프로퍼티의 참조를 유효화 한다

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });


    // 생성된 모든 Connection을 일괄적으로 Dispose

    foreach (var item in connection.Values.OfType<IDisposable>()) item.Dispose();

}



단 trackAllValues는 닷넷프레임워크 4.5 부터 사용 가능




trackAllValues 랩퍼 클래스 사용


public static class DisposableThreadLocal

{

    public static DisposableThreadLocal<T> Create<T>(Func<T> valueFactory)

        where T : IDisposable

    {

        return new DisposableThreadLocal<T>(valueFactory);

    }

}


public class DisposableThreadLocal<T> : ThreadLocal<T>

    where T : IDisposable

{

    public DisposableThreadLocal(Func<T> valueFactory)

        : base(valueFactory, trackAllValues: true)

    {

    }


    protected override void Dispose(bool disposing)

    {

        var exceptions = new List<Exception>();


        foreach (var item in this.Values.OfType<IDisposable>())

        {

            try

            {

                item.Dispose();

            }

            catch (Exception e)

            {

                exceptions.Add(e);

            }

        }


        base.Dispose(disposing);


        if (exceptions.Any()) throw new AggregateException(exceptions);

    }

}



// 사용

using (var connection = DisposableThreadLocal.Create(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }))

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}





출처: http://neue.cc/2013/03/09_400.html 

저작자 표시
신고
by 흥배 2016.11.04 08:00

'게임 서버 제작자' 모임에서 10월 25일에 했던 강연 중의 하나 


'CTO가 하는 일 '

https://www.youtube.com/watch?v=hkzgPFd_IFU&feature=youtu.be




저작자 표시
신고
by 흥배 2016.11.02 08:00

개요

- NoSQL용 SQL 쿼리 엔진으로, 파일 시스템 상의 JSON/CSV/Parquet 등의 파일, Hive 소스, HBase, MongoDB 등에 직접 SQL 쿼리를 던질 수 있다.

- http://drill.apache.org/

- 멀티플랫폼 지원.



Windows 설치 및 시작

- 다운로드 후 아래 처럼 압축을 푼다.

- bin 디렉토리에서 아래 명령어 실행

    - sqlline.bat -u "jdbc:drill:zk=local"

    - 위 명령어는 임베디드 모드로 실행한다는 뜻. 즉 하나의 컴퓨터에서 실행.

- 종료는 !quit



MongoDB 사용하기

- 실행한 후 http://localhost:8047 를 웹브라우져로 연다.

- Storage 탭에서 MongoDB 연결 설정을 한다.

Storage 탭


MongbDB 설정


- 콘솔 화면(클라이언트 실행)에서 show databases; 를 실행한다.

    - MongoDB 설정이 올바르게 되었으면 데이터베이스 이름 중 mongo. 가 붙은 것이 보인다.

- 데이터 베이스 선택

    - user mongo.GameDB;

- 테스트 용 쿼리 실행

    - select * from user limut 10;




웹브라우져로 쿼리 실행하기

- Apache Drill을 원격 서버에 실행한 후 웹브라우져를 통해서 쿼리를 실행한다.

- mongo.데이터베이스.컬렉션 을 모두 입력해야 컬렉션에 쿼리할 수 있다

저작자 표시
신고
by 흥배 2016.10.31 08:00

티스토리 툴바