레이블이 spring-boot인 게시물을 표시합니다. 모든 게시물 표시
레이블이 spring-boot인 게시물을 표시합니다. 모든 게시물 표시

2022-01-03

1/3 sleuth 를 이용하여 msa 통신을 추적하기

 


- msa 서비스는 하나의 서비스가 다른 여러 서비스들을 호출하고. 또 그것이 비동기적으로 다른스레드로 요청되기 때문에 하나의 트랜잭션을 추적하기에 어려움이 있다

- 이것을 도와주는 것이 sleuth 라는 라이브러리

- 하나의 요청 단위를 trace Id로, 스레드별로 id를 두개 

traceId는 하나의 요청단위에 있어서 유니크하며 이것은 서비스간 소통을 할때에도 동일하게 유지된다 (신기하군. AOP 로 구현할수있을것같음 )

위 이미지에서보듯이 스레드가 달라졌다 - feignClient 이용한 비동기요청

그러나 traceId 는 유지된다. 


동일하게 - 호출된쪽의서비스에서도 해당 traceId를 유지하고있는 것을 확인할 수 있다. 

이것을 zipkin서버와 연동하여 시각화 하면 더 좋다고는 하는데!!zipkin자체서버를 또 만들어야한다는 부담은 있다.. sleuth 만 넣어줘도. 좋을듯??

근데 - 결국에는 로그를 계속 심어줘야해서.... -> 이부분 어짜피 AOP로 해야되니까 걍 sleuth 안쓰고 다 AOP직접 구현해서 할수있을것도 같네...

2022-01-01

12/31 rabbitMQ 윈도우 설치

 

1.  https://erlang.org/downloads

다운로드

2. https://rabbitmq.com/install-windows.html#installer

서버 버전 다운로드. 윈도우 인스톨러 이용

3. 윈도우 환경변수 > 시스템 환경변수 >  Path 에 각각 추가




4. ELRANG_HOME 시스템 환경변수 추가




5. 윈도우 커맨드 창 관리자 권한으로 실행 후

rabbitmq-plugins enable rabbitmq_management 

명령어 실행으로 플러그인 설치


6. 서비스 에서 rabbitMQ설치확인


--------------------------

23.1 버전의 erlang은 현재 최신버전의 rabbitMQ와 호환되지않는 문제발생하여
최신버전인 24.2로 다시 다운로드 하였다.
rabbitmq-server로 시작!!


일단 로그인의 경우 guest/guest로 가능하다.



2021-12-30

12/30 super() 호출

 - spring cloud gateway 에서 , 커스텀 필터를 만들때 주의사항

- AbstractGatewayFilterFactory 를 상속하여 apply 메서드를 구현한다

단. 상속하는 부모의 생성자는 제네릭 파라메터로 들어가는 C타입을 부르는 생성자 뿐이다.

그러나 자바에서는 생성자를 명시적으로 작성해주지 않았을때 기본생성자만 만들어주고, 만든 생성자가 있으면 기본생성자를 불러주지 않는다.

- 내가 CustomFilter 를 만들었을때 - 이 부모의 생성자를 불러주지 않아서 오류가 발생했다. 

- 명시적으로 부모의 생성자를 호출하든지 아니면 부모에 기본생성자를 추가해야 함 (당연히 이건 내가 클라이언트로서 사용하는거니까 불가능..) 

현재 AbstractGatewayFilterFactory의 기본생성자또한 자기 부모의 super를 호출하고 있음. 여기에 넘겨줄 C타입의 class 가 필요. 



2021-11-23

1123 rabbitmq 간단 실습

 1 rabbitmq 다운로드

2 토픽 & 큐를 생성한다. 어드민 페이지에서 간단하게 생성할 수 있음

타입에 주의한다 - direct , topic.

direct는 특정 한개의 라우팅경로로만 메시지를 보내고

topic은 여러개의 라우팅 키 (정규식 사용하여 sample.* 이런식으로 ) 에 메시지 보낸다. 

3 exchange -> queue를 바인딩 하여 해당 큐에 바인딩된 리스너가 메시지를 받게 된다. 

4 listner 를 생성하고

5 publisher 를 생성한다





exchange 를 통해 들어가서 queue 로 나오는 구조
https://oingdaddy.tistory.com/166 <<< 이 글의 도움을 많이 받았다!!
exchange 의 타입에는 TopicExchange 뿐만 아니라. DirectExchange와 FanoutExchange도 있다










rest controller를 하나 생성하고. 메시지를 보낸다--




리스너가 메시지를 받은것을 확인할 수 있다. 


