반응형

분명 잘 구현한거같은데 해당 토큰을 넣고 테스트를 진행하면

자꾸 인증이 되지 않는다는 메세지를 보게되었을때 점검해봐야하는 부분이다.

 

다른 여러가지 부분을 확인해봐야하겠지만

내 구현엔 문제가 없는데... 이런생각이라면

import한 부분을 체크해보자.

 

import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local'; # 여기가 문제
import { ExtractJwt } from 'passport-jwt';

export class GraphqlStrategy extends PassportStrategy(Strategy, 'jwt') {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET,
      usernameField: 'email',
      passwordField: 'password',
    });
  }

  async validate(token: string) {
    return token;
  }
}

 

위에서 문제는 passport-jwt와 passport-local을 호환해서 사용했기 때문이다.

 

 

import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

export class GraphqlStrategy extends PassportStrategy(Strategy, 'jwt') {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET,
      usernameField: 'email',
      passwordField: 'password',
    });
  }

  async validate(token: string) {
    return token;
  }
}

 

반응형

gunicorn에 대해서 처음 작업해보았는데 성능을 개선해보아야했다.

worker라던지, gevent라던지 이런 부분에 대해서 알고있어야하는데

관련해서 추천할 블로그이다.

http://blog.hwahae.co.kr/all/tech/tech-tech/5567/

오늘의 집 테크 블로그인데 gunicorn에 대해서 공부하기 좋다.

나름 글이 잘읽히고 정보의 질이 좋다.

위 내용이 어느정도 읽히고 테스트를 해보았다면

오늘 에러관련내용해서 쓰는글을 이해하기 편할것이다.

문제가 되는 부분의 코드이다.

import logging.config
from gevent.monkey import patch_all
patch_all()
# 이 부분이 해결하기 위한 코드 
# import grpc.experimental.gevent as grpc_gevent
# grpc_gevent.init_gevent()

from flask import Flask
from config.default import CONFIG
from views.pixel_view import bp
from config.logger import LOGGING_CONFIG
from views.scheduler import scheduler, get_destination_template

def create_app():
    logging.config.dictConfig(LOGGING_CONFIG)
    if CONFIG['APP_ENV'] == 'PRODUCTION':
        logging.disable(logging.DEBUG)
    else:
        logging.disable(logging.NOTSET)

    ap = Flask(__name__)

    ap.url_map.strict_slashes = False
    ap.register_blueprint(bp)

    ap.config['SCHEDULER_API_ENABLED'] = True

    if not scheduler.running:
        scheduler.init_app(ap)
        scheduler.start()
        # break point
    **get_destination_template()**

    return ap

app = create_app()
logger = logging.getLogger('default')

if __name__ == '__main__':
    logger.info('APP START AND POLL START')
    app.run(port=5001)




위 코드를 보면 python cronjob도 돌리고있고 api서버의 기능도 있다.

스케줄링관련 프로세스에는 google 제품을 사용하는 코드들이 있다. bigtable요청관련된 부분이다.

그렇지만 위에 break point를 걸어보면 아래와 같은 코드에서 freezing이 걸린다.

def _run_channel_spin_thread(state):

    def channel_spin():
        while True:
            #freezing point 
            cygrpc.block_if_fork_in_progress(state)
            event = state.channel.next_call_event()
            if event.completion_type == cygrpc.CompletionType.queue_timeout:
                continue
            call_completed = event.tag(event)
            if call_completed:
                with state.lock:
                    state.managed_calls -= 1
                    if state.managed_calls == 0:
                        return

    channel_spin_thread = cygrpc.ForkManagedThread(target=channel_spin)
    channel_spin_thread.setDaemon(True)
    channel_spin_thread.start()




이 파일의 경로는 아래와 같다





grcp에서 프로세스를 fork하는 부분에서 freezing이 걸리는걸 확인하는 순간이다.

충돌이 일어난다고 볼수 있다.

이 부분을 해결하기 위해선 첫 코드에서 주석을 해제하는 코드를 작성해야한다.

import logging.config
from gevent.monkey import patch_all
patch_all()

# 이 부분이 해결하기 위한 코드 
import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()

from flask import Flask
from config.default import CONFIG
from views.pixel_view import bp
from config.logger import LOGGING_CONFIG
from views.scheduler import scheduler, get_destination_template

def create_app():
    logging.config.dictConfig(LOGGING_CONFIG)
    if CONFIG['APP_ENV'] == 'PRODUCTION':
        logging.disable(logging.DEBUG)
    else:
        logging.disable(logging.NOTSET)

    ap = Flask(__name__)

    ap.url_map.strict_slashes = False
    ap.register_blueprint(bp)

    ap.config['SCHEDULER_API_ENABLED'] = True

    if not scheduler.running:
        scheduler.init_app(ap)
        scheduler.start()
        # break point
    **get_destination_template()**

    return ap

app = create_app()
logger = logging.getLogger('default')

if __name__ == '__main__':
    logger.info('APP START AND POLL START')
    app.run(port=5001)




사용한 패키지 버전이다.

gevent = "~=21.8.0"
gunicorn = "~=20.1.0"

google제품과 사용 시 freezing현상이 있다면 이 부분을 확인해보면 도움이 될 거 같다.

'백엔드 > Python' 카테고리의 다른 글

[Python]ModuleNotFoundError: No module named '_ctypes'  (0) 2021.01.04
반응형

pyenv나 기타 방법으로 파이썬 3.7.x를 설치하려다 보면 아래와 같은 에러가 발생하는 경우가 있다.

ModuleNotFoundError: No module named '_ctypes'


