늘모자란, 개발

늘모자란, 개발


mysqldump를 뜨다보면 자연스럽게 swap이 생기는것 같다.
이렇게 생긴걸 굳이 남겨둘 필요가 없어서 swapoff -a 와 swapon -a 를 통해 풀곤 했는데 자동화하려고 crontab에 추가했는데 돌아가질 않는다.

swapoff -a && swapon -a


.sh 에 작성해서 돌려봐도 안된다. 왤까하다 구글링으로 찾아보니 full path를 작성해줘야 하는 것 같다.

/sbin/swapoff -a && /sbin/swapon -a


잘된다.

2017/11/19 12:48 2017/11/19 12:48
제목이 점점 산으로 가는 기분인데..

Android 에 Intent 가 있다면 iOS에는 UIDocumentInteractionController가 있다.
annotation을 태워서 같이 보내거나 하는 등의 intent와 여러모로 비슷한 옵션인데, 기본적인 동작은 AirDrop을 호출해 파일을 다른 앱의 번들안에 저장한 후 파일을 오픈하게 하는 구조이다.

그런데..
10.3에서 돌아가는 다음 소스가 11에선 돌아가지 않는다.

 NSString* filepath = [[NSBundle mainBundle] pathForResource:@"Filename" ofType:@"pptx"]; 
NSURL *url = [NSURL fileURLWithPath:filepath]; 
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; 


아무리 로그를 봐도 그냥 파일 복사가 실패했다는 말만 나온다. 영문도 모르겠다. 더 열받는건 iOS의 기본앱(메모, 페이지)로는 또 열린다는 것이다. 그러다가 비슷한 처지의 글들을 보게 되었는데 결론은 그냥 iOS의 보안정책이 변했다.

AirDrop이란건 그냥 뻔한건데,
iOS에서 파일을 받을 경우 앱내에 있는 번들 스페이스에 저장하게 된다. 이 번들안에 저장된 URL을 서드파티앱에 넘기고, url을 받은 서드파티앱이 해당 url로 접근 후 파일을 복사해서 자신의 번들안에 저장하고 여는 구조라고 할 수 있는데, iOS 10까지는 이런 일련의 과정들이 허용되었으나 이젠 애플 기본앱이 아니면 접근 할 수 없다.

고로 접근할 수 있는 임시 디렉토리를 생성하고, URL을 다르게 전달해야만 앱이 오픈된다

 NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];        // get /tmp folder path 
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:@"Filename"] URLByAppendingPathExtension:@"pptx"]; 
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
 


정말 봐도봐도 거지같단 생각밖에 안든다. 여튼 이러면 열린다..
2017/11/13 15:14 2017/11/13 15:14
사건 발생
지난 10월 25일 0시경, 사이트가 이상하다는 말을 듣게 되었습니다.
확인해보니 MySQL 서버가 말썽, 근데 좀 이상합니다. 잘될땐 잘되는데 새로고침할때마다 DB가 에러를 throw하고 있는데 왜지..?
가끔은 no such file or directory도 뜨고, too many connections도 뜨고.. 그리고 gone a way도 뜨는 등 난리도 아닙니다. 도대체 무슨일이 일어난걸까요.

서버 다운
처음 의심했던것은 MySQL 을 5.7.20으로 업그레이드 했기 때문 아닌가였습니다. 그런데 업그레이드는 아침에 이뤄졌고, 오류가 난건 거의 15시간이 지난 이후.. 연관이 없어보입니다. 아직도 업그레이드 했기때문에 터진게 아닌가 하는 강력한 의심을 가지고 있지만, 어쨌든 사건에 집중해봅시다.

제일 먼저 사이트를 활성화 시켜야했습니다. 뭐 할때마다 에러가 나는데 되는것도 아니고 안되는것도 아닌 기괴한 상태가 지속되고 있었습니다. 쉘에서 MySQL에 붙으려고 해도 too many connections로 붙을 수가 없을정도로 이미 점거 당한 상태. 보나마나 process에 행이 걸려서 뒤의 요청을 처리 못하고 있는 것이겠지요. 도저히 확인을 할 수 없을정도로 밀려들어오니 일단 웹서버를 내렸습니다. (어차피 서비스가 정상작동하고 있지도 않았습니다)

