Flask로 웹서버를 임시로 기동하면

WARNING : This is a development server. Do not use it in a production deployment.

Use a production WSGI server instead.

라는 문구를 볼 수 있다.

 

개발환경과 같이 단 건의 요청을 처리하는데는 flask를 써도 상관없지만

상용과 같이 high load 환경에서 flask는 분산처리가 제대로 되지 않아 요청을 처리하는데 실패하거나, 처리가 지연돼서 read timeout이 발생하기 쉽다.

 

이러한 문제를 해결하기 위해 nginx와 WSGI 서버를 사용하는 것이 정석이다.

나의 경우 API 서버라서 nginx를 사용하지 않고 WSGI 서버만 사용하고싶었다.

 

다른 출처에서는 gunicorn으로 flask의 app.py를 한번 더 감싸는 방법을 소개하는데,

flask의 app.py를 gunicorn 모듈로 실행하는 방법도 있다.

명령어는 

gunicorn --workers=1 --threads=4 --bind 0:5000 --timeout=0 file_name:app

이고, 

nohup 명령어를 이용해서 백그라운드로 실행할 수도 있다.

 

Flask나 Locust와 같이 웹서버를 기동하는 경우 flask run 이나 locust 명령어 실행시 특정환경에서

Fatal error in launcher: Unable to create process using "실행경로"와 같이 나오는 경우가 있다.

 

이 경우 python -m 이라는 명령어 (모듈로 인식)를 쓰면 정상적으로 동작한다.

 

 

 

 

약 2기가정도가 운영체제이고 남은 공간은 할당되지 않은 상태인데 그대로 라즈베리파이에 넣으면된다.

할당되지 않은 공간은 처음 부팅이 되면서 할당된다

첫 login은 ubuntu/ubuntu로 하면된다.

바로 비밀번호를 변경해준다.

 

 

우선 인터넷 연결을 위해 ip를 잡아준다.

1) 최상위 경로로 이동(cd .. 두번)

2) sudo nano etc/netplan/50-cloud-init.yaml

network:
  ethernets:
    enp0s3:
      addresses: [192.168.0.136/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4] #네임서버 설정이 안되면 apt upgrade가 안됨
  version: 2

3) sudo netplan apply : 설정 적용

[sklearn] cython 코드 수정하기

 

sklearn 패키지의 일부 알고리즘은 속도를 위해 c언어 기반의 python으로 작성되어있다.

일반적으로 이 수준의 알고리즘을 변경할 일이 거의 없어서 그런지 site-package에 있는 코드는 이미 컴파일이 된 상태라서 수정이 불가능했다. 환경은 ubuntu이고 python은 3.8에서 테스트하였다.

 

수정을 하기 위해서는

1. sklearn 의 깃 저장소에서 컴파일되지 않은 코드 _cd_fast.pyx 파일을 다운받는다.

2. 컴파일된 파일과 같은 경로에 추가한다.

3. _cd_fast.pyx 를 입맛대로 바꿔서 다시 컴파일한다.

 

3. 의 과정을 자세히 설명하자면,

우선, pyx 파일을 컴파일하기 위해 cython이 설치되어 있어야한다.

그리고 setup.py 파일을 만들어 pyx 파일을 컴파일하는 코드를 추가해야한다.

import numpy
from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("_cd_fast.pyx"),
    include_dirs=[numpy.get_include()]
)

이 코드를 실행시키는 코드는 아래와 같으며, cython 문서를 참조하면 된다.

python setup.py build_ext --inplace

 

코드 수정 과정에서 발생한 에러와 해결방법은 아래와 같다.

 

not allowed without gil error

cython에서는 gil (global interpreter lock) 이라는 cpu processing 방식이 존재하는데 코드 중 with nogil 이 있는곳에 코드를 임의로 수정하는 경우 아래와 같은 에러가 발생할 수 있다. 이 경우 with nogil의 코드블럭을 주석처리하면 에러가 사라진다. 

 

gcc failed with exit status 1

컴파일 과정에서 꽤 자주 발생할 것 같은 에러이다. gcc가 설치 되어있다는 가정하에 아래와 같은 에러가 뜬다면 코드를 추가하여 해결할 수 있다.

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("_cd_fast.pyx")
)

