monkey.patch_all(thread=False)

Remove "thread=False".

This makes thread hanging.


Refer to usage of pymongo + gevent on below site

http://api.mongodb.com/python/current/examples/gevent.html

https://stackoverflow.com/questions/7166998/pymongo-gevent-throw-me-a-banana-and-just-monkey-patch

They are telling,

"By default, PyMongo uses threads to discover and monitor your servers’ topology (see Health Monitoring). If you execute monkey.patch_all() when your application first begins, PyMongo automatically uses greenlets instead of threads."


'python' 카테고리의 다른 글

pytz localize vs normalize  (0) 2018.02.26
flask save session error  (0) 2017.12.05
gevent monkey patch all, code location  (0) 2017.09.14
flask with gevent monkey patch all  (0) 2017.07.26
flask gevent spawn use a lot of memory  (0) 2017.04.05
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

monkey patch all

1. 어느 위치에 써줘야할까?

문서에 보면 가능한 젤 위에 patch all코드를 쓰라고한다. 근데 상식적으로, import 모듈을 해놓고 패치를 해야 로드된걸 패치시키는게 아닐까? 라는 의문을 같게 된다.

대답은 맞다. 그렇지만 맨위에 쓰는게 맞다 이다.

왜냐면, monkey patch 를 지원하는 standard library들은 순서가 어찌되었건 몽키패치를 지원한다. 

from gevent.monkey import is_module_patched
from gevent import monkey;monkey.patch_all()
import socket
import threading
print(is_module_patched("socket"))
print(is_module_patched("threading"))

결과:

True
Ture

import socket
import threading
from gevent import monkey;monkey.patch_all()

print(is_module_patched("socket"))
print(is_module_patched("threading"))

결과:

True
True

그렇지만 몽키패치를 지원하지 않는 3rd library들은 위험할수도 있기 때문에 가급적 패치올을 맨위에 써서 영향이 안가도록 맨위에 쓰라는 것이다.


2. patch_all(thread=False) 

thread patch는 기본적으로 True다. thread가 몽키패치되게되면, threading을 쓰는 부분을 thread가 아니라 gevent에서 지원하는 Greenlet object로 바뀌게된다. 

일단 큰 차이는 context switching 시점이다.

thread는 내가 원하는 시점에 명시적으로 context switching을 하는게 아니라 os 스케줄에 따라서 context switching이 되어 쓸데없는 비용을 소비하게 될 확률이 높다.

그러나 greenlet object는 명시적 sleep이나 library의 io에 패치된 경우에 한해서 context switching이 된다.

참고로, windows 10에서는 maximum recursive error가 나오면서 patch_all 함수가 실패한다. 이때 thread=False 옵션을주면 잘 동작하게 된다. 아마 윈도우10에서는 thread패치를 완벽히 지원하지 않는것 같다. 


reference

1. https://stackoverflow.com/questions/39537004/gevent-monkey-patching-order

2. https://stackoverflow.com/questions/15556718/greenlet-vs-threads


'python' 카테고리의 다른 글

flask save session error  (0) 2017.12.05
python3 flask + pymongo + gevent, locust testing hangs  (0) 2017.09.26
flask with gevent monkey patch all  (0) 2017.07.26
flask gevent spawn use a lot of memory  (0) 2017.04.05
websocket with gunicorn  (0) 2017.03.03
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

Problem:

 - content length mismatched(ERR_CONTENT_LENGTH_MISMATCH)

 - response string truncated (cut off)


If you are using flask with gevent monkey patch all and you got such a problem above, 

than you should use gevent wsgi instead of flask app.run


For example..

from gevent import monkey

monkey.patch_all()

from flask import Flask

from gevent import wsgi


app = Flask(__name__)


@app.route('/')

def index():

  return 'Hello World'


server = wsgi.WSGIServer(('127.0.0.1', 5000), app)

server.serve_forever()

reason:

flask is not for aysnc future model, so if you want to use asynchronous for http or any socket use, than you should use gevent wsgi

'python' 카테고리의 다른 글

python3 flask + pymongo + gevent, locust testing hangs  (0) 2017.09.26
gevent monkey patch all, code location  (0) 2017.09.14
flask gevent spawn use a lot of memory  (0) 2017.04.05
websocket with gunicorn  (0) 2017.03.03
gunicorn vs uwsgi  (0) 2017.01.20
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

async 처리되는 지 안되는지 확인하기위해서는 server코드도 중요하지만 request보내는 클라코드도 중요하다. 둘중 하나라도 잘못되면 테스트가 제대로 안되서 오해소지가 있다.

아래 코드로 python 3.5환경에서 requests library가 async로 잘 처리되는 것을 확인했다.


server

# packages

from gevent import monkey;monkey.patch_all(thread=False, subprocess=False)