rabbit-mq 어드민 페이지에서도 두개 커넥션 (publisher, lisener ) 이 잘 붙은 것을 확인가능하다. 

2021-11-07

1107 JUnit 테스트시의 의문점 해결

 JUnit으로 스레드풀테스트를 돌렸을때. join()을 걸어주지않았더니 바로 테스트가 종료되는 점 이 이상하다고 생각했다.

메인스레드가 종료되어도 다른작업스레드가 남아있으면 JVM이 종료되지 않는것이 보통아닌가? 그런데 왜 메인스레드가 이걸 기다려줘야 하지? 하고 의문이 들었다.

->실험1) 스프링이 만들어주는 생명주기와 관련이있다?

이를테면스프링빈에 의존하고있어서?? HelloService의 생명주기와 관련한것인가?

하지만 그렇다면 스레드 자체가 종료되는게 아니고 에러가 떴을거다. 

applicationRunner클래스를 이용하여 즉시실행으로 확인해본결과 역시 스프링 빈 문제는 아니었다.
join()메소드를 걸지 않아도 메소드는 잘 동작했고 예상했던 바와 같이 동시성문제도 발생하는 것을 확인할 수 있었다.


-> 실험2) JUnit프레임워크의 생명주기와 관련이있다?


마찬가지로 일반 main메소드로 돌렸을때도 join()걸지않아도 예상했던대로 출력되었다.


메인 스택이 종료되어도 남은 스레드가 있기때문에 jvm이 종료되지않고 출력되고있음을 확인할수있다.

이로서 JUnit의 생명주기와 join()메소드가 관련있음을 알게되었다!!

아마 JUnit은 테스트종료후에도 남은 스레드로 인해 메모리 누수가 생기는 것을 방지하기 위해 하위스레드들을 자동으로 데몬으로 셋팅하는.. 그런 작업이 있지않나 싶다.

2021-10-30

1030 싱글톤 스코프 테스트!

 빈을 가져오는 방법

1. ApplicationContext에서 직접 getBean하기 -> 로우레벨의 기술(나는 스프링을 사용중이다!~) 라는 것을 들켜버리므로 좋지 않다. 

2. Factory클래스를 만들기

- ObjectFactoryCreatingFactoryBean을 @Bean으로 올린다.

인터페이스가 있고 - 이 인터페이스를 구현한 ObjectFactoryCreatingFactoryBean이 있음. 해당 클래스의 메소드 setTargetName 이름을 넣어주고 빈으로 등록해서 올린다. 사용할때는 인터페이스 타입으로 @Autowired받으면 됨. 다만 스프링이 정의해둔 인터페이스를 가져다 쓴다는 것이 찜찜할 수 있다. 

어쨌든 그래도 로우레벨을( 어플리케이션콘텍스트) 한번감싸서 팩토리 빈으로 빈을 생성해 주기때문에- 1번보다는 낫다. 빈이 어떤식으로 생성되는지는 몰라도 되기 땜에.

3. Provider<T> 인터페이스 이용하기

해당 인터페이스를 구현한 클래스를 @Bean으로 올리면 됨. Provider<돌려줄 빈타입> 으로 @Autowired받아서사용.


- 재미있었던점!!




첨에 @Configuration으로 안올리고 일반 @Component로 한뒤에 new SingletonScopeBean으로 되돌려주도록 메소드 만들었더니 해당 빈또한 @Component로 돌렸음에도 불구하고 새로운 빈이 또 생겨나서 싱글톤이 아니게되었다!!

그래서 @Autowired로 바꾼뒤에 돌려주게 만들었더니 이제 싱글톤빈으로 돌려줌. 그래서 @보통은 @Configuration으로 붙인담에 그런식으루 쓰는구나 싶었다.. 헷갈리니까?

2021-10-25

1025 톰캣, 스레드, 스프링, 커넥션객체

[스프링]

- 메타 정보 파일 + 클래스 => 스프링 어플리케이션

1. 메타정보파일 : xml, 자바 config , db데이터 등등 다양. resourceLoader만 필요적절하게 있다면뭐든 형식오케이

- 스프링 빈 등록방법

1. 형식 : xml또는 java config

2. 방법 : 

1) 직접 bean id일일이 등록

2) component scan해서 베이스 패키지 등록 - 아래에 있는 애들 다 등록하기 . 빈스캐너 등록

3) 스테레오 타입 어노테이션 이용 (위에랑 합쳐서,할수있음)

4) 빈스캐너 : 직접 등록하기 or 해당 빈스캐너를 이미 디폴트로 들고있는 applicationcontext사용하기(우리는 보통 이쪾을 사용하니까 걍 스테레오 타입어노테이션 막붙여버리고 ㅇㅇ 아무렇지않게 쓰고있었다)