이제 살펴보자
서버를 내린 이상 시간끌리지 않고 최대한 빠르게 문제를 확인해야 했는데 에러로그를 보니 메모리 관련해서 에러가 찍혀 있었습니다. key buffer size를 조절하라.. 뭐 memory trap 이라고 적힌거도 있고, because you hit a bug 이런식으로도 쓰여있는데 아니... 그래서 뭐가 문제라는건데... 정작 유추할 수 있는 에러로그는 없고 미칠 노릇입니다. 친구말로는 메타데이터 파일이나, 권한 문제가 일어났을 수 있다고 하던데 (바로 며칠전에 비슷한 에러를 겪음) 문제도 없었습니다. 

일단 뭐가 깨져도 깨진건 확실합니다. MySQL에서는 innodb 엔진을 쓰는 경우 1~6 레벨(?)까지 강제 복구 옵션을 지원하고 있습니다. recovery 레벨을 설정하면 read-only가 되는데 이때 살릴 수 있는거라도 살리려면 mysqldump해주는게 좋습니다. 저도 데이터를 일단 백업해야겠다는 생각에 mysqldump로 DB를 하나씩 덤프뜨긴했는데 특정 DB에 접근하니 바로 dump가 중지됩니다. select를 못한다는거죠. 어떤 DB가 깨졌구나하고 대강 범위를 좁힐 수 있었습니다.

2017-10-25T01:35:15.821493+09:00 4 [ERROR] InnoDB: Failed to find tablespace for table [ ] in the cache. Attempting to load the tablespace with space id 23958


왜 범위를 좁혔냐 하면, 위 로그는 전혀 상관없는 DB에서 났기때문입니다. 아마 하나가 깨지니 뒤에 따라오는 테이블을 모두 읽지 못하는 현상이 아닌가 싶은데.. 범위를 줄여나가는게 중요합니다.

그다음에는 .ibd 및 .frm을 모두 cp한후에, 문제가 일어났을것이라 생각하는 db의 내용을 모두 지우고, MySQL을 재시작해 싹 밀고, 다시 붙여넣어봤습니다. 해당 DB가 없으니 기가막히게 잘 굴러갑니다만 다시 데이터를 넣자마자 바로 db가 재시작되어버립니다. 여기서 ibdata가 박살이 났구나하고 감을 잡을 수 있었습니다.
보통은 이럴때 mysqlfrm을 사용해 테이블 구조를 새로 만들고, 데이터를 다시 밀어넣는식으로 복구합니다만, 저 같은 경우는 테이블 수도 많고, 일단 db에 select를 하면 db가 재시작되어버리기때문에 별 의미가 없다 생각했습니다. (사이사이 frm및 ibd 데이터를 하나씩 넣어서 산 테이블을 확보해보려했으나 거의 소용없는 짓이었습니다). 메모리 에러 일 수 있을것이라 생각해 서버 재부팅도 두번이나 했으나.. .안되네요.

결국 여기서 손을 들었습니다. ibd와 frm이 있지만 애초에 붙어지질 않으니 복구할 수가 없구나. 마지막 백업이 언제지? 아침 6시입니다. 그리고 새벽까지 삽질하고 있었으니 그 동안에 누적되지 못한 로그들도 많으니 문제가 된 DB는 최대 24시간정도의 데이터 유실이 발생합니다. 사이트는 다시 돌지만, 뼈아픈 경험입니다. 24시간마다 백업이 돌고 있으나, 유실될 양을 생각해보면 터무니 없이 부족합니다. 어떻게 해야할까요?

무중단 백업은 어떻게?
4년전 쯤에서는 MySQL의 replication을 활용하고 있었습니다. 이때는 DB쿼리가 최적화 되어있지 않아 쿼리한개가 DB를 잡아먹던 시절이기도 하고, VPS에서 사용했기때문에 서버 사양이 워낙 안좋아 시도때도 없이 DB가 죽을때가 있었습니다. 정확히 다시 말하면, 백업이 아니라 cpu 와 메모리 사용량을 분산시키기 위한 cluster개념으로 replication을 사용했습니다.