import gevent

from flask import Flask, request, Response

from gevent.pywsgi import WSGIServer

from logging.handlers import RotatingFileHandler

import logging

import werkzeug.serving

import requests

import json

import resource

import hashlib

# local files

# limit gate process to use fd count less than 1024

resource.setrlimit(resource.RLIMIT_NOFILE, (1024, 1024))


app = Flask(__name__)

end_server = False

secret = None


@app.route("/do")

def check_ip():

    param = request.args.get("param", None)

    print("got {0}".format(param))

    resp = requests.get("https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5")

    # resp = requests.get("http://www.naver.com")

    print("done {0}".format(param))

    return resp.text



if __name__ == "__main__":

    http = WSGIServer(("0.0.0.0", 9999), app, log=app.logger)

    http.serve_forever()


    end_server = True

    app.logger.info("Server will be closed")

 


test client



from gevent import monkey;monkey.patch_all(thread=False)

import gevent

import requests

j = 0

host = "127.0.0.1:9999"

def test():

global j

try:

d = requests.get("http://127.0.0.1:9999/do?param="+str(j))

print(d.text+str(j))

except Exception as e:

print(e)

pass


pool = []


for i in range(0, 100):

pool.append(gevent.spawn(test))

j += 1

gevent.sleep(0.1)


gevent.joinall(pool)


 


'서버 교양' 카테고리의 다른 글

filebeat traceabck multiline config  (0) 2017.10.16
logstash conf example  (0) 2017.10.13
Logstash install  (0) 2017.03.17
[펌] 인증 암호화와 해쉬  (0) 2016.10.29
Docker overview  (0) 2015.06.13
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

If you use http request or something using socket in gevent spawn,
you should make a limit of file open count. use python resource. like this,

import resource
resource.setrlimit(resource.RLIMIT_NOFILE, (1024, 1024))

Otherwise, It will consume all your memory as much as it can by consuming all file count that it can consume as specified on limit.conf (/etc/security/limit.conf)

But requests still consumes a lot of memory.. I just decided to use tornado instead of flask+gevent+requests

'python' 카테고리의 다른 글

gevent monkey patch all, code location  (0) 2017.09.14
flask with gevent monkey patch all  (0) 2017.07.26
websocket with gunicorn  (0) 2017.03.03
gunicorn vs uwsgi  (0) 2017.01.20
flask async response  (0) 2017.01.04
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

aws api gate way

aws 2017. 3. 18. 01:14

삽질

- 허용된 request만 받고 싶을때 -> api key 이용 (Resources -> GET-> Method Request를 누르면 설정하는게 나온다)

https://www.gellock.com/2015/12/10/using-api-keys-with-aws-api-gateway/

그럼 여기나온데로 request 날릴때 해더에 x-api-key: apikey 를 보내야 허용된다.

'aws' 카테고리의 다른 글

AWS lambda 삽질 일기  (0) 2017.03.17
kinesis firehose 삽질일기  (0) 2017.03.16
How to EC2 disk and memory usage monitoring  (0) 2015.03.27
elasticache dump to file  (1) 2015.03.23
[ubuntu server instance] mytoon setting  (0) 2014.10.24
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

AWS lambda 삽질 일기

aws 2017. 3. 17. 21:08

#aws lambda python test


1. Lambda 에 올릴 zip 패키지 만들기

패키지를 모두 zip으로 해야하므로

로컬에서 directory를 하나만들고

directory/main.py python 파일을 만든다.

그리고 패키지는 이런식으로 폴더 아래 설치 되도록 한다.

"pip install module-name -t /absolute/path/to/directory"

그다음 lambda_handler function을 만들고 람다가 할일을 코딩한다. 그리고 나서 directory폴더 안에 있는 파일들을 모두 선택한다음 zip으로 만들고 lambda에 업로드한다.


2. main.py연결

Lambda configuration에 보면 Handler가 있는데 이부분을 main.lambda_handler 라고 써주면된다. "파일명.함수명" 이다.

3. Test

만들어진 람다 function을 보면 테스트 시그널을 줘서 실행해볼수 있는데 실행하면 끝날줄 모른다. 알고보면 이미 끝나있을거니 그 실행로그는 cloudWatch에가서 보면된다. 

4. 삽질

- 람다에서 커넥션 안되면 에러를 튕기기보다 설정된 타임아웃시간까지 hang이 걸린다. 따라서 스텝이 안넘어가면 뭔가 네트웤 이슈가 있구나 라고 생각하면된다.

