최근에 업무하면서

TaskExecutor과 TaskScheduler를 모두 쓸 일이 있었다

 

그래서 개념에 대해서 깊게 보고싶어서

토비의 스프링을 펼쳐보았다^^7777

역시 이거만한게 없다..

 

정리해보쟛...ㅁ7ㅁ8

 

 


1. TaskExecutor

task실행기.. 그렇담 task는 뭘까?

 

Task : 독립적으로 실행한 가능한 작업

 

스프링은 이러한 task들을 다양하게 실행하도록 추상화하여 TaskExecutor라는 인터페이스를 제공한다.

 

package org.springframework.core.task;

import java.util.concurrent.Executor;

@FunctionalInterface
public interface TaskExecutor extends Executor {
    void execute(Runnable var1);
}

 

java5의 Executor 인터페이스를 상속한다.

 

Runnable타입의 태스크를 받아 실행하는데,

다음 인터페이스는 독립적인 스레드에 의해 실행 되도록 의도된 오브젝트를 만들 때 주로 사용된다.

package java.lang;

@FunctionalInterface
public interface Runnable {
    void run();
}

 

Spring의 TaskExecutor는 java.lang.concurrent 패키지 의 Executor와 똑같은 메소드를 가지고 있다. 

 

package java.util.concurrent;

public interface Executor {
    void execute(Runnable var1);
}

 

그럼에도 스프링에서 다시 만든이유는 다음과 같다.

 

1. 다른 기술의 태스크 실행기에 대한 어댑터를 제공 ( Quartz , CommonJ WorkManager...)

2. 스프링에 최적화된 방식의 태스크 실행기 확장 

 

반드시 비동기 독립적 스레드에서 실행될 필요는 없지만 ,

대부분 비동기로 쓴닷 ㅎ_ㅎ

 

 

2. TaskExecutor 구현체

 

2.1 ThreadPoolExecutor

corePoolSize, maxPoolSize , queueCapacity 속성을 설정할 수 있다.

지정된 크기의 스레드 풀을 이용하며 , 작업 요청은 큐를 통해 관리된다.

가장 대표적인 태스크 실행기다.

 

 

   @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("async-");
        executor.initialize();
        return executor;
    }

 

2.2 SimpleThreadPoolTaskExecutor

Quartz의 SimpleThreadPool을 이용해 만들어진 태스크 실행기이다.

 

2.3 WorkManagerTaskExecutor

CommonJ WorkManager의 태스크 실행기에 대한 어댑터이다.

 

 

2.4 SyncTaskExecutor

별도의 스레드에서 수행되는게 아니라 호출한 스레드 상에서 호출

 

 


3. TaskScheduler 

다음 인터페이스는 주어진 태스크를 조건에 따라 실행하거나 반복하는 작업을 수행

태스크의 실행조건은

1) 특정시간

2) 일정한 간격을 두고 반복

3) Trigger인터페이스를 구현해서 유연한 조건 

 - > cron 서버의 실행시간 설정 포맷을 활용한 cronTrigger가 가장 대표적인 구현 클래스이다. 

 

package org.springframework.scheduling;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
import org.springframework.lang.Nullable;

public interface TaskScheduler {
    @Nullable
    ScheduledFuture<?> schedule(Runnable var1, Trigger var2);

    default ScheduledFuture<?> schedule(Runnable task, Instant startTime) {
        return this.schedule(task, Date.from(startTime));
    }

    ScheduledFuture<?> schedule(Runnable var1, Date var2);

    default ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
        return this.scheduleAtFixedRate(task, Date.from(startTime), period.toMillis());
    }

    ScheduledFuture<?> scheduleAtFixedRate(Runnable var1, Date var2, long var3);

    default ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Duration period) {
        return this.scheduleAtFixedRate(task, period.toMillis());
    }

    ScheduledFuture<?> scheduleAtFixedRate(Runnable var1, long var2);

    default ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
        return this.scheduleWithFixedDelay(task, Date.from(startTime), delay.toMillis());
    }

    ScheduledFuture<?> scheduleWithFixedDelay(Runnable var1, Date var2, long var3);

    default ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Duration delay) {
        return this.scheduleWithFixedDelay(task, delay.toMillis());
    }

    ScheduledFuture<?> scheduleWithFixedDelay(Runnable var1, long var2);
}

 

 

4. TaskScheduler 구현체

 

4.1 ThreadPoolTaskScheduler

JDK의 ShcdeuledThreadPoolExecutor 스케쥴러에 대한 어댑터이다.

 

 

    @Bean
    public TaskScheduler scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("Scheduler-Thread-");
        scheduler.initialize();
        return scheduler;
    }

 

 