3. 반드시 필요한것 : id , class 보통 어노테이션 방식쓰면 - id는 class명에서 앞에만 소문자로 따서 ㅇㅇ만들어짐 

4. 빈 스코프설정  : 디폴트 싱글톤. 특별한 경우 prototype으로 계속 생성도 가능

5. @configuration : 이거 이용해서 여러빈을 한번에 등록. 얘 자체도 하나의 빈이기때문에 싱글톤. 설령 얘의 메소드를 직접부른다고 하더라도1!! 반환된 객체는 싱글톤이다 (오묘~~~@!)

6. 같은 타입의빈이 여러개 있을떄 ? -.> @qualified같이 이름으로 구분하거나 / 아니면 배열로 주고 파라메터 받아서 적절하게 반환한다는 전략도 있음. HashMap으로 해서 이름/ 객체로 받을수도 있음!!! 개쩐당


- DI하기

1. 전략 : setter / 생성자 / 필드 / 일반 메소드 주입

2 . 만약에 테스트 환경같이 갈아끼울필요있으면 setter주입고려해보고.

3. 생성자주입쓰면 한번에 할수있으니까 편하다-

-스테레오타입어노테이션 

: 해당 어노테이션으로 빈등록하면 - aop쓸때 걸러낸다던지. 좀더 명확하게 클래스에 이런애입니다!! 라고 정보를 모아서 볼수있으니 편함. 이용하자. @Repository, @Controller, @Service 그외에 애매한 애들은 @Component라고 등록. 

- @Configuration에 등록하는 애들 : 개발자가 작성한 클래스가 아니라 기술적으로 필요한 애들등록할때도 사용@Bean으로. 


- 다양한 종류의 ApplicationContext가 있다. 여기는 빈들이 생성(초기화) 되고 . 한번 호출해준다!! 그러면- 이제 타고타고 유저요청에따라 main메소드가 실행되고. 







2021-10-24

1024 스프링, 스레드, 톰캣에 대한 의문들

 1. 스프링은 빈 객체를 싱글톤전략으로 (기본적으로는) 사용한다.

2. 왜냐? 유저 요청이 들어올때마다 컨트롤러 서비스 각각 개별적으로 띄우면- 금방 메모리가 바닥날것이기 때문에 같은 빈을 공유하는 것이 효율적이다. 

3. 여기서 의문!! 그럼 아니 어떻게 하나의 컨트롤러가 유저요청을 다받아내??

4. 톰캣은 기본적으로 max스레드 수가 200으로 되어있으니까 최대 동시에 200요청을 하나의 컨트롤러가 받아낸다고 ?!! 하는 의문이 들어서 찾아보았다---

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

<< 여기 글을 보고 의문을 해결할수있었다!!!

5. 결론 - 객체 주소(heap영역_)는 공유하지만, 메소드(stack영역)는 개개별 스레드마다 생성되므로- 동기화 우려가 없다. 그래서 빈 객체는 무상태로 유지해야하는 것이 중요하다! 그래야 동기화 이슈가 없다-. 그리고 메소드는stack별로 유저마다 다른 값을 가질것이므로 - 컨트롤러라는 객체를 '공유'한다는 것이 가능하다.

6. '공유'라는 개념을 헷갈리고 있었던것이당.

7. 커넥션풀과 톰캣스레드 수는다르다!!

-> 톰캣스레드별로 커넥션을 물고간다? 뭐 그런 식의 표현을 읽은적이 있다... 근데 커넥션 수 100개만 넘어가도 뻑 죽던데 왜지... 하는 의문이 있었는데그것도 해결!!

스레드를 공유하는게 아니라 객체의 수를 공유한다는 것이었땅.

2021-10-12

1012 FactoryBean 만들기

 

스프링이 bean을 등록하는 방식

1. 자바 리플렉션

2. FactoryBean이용.

직접 factorybean클래스를 상속하여 나만의 helloFactoryBean을 만든다. 

hello 오브젝트를 interface만든후 impl클래스 하나 만들고. @Autowired로 받아둔다.

hello factory bean은, 일종의 프록시로 작동한다. hello의 메소드에 invocationHandler를 붙여서- 부가기능을 첨가해줄것이다. 



재미있는 점은. helloFactoryBean을 bean으로 가져왔을때 던져주는 클래스가 helloFactorybean이 아니라, hello클래스라는 점이다. 

확장한다면 hello뿐만이아니라- 다양한 Object클래스를 받을 수 있을 것이다. 