- 일단 람다란 녀석은 만들어진 vpc내의 통신만 되기 때문에 외부 DB나 s3의 서비스 연결은 기본적으로 불가하다 -ㅅ-ㅋ 그래서 s3같은경우는 VPC -> endpoints 를 하나 만들어줘야 접근이 가능하다. 그리고 다른 vpc에 있는 DB같은경우는 Peering을 만들어서 하면되는데 그냥 peering만 만들면 접근이 안되고, 람다가 속한 vpc의 route table에 peering 접근설정을 해줘야한다.
예) destination: 10.0.0.0/28, target: pcx-c37bdsfsa(peering)(http://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide/vpc-peering-routing.html)

람다가 속한 vpc내 resource만 사용할경우 vpc만 설정해주면되고
람다가 그냥 퍼블릭 주소에 접근하는 경우만 있을경우는 vpc를 설정 안해주면된다.

하지만 이 둘을 모두 사용할땐 NAT gateway가 필요하다.. 이건 또 따로 돈나가고.. 이 두가지 모두 해당되면 람다는 좀 아닌것 같다.


*참고

http://docs.aws.amazon.com/lambda/latest/dg/python-programming-model-handler-types.html

http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html

http://blog.hde.co.jp/entry/2016/05/19/102706


'aws' 카테고리의 다른 글

aws api gate way  (0) 2017.03.18
kinesis firehose 삽질일기  (0) 2017.03.16
How to EC2 disk and memory usage monitoring  (0) 2015.03.27
elasticache dump to file  (1) 2015.03.23
[ubuntu server instance] mytoon setting  (0) 2014.10.24
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

Logstash install

서버 교양 2017. 3. 17. 15:16


Prerequisite


1. java 8

yum update

wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.rpm"

rpm -ivh jdk-8u45-linux-x64.rpm



Install Log stash


1. rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch


2. Add the following in your /etc/yum.repos.d/ directory in a file with a .repo suffix, for example logstash.repo

[logstash-5.x]

name=Elastic repository for 5.x packages

baseurl=https://artifacts.elastic.co/packages/5.x/yum

gpgcheck=1

gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch

enabled=1

autorefresh=1

type=rpm-md 


3. yum install logstash


4. info

 - /etc/logstash/logstash.yml


5. configurations for input (filebeat in my case)

vim /etc/logstash/conf.d/input-beat.conf

 input {

beats {

port => 5044

}

}


filter {

grok {

match => { 

"message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{DATA:log_level}\] %{DATA:path} %{GREEDYDATA:tail}"

} // this log format is for flask+ gevent wsgi server log

}


if "_grokparsefailure" not in [tags] {

json {

source => "tail" // json will decode target source and add all field to output json. so tail field is not needed anymore

}


mutate {

remove_field => [ "tail", "message"] //will remove specific field
gsub => ["timestamp", ",[0-9]+", ""] // replace (target field, regex, newStr) 

}

}

}



6. configurations for output (s3, elasticsearch)

(if you are using aws-es, you should add your instance public ip on the es policy)

vim /etc/logstash/conf.d/output.conf

 output {

if "_grokparsefailure" not in [tags] { // well parsed

   s3 {

     access_key_id => "crazy_key"
     secret_access_key => "monkey_access_key"
     region => "us-east-1" (US Standard)

     bucket => "your_bucket"
     size_file => 2048 (optional)
     time_file => 5    (optional) - Minutes

     codec => "json" (or "plain")

(optional. Options are "private", "public_read", "public_read_write", "authenticated_read". Defaults to "private" )

   }

}

// all logs

elasticsearch {

    hosts => ["localhost:9200"]

  }

}


7. run

systemctl start logstash


8. check log

/var/log/logstash/


Reference

1. https://www.elastic.co/guide/en/logstash/current/installing-logstash.html

2. https://alexandreesl.com/tag/logstash/

'서버 교양' 카테고리의 다른 글

logstash conf example  (0) 2017.10.13
python 3.5 flask gevent async requests test  (0) 2017.04.07
[펌] 인증 암호화와 해쉬  (0) 2016.10.29
Docker overview  (0) 2015.06.13
SSL 인증서 발급  (0) 2015.03.04
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

kinesis firehose 삽질일기

aws 2017. 3. 16. 20:09

kinesis 에 보면

streams랑 firehose가 있는데 

stream은 그냥 진짜 stream만 받는것이고

firehose는 stream을 받아서 s3나 elastic search(es)로 보내는 역할을 하는녀석이다.

차이 설명: DemystifyingAmazonKinesis_infographic.pdf

목적지가 s3와 es, redshift정도라면 firehose만 쓰면된다.


시작하기전에 한가지 알아두어야할 사실은 "그림에 속았다" 이다.

kinesis를 보면 마치 firehose하나로 s3, redshift, es에 동시에 보낼수 있을것 같이 보인다. 

하지만 설정에 들어가보면 3개중 하나를 고르라고한다.. 잉? 그리고는 백업용으로 s3를 선택할수는 있다. 그럼 redshift랑 es에는 동시에 못하나?

https://stackoverflow.com/questions/44595655/multiple-destinations-for-kinesis

같은 생각을 갖고있는 사람들이 역시 있다. 좀 가시나무들이 있지만 방법은 있단다.. firehose에 람다 트리거를 붙여서 람다가 es에 쓰도록 하는것..


아무튼, file tailing을 이용한 firehose에 로그보내기를 

aws-kinesis-agent를 설치하고 테스트해보았다.


1. config

-> /etc/aws-kinesis/agent.json

이렇게 테스트함.

{

  "cloudwatch.emitMetrics": false,

  "firehose.endpoint": "",

  "log.level": "DEBUG", 

  "flows": [

    {

      "filePattern": "/test/debug2.log",

      "deliveryStream": "test",

      "maxBufferAgeMillis": 1000,

      "minTimeBetweenFilePollsMillis": 1,

      "dataProcessingOptions": [

                {

                    "optionName": "LOGTOJSON",

                    "logFormat": "SYSLOG",

                    "customFieldNames": ["@timestamp", "host", "filename", "lineno", "msg"]

                }

            ]

    }

  ]

}


2. kinesis log

-> /var/log/aws-kinesis-agent/aws-kinesis-agent.log

먼가 안뜨거나 모니터링 할때 용이함.


3. 삽질

- firehose는 deliveryStream으로 써야한다는것

- aws key는 json파일말고 /etc/sysconfig/aws-kinesis-agent 여기에 설정해줘야 한다는것 (IAM role에서 AmazonKinesisFirehoseFullAccess 권한을 준 계정을 만들어 사용한다.)

- 로그가 오해의 소지가 있을수있다는 것. 로그는 파일 append에 상관없이 일정시간동안 찍는데 나오는 값은 agent가 실행된순간부터 지금까지의 토탈이다.

- 저 위에 dataProcessingOptions는 그야말로 옵션인데, 기본 파일에 남는 로그가 json string이 아니면 es에서 먹지 않고 에러만 남는다. (s3엔 상관없이 잘써짐) 그런데 여기서 가능한 logFormat이 4개가 있는데 이중에서 젤 만만한 녀석이 SYSLOG라 이거로 골랐다. 어떻게든 

Mar 16 10:46:49 앞에 이 타임 형식만 잘 찍어주면 뒤에는 없는 부분은 - 로 써서 넘기면 된다.

예) Mar 16 10:46:49 - main.py[123]: message