import numpy
from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("_cd_fast.pyx"),
    include_dirs=[numpy.get_include()]
)

include_dirs=[numpy.get_include()]를 추가하면 에러를 해결할 수 있다.

 

[SimPy] 파이썬 시뮬레이션: 기초 알아보기

 

 

1. Environment

Environment 클래스를 객체화(선언)하는 것은 새로운 게임을 생성하는 것과 같다.

 

import simpy

env = simpy.Environment()

 

위와 같이 simpy의 Environment 클래스를 인스턴스화 하여 environment를 정의한다.

 

2. Process Interaction

Process는 다른 프로세스를 기다리거나 중간에 interrupt를 걸 수 있게 하는 env의 기능이다. 

import simpy

env = simpy.Environment()
car = Car(env)
env.run(until=15)

이 차는 전기차여서 충전시간이 필요하다. 충전은 charge()라는 함수로 구현하고 '5'라는 충전시간이 지나면 차는 출발한다.

class Car(object):
    def __init__(self, env):
    	self.env = env
        self.action = env.process(self.run())
        
    def run(self):
    	charge_duration = 5
    	yield self.env.timeout(self.charge(charge_duration))
    	
    def charge(self, duration):
    	yield self.env.timeout(duration)

운전자가 충전을 다 기다리지 않고 출발을 원한다면 어떻게 구현해야 할까? 충전은 run() 함수 안에서 돌아가므로, run()에 interrupt를 거는 함수를 만들 필요가 있다.

 

2-1 Interrupting another process

interrupting을 구현하기 위해 driver라는 함수를 만들었다.

def driver(env, car):
    yield env.timeout(3)
    car.action.interrupt()

 이 함수는 클래스 내부에서 선언하지 않았다. 이 함수는 car라는 클래스 인스턴스를 파라미터로 받아 env.process를 interrupt 한다.

import simpy

env = simpy.Environment()
car = Car(env)
env.process(driver(env, car))
env.run(until=15)

 

3. Resources

리소스란 사용 가능한 자원이다. 예를 들어, 충전기가 5개인 충전소에 여러대의 차들이 충전을 하러 오는 상황을 생각해 볼 수 있다. 그리고 일반적인 카페와 같이 만들어서 파는 생산자-소비자 관계가 있을 수 있다.