그러나 세월이 꽤 흘렀죠? 문제가 된 DB 쿼리도 다 수정되었고, 서버 스펙은 그때와 말도 안되게 뻥튀기되었습니다. 서버 두대를 돌릴 이유가 없으니 자연스럽게 replication 서버를 내렸었죠. 이 얘길 왜 하느냐? 지금부터 replication을 사용할 것이기 때문입니다.

왜? 기존에 사용하고 있는 mysqldump는 모든 db를 full select 합니다. 또한 쿼리 캐시 옵션을 비활성화하기때문에 DB에 심각한 부하가 발생하며, 사이트 전체의 성능저하도 일어납니다. 따라서 백업텀을 줄이면 안되겠느냐 같은 말은 사용량이 많은 시간대엔 절대 먹히지 않는 말입니다. 고로, 부하가 발생하지 않으면서도, 실시간 백업을 할 수 있는 방법 = 데이터가 insert되면 다른 데이터베이스에 저장하는 방법은 뭐가 있죠? replication입니다. 그래서 docker를 이용해 가상 서버를 하나 만드는걸로 진행합니다.

다음과 같이 변경했습니다
모든 과정이 매끄럽게 진행되진 않았지만, 주말동안 작업해 적용된 내용은,
Replication 서버를 돌려서 한쪽 DB가 맛이 가더라도 관리자 확인하에 즉시 DB를 변경할 수 있게 변경했습니다.
서비스 중일때 발생하는 dump 백업의 텀을 3시간으로 줄였습니다.(기존 24시간)
마지막으로, 서버 이미지를 하루마다 저장해 허브에 푸시합니다. DB 두개가 한번에 박살나도, 최대 10분내에 복구가 가능합니다.(순수하게 다운로드 시간)

얻은 결론
서버 용량이 풍족하진 않습니다. 이번 구성으로 인해 꽤 많은 용량을 차지하게 되었습니다만... 서버 용량이야 좀 더 자주 확인하면 되는 것이고, 밤을 안새게 해주진 않습니다. 또한 사용자 여러분들의 사이트 사용에도 차질이 없도록 만반의 준비를 했어야 했는데, 진작해야할 일을 이제야 한 것 같습니다. 좋은 교훈을 얻었다 생각하고, 서버 안정화에 더 힘쓰겠습니다
2017/10/26 10:02 2017/10/26 10:02

VPN 사용..

Gossip 2017/10/13 17:24
원룸에 hcn 이라는 현대 케이블 네트워크.. 즉 케이블 인터넷이 들어와있다.
8월부터 스멀스멀 느려지더니 9월 10월을 거쳐 속도가 100kbps 가 나오고 있다. 뭐 하나 받으려고 하면 2시간 넘게 찍히는건 일상이라 너무 열받아서 kt 인터넷으로 바꾸려고 하였으나...

속도 테스트를 해보고 화가 치미는 상황이라면 VPN을 꼭 권해본다

1. 건물에 kt쓰는 사람없어서 전봇대에서 끌어와야함
2. 건물에 구멍남
3. 외관 드러워짐

의 이유에 의해서 kt인터넷을 쓸수가 없었다. 결국 VPN을 사용해야만 하는 상황..
나는 아이피팩토리 란데서 결제했다. (IE로 접속하세요. 액티브X있음)
esvpn 이란데도 있는데 만오천원이고 일단 결제 액티브엑스가 안깔리길래 그냥 싼걸루..

30일에 13200원이다.
그냥 설치하고 접속하니 4메가 쯤 나오는데 속도가 몇배 상승한건지... 
HCN에 문의하는 사람 많다는데 공사중이라는 답변을 많이 한다고 하지만 일단 당장 불편하니까 한번 고려들 해보시라..
트윗덱이랑 나무위키 바로 로드 되는거보고 눈물 흘릴뻔했네 