- 진짜 최강삽질은 es에 기록이 된다음부터인데, 키바나에서 일단 시작하려면 index pattern에서 add New를 해줘야하는데 이때 Time-field name이 뜨질 않는다. Advanced Settings에 가면, dateFormat:scaled라고 해서 타입을 정해줄수있는데 IOS8601 기준밖에 안된다. 그러나 Mar 16 10:46:49 이 타임형식은 rfc3164라는것!! 그래서 여기서 막혔다....


참고:

http://docs.aws.amazon.com/firehose/latest/dev/writing-with-agents.html

https://www.sumologic.com/aws/demystifying-kinesis-streams-firehose-infographic/

'aws' 카테고리의 다른 글

aws api gate way  (0) 2017.03.18
AWS lambda 삽질 일기  (0) 2017.03.17
How to EC2 disk and memory usage monitoring  (0) 2015.03.27
elasticache dump to file  (1) 2015.03.23
[ubuntu server instance] mytoon setting  (0) 2014.10.24
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

websocket with gunicorn

python 2017. 3. 3. 04:13

reference: http://d.hatena.ne.jp/Malan/20121007

flask + gevent websocket + gunicorn

실행 방법은

gunicorn --bind 0.0.0.0:yourwebsocketport -w 2 -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" yourappfilename:app

으로 실행하면 아주 잘 되야한다.


그러나 쟁점은 gunicorn 실행시

if __name__ == "__main__" 에 걸리지 않는다는것이다.

걸리게 하려면 yourappfilename을 __main__대신 넣어주면 된다.


if __name__ == "yourappfilename"

그리고 실행하면 Address already in use를 만날수 있다.

그렇다면 살며시 이부분을 주석처리해준다.

# server = pywsgi.WSGIServer((myIP, config.NOTI_WS_PORT), app, handler_class=WebSocketHandler)
# server.serve_forever()


'python' 카테고리의 다른 글

flask with gevent monkey patch all  (0) 2017.07.26
flask gevent spawn use a lot of memory  (0) 2017.04.05
gunicorn vs uwsgi  (0) 2017.01.20
flask async response  (0) 2017.01.04
functools.wraps에 대해  (0) 2015.04.15
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,