4.2 TimerManagerTaskScheduler

 

참고) 유연한 조건을 이용!할때 쓰는 Trigger 인터페이스

 

package org.springframework.scheduling;

import java.util.Date;
import org.springframework.lang.Nullable;

public interface Trigger {
    @Nullable
    Date nextExecutionTime(TriggerContext var1);
}

 

그 Trigger 인터페이스를 구현한 CronTrigger  CronExpression을 지원한다.

package org.springframework.scheduling.support;

import java.util.Date;
import java.util.TimeZone;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

public class CronTrigger implements Trigger {
    private final CronSequenceGenerator sequenceGenerator;

    public CronTrigger(String expression) {
        this.sequenceGenerator = new CronSequenceGenerator(expression);
    }

    public CronTrigger(String expression, TimeZone timeZone) {
        this.sequenceGenerator = new CronSequenceGenerator(expression, timeZone);
    }

    public String getExpression() {
        return this.sequenceGenerator.getExpression();
    }

    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date date = triggerContext.lastCompletionTime();
        if (date != null) {
            Date scheduled = triggerContext.lastScheduledExecutionTime();
            if (scheduled != null && date.before(scheduled)) {
                date = scheduled;
            }
        } else {
            date = new Date();
        }

        return this.sequenceGenerator.next(date);
    }

    public boolean equals(Object other) {
        return this == other || other instanceof CronTrigger && this.sequenceGenerator.equals(((CronTrigger)other).sequenceGenerator);
    }

    public int hashCode() {
        return this.sequenceGenerator.hashCode();
    }

    public String toString() {
        return this.sequenceGenerator.toString();
    }
}

 

 


5. Annotaion 활용 ( @Scheduled , @Async )

 

5.1 @Scheduled

태스크 역할을 맡은 메소드에 직접 스케줄 정보를 어노테이션을 통해 부여해 수케줄이 적용되게 해준다.

@Scheduled 부여되는 메소드는 파라미터를 가질 수 없으며 반드시 void형 리턴 타입이어야한다.

 

-  fixedDelay : 이전 작업이 끝난 시점부터 일정시간이 지난후에 동작하도록 설정 ,

 이전 작업이 끝난후로 부터 정해진 시간이 지난후 다음작업이 시작된다.

@Schduled (fixedDelay=60000)
public void testFixedDelay(){...}

 

- fixedRate : 밀리초로 설정된 일정한 시간간격으로 메소드 실행 

@Schduled (fixedRate=60000)
public void testFixedRate(){...}

 

- cron : Cron expression 으로 메소드 실행

@Schduled (cron = "0 0 12 1 * ?")
public void testCron(){...}

 

 

5.2 @Async 

TaskExecutor를 코드로 사용하지 않고도 비동기 실행이 가능하게 해주는 어노테이션이다.

( 그런데 설정이 필요하면.. Bean으로 만들어주는게 좋다.. threadpool size 등등..)

 

리턴타입은  void 또는 Future 타입이어야한다.

메소드는 다른 코드에 의해 직접 호출 되므로 파라미터를 가질 수 있다. 

 

더자세한 내용은 이전에 포스팅한 이글을 참조한다.

https://hyeonyeee.tistory.com/55

 

Spring에서 Async 처리 (@Async )

Spring에서 Async처리를 해보겠다..! 블로그에 정리되어 있는게 많았는데 그중에 어떤 방법을 택할까 고민을 했다. 가장 간단한 방법으로 구현하였다. @Async annotaion을 붙여주는 방법이다. 1. @EnableAsyn

hyeonyeee.tistory.com

 

 

 


6. 결론

 

정리하다보니 더 자세히 이해가 되었다.

그리고 이전에 개발한 코드가 더 잘 와닿게 되었다 후후

 

그래서 한마디로 정리하자고 하면

 

TaskExecutor는 task를 주로 비동기적으로 처리할때 쓰고

TaskScheduler는 스케줄링할때 쓴다.

 

이 두개 모두 @Async , @Scheduled 라는 어노테이션으로 대체가 가능한데,

자세한 설정이 필요하면

bean으로 만들어 주는것이좋다~ (@Configuraion...)

 

그럼 정리 끝 - 

Backend 개발을 하다보면 인증방식을 결정해야 되는 순간이 꼭 있다.

 

서버와 서버간의 인증

서버와 모바일 서버

아니면 유저가 api서버를 가져다 쓸 때 의 인증 등등..

 

Backend 서버에서 제공해주는 정보를 가져다 쓸 때 인증이 필수 라고 볼 수 있다.