2017/10/13 17:24 2017/10/13 17:24
즐거운 산수시간
2017/09/28 11:24 2017/09/28 11:24
유저이름, 유저 비밀번호는 아무 쓸모 없음. 시간에 집중
2017/09/27 10:11 2017/09/27 10:11
풀이법을 쓰면 안된다니까 그냥 힌트만 적기로 해본다

100점짜리 문제고, 별다른 필터링이 없는 것 같아보인다. PHP를 돌릴 환경하나 쯤 구축해두면 좋을 것 같고, 쿠키를 잘 봅시다
2017/09/26 15:52 2017/09/26 15:52
이번에 해볼 사이트는 noe.systems 라는 특이한 도메인을 가진 워게임이고, wechall 에서 발견해서 해보게되었다.
근데 풀이법을 올리면 안된대서 그냥 비공개 write-up 이라도 써볼까 한다. 근데 웹이 주력이 아니라서 몇개나 올릴지는 잘 모르겠고..
문제 견적 봐가며 한번 풀어봅시다..
2017/09/25 12:42 2017/09/25 12:42
기업용앱은 ipa로 배포하곤 한다. 내부배포니까 굳이 앱스토어에 올릴 필요가 없기 때문이다.
원래는 ipa를 더블클릭하면 아이튠즈 창이 활성화 되고, 기기의 '앱' 메뉴가 열리며 설치예정, 삭제예정 등이 나왔는데 

아이튠즈 12.7이 업데이트 되면서 그런 메뉴가 다 사라졌다. 앱에 파일 넣던 기능은 '파일 공유'로 바뀌었고, ipa설치는 흔적도 없어져 어떻게 까나.. 싶었는데, 방법은 그냥 ipa를 드래그해서 '기기' 밑에 연결된 기기에 그냥 드래그 하면 깔린다. 어이가 없게 바뀌긴했는데...
.헤매지말고 잘들 깔아보시라..
2017/09/19 11:48 2017/09/19 11:48
iOS 코드중
[self.window setHidden] 옵션을 사용하는 경우가 있다. 파라미터에 NO를 줘 AppDelegate 에서 사용할 경우 앱이 새카맣게 되는 효과가 생긴다.
즉 화면이 내려갈때 창을 감춰버리기때문에 한순간도 보이지 않게 하는 효과를 낼수도 있지만 사실 거의 사용할 일은 없을 것 같은 기능이다.

이번에 회사앱을 만들면서 길고 긴 키보드 이슈가 있었는데, 앱에서 키보드를 치다가 홈버튼으로 나갔다 들어오면 키보드를 더 이상 사용할 수 없게 되는 황당한 버그였다.

이 문제의 결론은 iOS11에서 변경된 사항으로 인해 일어나는 버그였었는데, 내가 직접 테스트 해본건 아니고 벤더사의 메일 내용을 대부분 인용해서 블로깅한다. (아마 관계자 분들께서 들리실 수도 있을 것같다. 이런 삽질은 정말.. 유니크하다...)


1. [self.window setHidden:YES]


해당 코드가 실행되면 window의 visible의 false로 변경되며 key window도 아니게 된다
이 상태에서 [self.window setHidden:NO]를 실행하게 되면 iOS10과 iOS11에서 동작하는 로직이 달라 문제가 생긴다

2. iOS10


해당 윈도우 visible이 true가 되며 key widnow로 변경됨

3. iOS11


key window로 변경되지 않음 = 키보드 관련 이벤트가 동작하지 않는다


해결


iOS10과 11이상의 버전에서 달리 이벤트를 처리한다

iOS10 이하에서는
[self.window setHidden:NO];

만 사용해도 좋다.

iOS11에서는 다음과 같이 변경한다
[self.window setHidden:NO];
[self.window makeKeyWindow];


혹은,

[self.window makeKeyVisible];


로 작성하면 정상적으로 사용이 가능하다
2017/09/11 16:22 2017/09/11 16:22

1 2 3 4 5 6 7 8 ... 20