해결방법

# libffi-dev 패키지를 설치해준다.
# 우분투
sudo apt install libffi-dev 

# 레드헷이나 페도라 리눅스는 아래처럼 설치.
sudo apt install libffi-devel

#centos
sudo yum install libffi-devel

 

설치 시 libffi-devel 해당 모듈이 설치가 되지 않아 생기는 오류이다.

해당 os에 맞게 설치 한다.

'백엔드 > Python' 카테고리의 다른 글

[Python] gunicorn 과 grcp 충돌  (0) 2021.09.24
반응형

해당 에러는 개발 시 메모리를 많이 사용하는 부분이 생성되어

코드 중 어느 부분인가 잘못되면 메모리가 사용 되게 되었다.

오늘은 잘못 짠 내 코드를 보면서 개선해보겠다.

// file : File 변수
// s3Client :s3 uploader

byte[] bytes = IOUtils.toByteArray(file.getInputStream());
    	
ObjectMetadata objMeta = new ObjectMetadata();
objMeta.setContentLength(bytes.length);
ByteArrayInputStream byteArrayIs = new ByteArrayInputStream(bytes);
s3Client.putObject(new PutObjectRequest(filePath, fileName, byteArrayIs, objMeta)
        .withCannedAcl(CannedAccessControlList.PublicRead));
s3Client.getUrl(filePath, fileName).toString();

 

아직도 스트림에 대해서 제대로 이해를 하지 못하는 수준의 코드이다.

 

 

대략적으로 설명을 하자면

S3 Uploader에서 Metadata 에 length를 계산하기 위해 IOUtils.toByteArray 으로 바이트로 변환하여

byte[] 을 .length로 출력한다.

이후 ByteArrayInputStream 으로 다시 변환하여 S3에 업로드 변수에 넣는다.

이렇게 설명할 수 있다.

 

보다 보니 반복되는 부분이 보이는것 같다. InpustStream이 두번 생성되는 부분이 있다.

코드 첫라인인 1번째 라인과 5번 라인에서 반복되는 구문이 보인다. 이렇게 사용하게되면 물론 반복에도 문제가 있지만

해당 서비스는 용량이 큰 파일을 upload하기때문에 메모리에 큰 부하가 오게된다.

개선하기 위해 아레와 같이 반복되는 부분을 제거하였다.

// file : File 변수
// s3Client :s3 uploader
    	
ObjectMetadata objMeta = new ObjectMetadata();
objMeta.setContentLength(bytes.length);
s3Client.putObject(new PutObjectRequest(filePath, fileName, file.getInputStream(), objMeta)
        .withCannedAcl(CannedAccessControlList.PublicRead));
s3Client.getUrl(filePath, fileName).toString();

 

 

반복 구문

 

byte[] bytes = IOUtils.toByteArray(file.getInputStream());

ByteArrayInputStream byteArrayIs = new ByteArrayInputStream(bytes);

OutputStream으로 만들고, InputStream으로 만드는 두 부분을 제거하였다.

반복되는 부분을 제거하고 메모리 모니터링을 진행한 결과

현저히 메모리 사용량이 줄어들었다. 엉뚱한곳을 바라보고 메모리 수정을 하였으나

Java heap memory 에러에서는 몇번째 라인에서 에러가 나는지 보여주고있었다.

꼭 에러로그에 기반한 오류수정을 우선적으로 하길.

반응형

[CriteriaBuilder]


해당 내용을 사용하다보면 

Unable to locate appropriate constructor on class

관련돤 에러를 볼 수 있는데


해당 내용은 모델끼리 맵핑이 되지 않아서 나오는 오류이다.


이 애러를 알더라도 맵핑의 순서를 알기쉽지 않은데 

오늘 해본 결과는 이러하다.


1. 다수가 되는 테이블 컬럼을 먼저 쓸 것

2. 다수가 되는 테이블에 Serializable을 적용할것

3. 컬러수를 다수-> 단일 순서로 맞춰줄것.


나의경우는 ManyToOne 이 단일테이블 걸려있으면서 아래와 테이블이 같다


다수 테이블 implements Serializable

A -1 ,2, 3


단일 테이블

B -3, 4, 5


이럴때 multiselect 에 쓰이는 Selection list 는 

1, 2, 3, 4, 5 


이 순서로 써야 한다. 다수테이블 컬럼이 앞에 쓰여야한다.


'백엔드 > 웹(Spring)' 카테고리의 다른 글

[Spring] forward / redirect  (0) 2016.09.16
반응형

- 출처

http://chan7ee.tistory.com/entry/redirect-forward-java-controller-method%EC%97%90%EC%84%9C-%EB%8B%A4%EB%A5%B8-do-%EB%A5%BC-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95




여기에 추가할 내용이 있다.


forward를 할때에는 jsp 화면 기준으로 넘겨지는 값들이 넘어간다.


예를들어 

FORM 안에 FOOD 라는 값이 있다면

화면에서 값을 지정해야만 다음화면에서 REQUEST PARAMETER를 사용 할 수 있다.


컨트롤러에서 FOOD를 지정한다면

그 값은 넘어가지 않는다.




-----

나의 경우는 FIRST JSP -> 1CONTROLLER -> 2CONTROLLER -> END JSP 이런 흐름으로 짜여있는데

FIRST JSP에서 값을 지정했어야 했다.


1CONTROLLER에서 아무리 지정해도 값은 넘어가지 않았다.


'백엔드 > 웹(Spring)' 카테고리의 다른 글

[JPA] CriteriaBuilder - multiselect  (0) 2018.11.05

+ Recent posts