매 HTTP 요청마다 본인이 누구인지 알 수 있는 인증정보를 요청에 포함 시켜 요청해야한다. 

 

그런데 현업에서는 

다양한 아키텍쳐와 비지니스 로직이 있기 때문에

그러한 범위내에서 과연 수많은 인증 방식 중에서 어떤 인증 방법을 택하면 좋을까?

란 고민을 하게된다.

 

어떤 인증 방식을 택하면 좋을지? 를 결정하려면

당연히 어떤 인증방식이 있는지 알면 되지 않을까,,,,

 

란 답으로 시작해서 이번 포스팅을 하게 되었다.

(사실 보안이나 여러가지 개념이 너무너무 헷갈렸다 ^_^; 이러면서 배우는거쥐 뭐~)

 

그리고 Spring Security와 결부시켜서도 얘기해보겠다.

 


1. id + password 방식

가장~~~ 기본이 되고 간단한 방식이다.

그냥 DB에 있는 id와 password 를 요청에서 넣어준 값과 같은지 확인하는 방식이다.

 

여기서 한단계 더 나아가면 password를 암호화정도 하면 되겠다.

 

Spring Security에서도 이부분이 Default인 방식으로 볼 수 있다.

화면 Form에 그냥 id + password 를 담아서 넣어주면 인증이 된다.

 

 

2. Basic Auth

Basic Auth 도 간단한 방법인데

id:password 이 값을 base64로 인코딩한 값을 HTTP 헤더에 담아서보내주면 된다.

Authorization : Basic Base64(id:password)

 

ex) Authorization : Basic VGVycnk6aGVsbG8gd29ybGQ=

 

앞에 Basic을 붙여줘야한다!

 

중간에 패킷을 가로채서 이 헤더를 Base64로 디코딩 하면 id, password가 그대로 노출되기때문에 HTTPS를 쓰는 것을 권장한다.

 

 

3. JWT ( JSON Web Token)

JWT 는 . 을 구분자로 3가지의 문자열로 되어있습니다. 

aaaaaaa.bbbbbb.cccccc

header

payload

signature 

이 각각 세 파트를 각각 다른 방법으로 인코딩하여 HTTP 헤더에 정보를 담아서 넘겨준다.

 

참고

https://sanghaklee.tistory.com/47

 

 

 

 

4. OAuth 

방식은 다섯가지로 grant type이라고 한다.

요새 가장 많이 쓰는 방법이다.

참고

https://hyeonyeee.tistory.com/48

 

 

5. SAML ( Security Assertion Markup Language)

SSO( Sing Sign On) 이 필요할 때 많이 쓰는 인증방식이다.

즉 한번 로그인하면 다른 사이트나 다른 서버에서도 인증이 되는것이다.

하나의 인증으로 다 통합된다는것이다 

얼마나 편리한가,, 사실 이 안의 개념도 엄청 복잡하다.

따로 포스팅 해도 될정도 

 

 

 

ㅎㅎ간단히 보면 이정도 되겠다..

요새는 OAuth나 SAML을 가장 많이 쓰는거 같다.

그래서 그런지 이 두개를 비교하는 포스팅도 많다.

 

Spring Security는 그러면 이 모든 걸 다 제공한다^^

얼마나 방대한가.. ㅎㅎ;

 

사실 이 인증 방식과 Spring Security의 개념이 좀 혼동 되었었는데

이번에 정리 하고 넘어가서 좋다 ^^77

 

화이팅!

 

안의 포스팅은 차차.. 내용을 더 채워 나가도록 하겠다 

 

 

 

 

 

 

1. 서버에서 mysql 로 접속한다.

 

mysql -u root 

mysql -u root -p // 비밀번호 치고 들어가야 할 때

 

 

2. mysql 스키마 변경

use mysql;

 

 

3. user 테이블 조회

select host , user, password from user;

 

4. 계정 생성

create '계정아이디'@'ip' indentified by '비밀번호';

ex)
create user 'test'@'%' IDENTIFIED BY  'test1!';
create user 'test2'@'127.0.0.1' IDENTIFIED BY  'test1!';

 

생성한 user 삭제

 

delete from user where user='test2';

 

 

5. 권한 설정

grant select , insert , update , delete on  스키마명.테이블명 to '계정 아이디 '@'아이피';

grant all privileges on 스키마명.테이블명 to '계정명'@'호스트명' identified by '계정비밀번호' with grant option;

 

첫번째는 주어진거만 , 로 구분해서 권한을 주면 된다.

두번째는 전체 권한이고 

 

 