해당 target 클래스의 toString이 불리는 것을 확인할 수있다.

2021-10-11

1011 implements 하는 타입의 빈이 여러개 등록된경우

 

스프링은 싱글톤으로 빈등록을 한다.그래서 여러개 implements하는 빈이 있으면 어느쪽을 주어야할지몰라서 에러가 발생하곤 한다. 해결방법은

1 ) @qualified사용하거나

2) 이름을 지정해준다

스프링은 일단 타입으로 찾고 -> 그다음에 이름으로 찾기때문에.. 특정 이름으로 인스턴스변수를 넣어주면 그 객체로 @Autowired해준다. 



Tx의 메소드가 호출된 것을 확인할 수 있다. 

이런식으로 한겹 감싸서 - (프록시 패턴. 혹은 데코레이터 패턴) 부가기능을 제공해줄 수 있다. 

1011 spring boot test


 @RunWith 

@SpringBootTest

로 했을 때의 차이??

이상하게 - @Runwith(SpringBoot4TestRunner.class)로 돌리면 ApplicationContext가 찾아지는데

단순히 @SpringbootTest로 붙이면 못찾더라. 왜지?

테스트 쉽게하라고 만들어준 어노테이션이 아니었던 건가?!!



-----

확인결과

 @Runwith(SpringBoot4TestRunner.class)로 돌리면, 단위테스트. 정말로 test에 필요한 최소한의 클래스만 올려줌. 만약에 @Component등.. bean으로 등록한 애들 가져오고 싶은거면

1. @ContextConfiguration으로 지정해서 - 테스트하고 싶은 클래스들만 가져온다

2.

@BootstrapWith(SpringBootTestContextBootstrapper.class)


이용해서 . 빈들 다 띄울수도 있다.

특히 저 둘 어노테이션들은 @SpringBootTest어노테이션안에 들어가 있음. 그래서 @SpringBootTest를 붙이면 모든 클래스를 올려주는 통합테스트가 된다. 

스프링부트가 만들어주는 각종 AutoConfig하는 클래스들과 내가 만든 모든 빈들 전부 등록해준다. 안으로 들어가보면.. mvc (web일경우.) 부터시작해서 각종 autoconfigure클래스들이 들어오는 걸 확인할 수 있다.


3. @ExtendWith 어노테이션 : JUnit4 -> 5로 확장해줌. 

2021-08-24

0824 자바 8 메서드 참조

 

자바 8의 메서드참조기능에는

클래스::메서드 명

이렇게만 알고있었는데!

참조변수::메서드 명

으로도 사용할 수 있다.

해당 참조변수가 사용할 수 있는 메서드라면 얼마든지 가능함!

2021-08-23

0823 inner 클래스의 접근 범위

 


이후 @PostConstructor 에서 init메소드를 부를때, default로 설정했더니 메소드를 부를 수 없었던 에러가 있었다!!

public으로 메소드를 바꾼 후 해결되었는데, 그이유는

애초에 지금 inner클래스로 default로 잡았기 때문에 - default 안의 default여서 바깥에서 해당 메소드를 부를 수 없었던 것이다.

중첩 클래스의 경우 접근 범위가 더 좁아지는 것에 유의해야 한다!! ㅎㅎ


2021-08-22

0822 api조회 컨트롤러, 서비스, 레포지토리 생성하기

 더미데이터 넣기


profile.active설정을 통하여 test일때에만 해당 프로파일이 작동되도록 설정. application을 로딩할 때 해당 설정을 확인할 수 있다.



멤버 init이라는 클래스를 작성하여 더미데이터를 넣어줄 것이다. profile이 local일때에만 이 클래스는 로딩된다. 

@PostConstruct를 통해서, 클래스의 로딩 -> 의존성주입 이후에 곧바로!! 실행될 메서드를 넣어주었다.


엔티티매니저를 주입받고. (inner 클래스를 작성할때에는, static으로 한다. 그렇게 해서 외부클래스와의 의존성을 낮춘다.) 

init메서드를 작성하여 더미데이터를 넣는다.

이때 자바8문법을 활용해본다!!(재밌기 땜이다 ㅎㅎ)

나이는 랜덤으로 1~50까지 들어가며, 

홀짝으로 팀을 분배하였다.


쓰다가 한가지 오류 난 것 - 신기하게(?) 저 init()메서드를 내가 public을 안붙이고 실행했더니 - 실행이 안되었다. 처음에는 entitymanager가 주입이 안된건가?? 했는데, 아무래도 init을 부르는 쪽 ( @PostConstructor) 에서 못찾는 거거나. 아니면 - 

엔티티매니저와 public메서드가 관련이있나??