def car(env, name, station, driving_time, charge_duration):
	yield env.timeout(driving_time) # 차가 돌아다니다가 들어올 시간
    
    print(f'{name} 차가 충전소에 {env.now}에 도착했습니다.)
    with station.request() as req:
    	yield req
        
        print(f'{name} 차가 충전을 시작한 시간 {env.now}')
        yield env.timeout(charge_duration)
        print(f'{name} 차의 충전이 완료된 시간 {env.now}')
        
import simpy
env = simpy.Environment()
station = simpy.Resource(env, capacity=2)

for i in range(4):
	env.process(car(env, f'Car {i}', station, i*2, 5))

env.run()    

 

Resource클래스를 station으로 인스턴스화했고 Resource 인스턴스는 request() 함수를 사용할 수 있다. 이 함수는 리소스인 station이 다시 사용가능해질 때까지 기다리게 한다. station의 리소스 총량은 capacity 값으로 정할 수 있다.

여기서 충전소가 차에게 리소스를 제공하는 형태는 FIFO(first in first out) 방식이다.

   

[Javascript] 마니또 알고리즘(리스트 셔플 List shuffle)


가끔 오프라인으로 종이뽑기로 하면 본인을 뽑는 경우도 있는데 마니또는 본인 말고 다른 사람을 뽑는 알고리즘입니다.

O(n^2)이라 좋은 알고리즘은 아닌거 같은데 다른 방법을 생각해내지 못했습니다.


 A, B, C, D, E 5명이 서로 다른 사람을 뽑게 하려면 A부터 순서대로 1~5번까지의 숫자를 뽑는데 1번을 제외한 숫자를 뽑도록 했습니다.

우선 랜덤한 숫자를 먼저 뽑는데 0부터 4의 숫자가 랜덤하게 추출됩니다.(while문 조건중 i == temp 를 빼면 리스트 셔플이 될 것입니다.)

while(i == temp || result.includes(temp))

이 조건은 자기 자신을 뽑지 않고 이미 뽑힌 사람은 뽑지 않는 조건이고, 자기 자신이거나 result에 숫자가 있을 경우엔 True가 되므로 False가 될 때까지 반복 추출을 합니다.



var dbconnect = require('./sqlite');
exports.createtable = function(){

var name_list = ['A', 'B', 'C', 'D', 'E'];

var result = [];
for(var i=0; i < name_list.length; i++){

var temp = Math.floor(Math.random()*name_list.length);

while(i == temp || result.includes(temp)){

temp = Math.floor(Math.random()*name_list.length);

}
result.push(temp);
var ins_sql = `INSERT into member (name, manitto) VALUES (?, ?)`
var ins_list = [name_list[i], name_list[result[i]]]
console.log(ins_list)
dbconnect.insert(ins_sql, ins_list, function(db){});
}
}

 


이 코드에선 추출 결과를 저장하기 위해 DB에 Insert 하도록 했습니다.


다른 아이디어가 있으시면 댓글로 남겨주세요!ㅎㅎ

[Nginx] 포트 리다이렉트, Proxy_pass 설정하기



Nginx 설치하기


Nginx를 이용하면 ip:port와 같이 특정 포트로의 연결을 리다이렉트 해줄 수 있다.

우선 nginx의 설치와 명령어는 아래와 같다.


 설치
$ sudo apt-get install nginx

버전 확인 $ nginx -v


 시작
$ sudo service nginx start

재시작
$ sudo service nginx restart

중지
$ sudo service nginx stop

상태
$ sudo service nginx status

설정 reload
$ sudo service nginx reload


서버의 포트는 열려있다고 가정하겠다.

AWS를 사용하는 경우 인바운드 규칙으로 넣어줄 수 있다. 3001번 포트를 열었는데 nginx 설정을 마치면 지워도 된다.



Nginx 설정 파일 수정하기


경로를 확인하는 방법과 설정파일을 수정하는 명령어이다.


$ sudo find / -name nginx.conf
$ sudo vi /etc/nginx/nginx.conf


그리고 아래의 코드를 http{ } 안에 써주기만 하면 된다. 인터넷에 예제로 나온 conf 파일과 형식이 달라 처음에 조금 시행착오를 겪었지만 http{ 안에만 넣어주니 됐다. 


server { # simple reverse-proxy

                listen       80;

                server_name  domain.com;


                # pass requests for dynamic content to rails/turbogears/zope, et al

                location / {

                        proxy_pass      http://127.0.0.1:3001;

                }

        }



'Computer Science > 웹 개발' 카테고리의 다른 글

[AWS ec2] Node.js 설치하기  (0) 2018.11.26

[AWS ec2] Node.js 설치하기


AWS linux ec2에서 node.js를 설치하는 방법은 아래와 같다.



1. SSH를 이용하여 Linux 인스턴스에 접속한다.


2. nvm 설치

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.0/install.sh | bash



3. activate nvm

. ~/.nvm/nvm.sh


4. node js 설치(원하는 버전으로)

nvm install 4.4.5

nvm install stable(안정 버전-추천)


5. 설치확인

node -e "console.log('Running Node.js ' + process.version)"





[선형대수] 너무 쉬운 고유값(eigenvalue)과 고유벡터(eigenvector)


고유값과 고유벡터의 의미는 나중에 설명하기로 하고 아래의 행렬 곱을 보자.


계산 결과 값에 어떤 값을 곱해서 원래의 111행렬을 만들 수 없다.


이번엔 1 1 0 행렬을 곱해보자.

이 경우엔 결과 값에 1/3을 곱해서 1 1 0을 만들 수 있다.


여기서  

에서 3이 고유값이고 고유벡터이다.


정의

n x n 행렬 A가 있을 때 아래의 식을 만족하는 는 고유값, X는 고유벡터이다.

 

이식을 방정식 형태로 쓰면 

 이 된다. 고유벡터는 영이 아닌 벡터로 정의 되어있으므로 x의 계수행렬이 특이행렬이어야 한다.

 는 A의 특성방정식(characteristic equation)이라고 부른다.


이 방정식을 풀면 고유값과 고유벡터를 구할 수 있다.


예제1


의 특성다항식은 아래와 같다.


그리고 행렬식 계산을 통해 구한 특성방정식은 아래와 같다.

방정식을 풀면 해는 2 또는 -1이다.

즉, A의 고유값은 2와 -1이다.


람다 2를 위의 식에 다시 대입하면,

이고

이 되어 의 관계를 얻는다. 이 방정식 계의 해는 r을 스칼라로 놓고 

로 나타낼 수 있다. 즉 에 대응하는 고유벡터는  의 형태인 영이 아닌 벡터가 된다.

마찬가지로 을 대입하면 형태의 고유벡터를 구할 수 있다. (s는 스칼라)





마코프체인(Markov chain)


마코프체인은 과거의 상태와 현재 상태가 주어질 때, 미래 상태의 조건부 분포는 과거 상태에는 독립이고 오직 현재 상태에만 종속한다.


예를 들어보자,

1. 날씨 예측

 내일 비가 올 가능성은 오직 오늘 비가 오는지 안 오는지에만 종속하고 과거의 날씨에는 종속하지 않는다고 가정한다. 또한, 오늘 비가 올 때 내일 비가 올 확률은 a이고 오늘 비가 오지 않을 때 내일 비가 올 확률은 b라고 가정하자.

비가 올 때는 상태를 0이라고 하고 비가 오지 않을 때는 상태를 1이라고 하면, 이 과정은 다음의 전이확률을 갖는 2-상태 마코프체인이 된다.


2. 확률 과정을 마코프체인으로 변환하기

오늘 비가 올지의 여부가 과거 날씨 중 최근 이틀의 날씨에만 영향을 받는다고 가정하자. 

1. 지난 이틀 동안 비가 왔으면 내일도 비가 올 확률은 0.7이다.

2. 어제는 비가 오지 않고 오늘 비가 왔다면 내일 비가 올 확률은 0.5이다.

3. 어제는 비가 왔지만 오늘은 오지 않았다면 내일 비가 올 확률은 0.4이다.

4. 지난 이틀 간 비가 오지 않았다면 내일 비가 올 확률은 0.2이다. 


상태 0 : 오늘과 어제 모두 비가 옴

상태 1 : 오늘 비가 오고 어제는 안 옴

상태 2 : 어제 비가 오고 오늘은 안 옴

상태 3 : 어제와 오늘 모두 비가 안 옴


위 상태는 다음과 같은 전이확률 행렬을 갖는 4-상태 마코프체인을 나타낼 것이다.


3. 랜덤보행 모형

상태공간이 정수로 주어진 마코프체인이 어떤 상수 0<p<1에 대해 다음 관계를 만족하면 랜덤보행(random walk)라고 말한다.

이 마코프체인이 랜덤보행이라고 불리는 이유는, 직선 위를 걷고 있는 사람이 각 시점마다 확률 p로 오른쪽으로 한걸음 가든 1-p의 확률로 왼쪽으로 한걸음 가는 것에 대한 모형으로 볼 수 있기 때문이다. (무한도전에서 위에서 공 떨어뜨리면 중간에 막대에 맞고 아래로 내려가는 복불복 게임이랑 비슷한 것 같다. 사진은 못 찾음 ㅎㅎ)


4. 인구이동 모델

2007년에 미국의 도시에 살고 있는 사람의 수는 8천2백만이고 주변 교외에 살고 있는 사람의 수는 1억6천3백만으로 추정된다. 이 정보를 행렬 로 나타내자. 

2007년 인구 흐름은 도시에 그대로 머물 확률은 0.96이었고 교외로 이사 갈 확률은 0.04였다. 거꾸로 교외에서 도시로 이주할 확률은 0.01이었고 교외에 남아 있을 확률은 0.99였다. 이 확률을 원소로 하여 확률행렬 P를 다음과 같이 쓸 수 있다.

       도시 교외(에서)  (로)

   

2008년도의 인구는 행렬 곱으로 얻을 수 있다.


행렬 P로 표현된 인구흐름이 매년 변하지 않는다고 가정하면, n년 후의 인구 분포는,

로 나타낼 수 있다. 즉, 

 이고 은 n-단계 전이행렬로 불린다.


사실 인구 인구이동의 확률행렬 P는 매년 같다고 하기 어려운 점이 있다. 그래서 인구 이동 보다는 유전 법칙이 마코프체인을 적용하기에 적절하다고 생각한다.

+ Recent posts