6. 권한 조회 

show grants for '계정아이디'@'호스트';

ex)
show grants for 'test'@'%';

 

 

7. 권한 삭제

revoke all on '스키마명'.'테이블명' from '계정명'@'호스트';

 

'DEVELOP > DB' 카테고리의 다른 글

[DB] postgreSql Centos7에 설치 및 설정하기  (0) 2020.08.24
[DB]Isolation Level 알아보기  (0) 2020.07.19
[MariaDB] general log 설정하기  (0) 2020.05.25
DB (mysql) 설정 변경  (0) 2020.03.13
NewSql 이란? All in one DBMS  (0) 2019.12.16

MariaDB에는 다양한 로그가 있다.

 

모든 query log가 나올 수 있는 general log가 있고

 

느린 쿼리를 수집하는 slow로그 

 

에러로그를 수집하는 에러로그

 

그중에서 오늘은 general log에 대해서 알아보도록 하자

 

 


1.  root 권한으로 mysql로 접속

우선 서버에서 root 권한으로 들어가준다.

 

mysql -u root 

mysql -u root -p // 비밀번호 치고 들어가야 할 때

 

그리고 mysql로 들어가줌!

 

 

2. general log에 관한 설정 조회

general log에 관한 설정을 조회 해준다.

 

MariaDB [(none)]> show variables like 'general%';
+------------------+-------------------------+
| Variable_name    | Value                   |
+------------------+-------------------------+
| general_log      | OFF                      |
| general_log_file | general.log |
+------------------+-------------------------+

 

 

3. general log 설정 on

set GLOBAL general_log='ON';
set GLOBAL general_log_file='/data/general.log';

이러면 설정은 끝난다.

그치만 매번 DB를 올리고 내릴때마다 같은 설정을 유지하고 싶으니깐

 

my.cnf 파일을 수정해준다.

 

vi /etc/my.cnf

[mysqld]
general_log = 1
general_log_file=/data/general.log

 

만약, 권한이 없으면 sudo 권한으로 열어준다!

( sudo vi /etc/my.cnf )

 

 

default general_log 테이블은 CSV 엔진을 사용하기 때문에 MyIsam 엔진으로 변경한다.

아래와 같은 에러 발생 시 general_log 를 off 시킨 후 수행해야함!

mysql> alter table mysql.general_log engine=MyIsam;

4. 로그 수집 방법 (FILE / TABLE)

 

로그 수집 방법을 조회 해준다.

MariaDB [(none)]> show variables like 'log_output%';
+---------------+------------+
| Variable_name | Value      |
+---------------+------------+
| log_output    | FILE       |
+---------------+------------+
1 row in set (0.001 sec)

 

그런데 나는 로그에서 매번 user_host 즉, ip가 나왔으면 했다.

 

 

그런데 general-log에서는 FILE 로그에서는 connect 할때는 ip가 나오는데 

그 이후, query에서는 나오지 않았다.

 

그런데 table 에서는 기본적으로 user_host가 있으므로 TABLE로 로그를 수집하기로 하였다.

 

cf) 이를 대체하는 방법으로 slow log의 시간을 조정해주는 방법이 있다. 

왜냐면,, slow 로그는 모든 ip를 수집하기 때문이다.

 

SET GLOBAL long_query_time = 0.01;


MariaDB [(none)]> show variables like 'long%';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 0.100000 |
+-----------------+----------+
1 row in set (0.001 sec)


 

 

 

잠시 삼천포에 빠졌었는데 다시 !

그럼 TABLE 에 로그를 쌓도록 수정하겠다.

 

set global log_output='TABLE';

 

그런데 이러면 slow 로그등 다른 로그들도 영향을 받는다.. 그래서 FILE 도쓰고 TABLE도 쓰겠당!

 

set global log_output='TABLE,FILE';

 

그러면 mysql에 general_log라는 테이블이 기본 지원 되기때문에 해당 테이블을 조회 하면 connect , query, 권한 부여등

모든 것이 나온다!

 

 

 

 

event_time	user_host	thread_id	server_id	command_type	argument
03:03.8	root[root] @ localhost []	24	1	Query	show variables like '%log%'

 

 

'DEVELOP > DB' 카테고리의 다른 글

[DB]Isolation Level 알아보기  (0) 2020.07.19
[mySql] 계정 생성 및 권한 설정  (0) 2020.05.25
DB (mysql) 설정 변경  (0) 2020.03.13
NewSql 이란? All in one DBMS  (0) 2019.12.16
NoSql DB 종류  (0) 2019.12.13

이전에 OAuth 2.0에 대해서 정리하는 글을 올렸었다.