java문법을 더 공부해야 겠다!!

0822 dto로 직접 조회하기

 1. jpql문법 : 조회해서 가져오고 싶은 dto패키지 명을 다 써줘야 되기 때문에 보기에 더러워(?)짐. 

2. querydsl문법: 1) bean으로 가져오기 2)constructor로 가져오기 3) field로 가져오기

가 있다.

1)과 2)의 경우에는 getter setter 혹은 생성자에 유의해서 만들어줘야 한다. 그래야 리플랙션으로 샥 넣어준다. 

3. alias로 가져오고 싶은 경우 - ExpressionUtils를 이용할 수 있다. 


JPAExpressions를 사용해서 서브쿼리 날리고, 해당 서브쿼리를 age라는 alias로 조회.

그냥 alias만 주고 싶으면 간단하게 as()만 쓰면댐.

2021-08-21

0821 서브쿼리 날리기

 

1. 방법

1) 만약 같은 테이블에서 서브쿼리를 날릴경우 - alias를 다르게 주어야 하므로, 새로운 Q도메인 객체를 생성한다. 

2) JPAExpressions를 이용하여 서브쿼리를 날린다. fetch수식어만 제외하고 QueryFactory에서 만드는 문법이랑 똑같음.

3) where 혹은 in조건을 이용하여 서브쿼리를 날릴 수 있다.

2 . 서브쿼리의 종류 : select , from, where

- 그러나 Querydsl에서는 from절에서의 서브쿼리를 지원하지 않는다.

Querydsl은 기본적으로 JPQL를 사용하기 쉽게 만들어주는 녀석인데, JPQL이 from절 서브쿼리를 지원하지 않기 때문이다. JPQL에서 안되는 것은 Querydsl에서도 안된다. ㅜㅜ

이경우에는hibernate구현체를 직접이용하거나, 조인으로 풀어내거나, 그것도 안되면 네이티브SQL을 날리는 수밖에 없다...


3. assertThat의 다양한 사용법

as("~~)를 이용해서 해당 assertThat에 특정 이름을 지정할 수 있다.

extractind("필드변수명").contains()혹은 containsExactly()를 사용하여 해당 값이 포함되어있는지를 좀더 상세하게 검증할 수 있다.


4. EntityManagerFactory에서 제공하는 LoadedUnitUtils를 이용하여, 해당 필드값이 loaded되었는지 아닌지를 true false로 검증할 수 있다. 

0821 join on조건


 leftjoin한 후에 on으로 조건추가할 수 있음. 



일반 join한 후에 on으로 조건 추가하거나. where로 추가할 수 있음. 결과는 동일함.

좀더 익숙한 where절을 사용하도록 하자.

0821 inner join, outer join

1.  entityManager : 스프링에서 ,멀티스레드로 돌려도 동시성 문제 없도록 바인딩 처리해준다고 함.. 우와아아아.

2. 조인에는 크게 두가지가 있다. inner join, outer join.

inner join을 디폴트로 되어있으며 보통 왼쪽 기준으로 left inner join을 한다.

이것을 querydsl 혹은 jpql문법으로 바꾸면 ->

join (= inner join) , leftJoin => left outer join이 된다.


팀과 멤버를 일반 조인으로 했을 때는 team이 null인 member는 조회되지 않는다. 교집합만 추출된다.


왼쪽 (멤버)기준 leftJoin을 한 경우 left outer join으로 전환되어 SQL이 실행되며, 팀이 null인 멤버도 전부 조회된다. 


0821 fetch type=Lazy인 경우

 


Lazy로 설정하는 경우, getTeam을 부를때 한번 더 select를 때린다.


select member한 후에 -> getTeam하니까 (어!! 나 select안해왔는뎅 !!)하면서 다시 select때리고..

이경우에는 4명의 회원이 각각 2개의 팀에 소속되어있기 떄문에

select member -> select team -> select Team

총 3번의 쿼리가 날라가는!! 이것이 바로 N+1문제이다!!!

(사실은 1+N이라고 말하는게 맞는 것 같지만)


따라서 fetch join을 써야한다!

0821 querydsl학습

 javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call


entitymanager를직접사용할때는 transaction에 주의한다. 꼭 감싸 주어야 함




0328 fdisk, mkfs, mount, fstab

 1. 하드디스크를 붙인다. 2. fdisk -l로 하드디스크를 확인한다.  - interactiive한 커맨드모드 사용하여 (m) 붙인 하드디스크의 파티셔닝을 한다.  - 마지막에 w를 해야 실제로 반영이 된다.  3. mkfs를 하여 어떤 파일시스...