그렇다면 Spring 에서 OAuth를 어떻게 구현할까?

 

그게 바로 Spring Security인데 그것에 대해서 알아보고자한다.

 

OAuth와 Spring Security는 여러번 보았는데

볼때마다 헷갈리고 다시 공부하는 느낌이다

 

부디 이번에 조금이나마 더 정리되길 바라며,,, 포스팅 시작한닷..ㅁ7ㅁ8

 


1. OAuth란?

Open Authorization , Open Authentication ( Open 인증 , Open 인가) 로

자신의 애플리케이션 서버의 데이터를 다른 Third Party 에게 공유나 인증을 처리해줄 수 있는 오픈 표준 프로토콜이다

 

즉,,

내 서버의 어플리케이션에 접근 하려면 인증을 거쳐야 하는데, 

이것의 표준이라고 생각하면 된다 ( 인증 & 인가)

 

이 개념이 궁금하면?

https://hyeonyeee.tistory.com/48

 

OAuth 2.0이란?

Oauth 2.0 는 무엇인가,, 알아보겠다 이전엔 보통 open api를 이용할때 토큰을 받아와서 헤더값이 넣어주는 걸 즉, 토큰값을 받아오는걸 구현한 방식이 OAuth 라고 알고있었다 이것도 맞지만 더 자세히

hyeonyeee.tistory.com

다음 포스팅을 참고하자.

 

 

2. Spring에서 OAuth 2.0?

OAuth가 오픈 표준 프로토콜이면 , 

Spring에서 OAuth를 구현하려면? 

Spring Security를 쓰면된닷,,!

 

 

 

3. Spring Security

이제 어느 부분을 구현해보면 되는지 알아보자.

다행히 Spring에서는 많은 소스를 제공해준다

엄청 복잡하게 공부할 수도있지만 우선, 나는 간단하게,, 이해해보겠다.

 

5가지 Grant Type중 

Resource Owner Password Credentials 방식으로 구현해보자.

 

여기서 크게 구현해야 될것은 세가지다.

 

 

1. AuthenticationProvider (Interface)

인증을 담당할 클래스를 구현

UserDetailServiceImpl에서 받아은 유저의 정보를 인증이 완료되면 Authentication 객체를 리턴해준다.

 

 

2. UserDetailService (Interface)

UserDetailService를 implements해서 custom UserDetailService를 만들어주어야한다.

user의 정보를 DB에서 받아온다.

 

3. Authentication Provider 추가하기 

 - SecurityConfig extends WebSecurityConfigurerAdapter

 

1번에서 만든 내가만든 인증 클래스를 ProviderManager에게 등록해주어야 한다.

 

 

 

 

 

 

 

 

 


 

참고)

HTTP Basic Auth 
가장 기본적이고 단순한 형태의 인증 방식으로 사용자 ID와 PASSWD를 HTTP Header에 Base64 인코딩 형태로 넣어서 인증을 요청한다.
예를 들어 사용자 ID가 terry이고 PASSWD가 hello world일 때, 다음과 같이 HTTP 헤더에 “terry:hello world”라는 문자열을 Base64 인코딩을해서 “Authorization”이라는 이름의 헤더로 서버에 전송하여 인증을 요청한다.
Authorization: Basic VGVycnk6aGVsbG8gd29ybGQ=
중간에 패킷을 가로채서 이 헤더를 Base64로 디코딩하면 사용자 ID와 PASSWD가 그대로 노출되기 때문에 반드시 HTTPS 프로토콜을 사용해야 한다.

 

 

en.wikipedia.org/wiki/Basic_access_authentication

 

 

 


https://jeong-pro.tistory.com/205

 

로그인 과정으로 살펴보는 스프링 시큐리티 아키텍처(Spring Security Architecture)

Spring Security Architecture 학습 목표 스프링 시큐리티를 처음 배우는 사람 또는 적어도 한 번은 적용해본 사람을 기준으로 "가장 기본이자 뼈대인 구조를 이해한다"는 학습 목표가 있다. 수 많은 블��

jeong-pro.tistory.com

 

https://minwan1.github.io/2018/03/11/2018-03-11-Spring-OAuth%EA%B5%AC%ED%98%84/

 

Wan Blog

WanBlog | 개발블로그

minwan1.github.io

 

https://spring.io/guides/topicals/spring-security-architecture

 

Spring Security Architecture

this topical is designed to be read and comprehended in under an hour, it provides broad coverage of a topic that is possibly nuanced or requires deeper understanding than you would get from a getting started guide

spring.io

 

+ Recent posts