Giter VIP home page Giter VIP logo

freelec-springboot-webservice's Introduction

freelec-springboot-webservice's People

Contributors

zhtmr avatar

Watchers

 avatar

freelec-springboot-webservice's Issues

freelec-springboot-webservice

freelec-springboot-webservice Build Status

  • 스프링 부트
  • JPA
  • JUnit 테스트
  • gradle
  • 소셜 로그인
  • AWS 무중단 배포

Intellij + SpringBoot + Template engine 에서 livereload 하기

이것때문에 travis 빌드 안돼서 주석처리 했음.

주석 2020-02-27 195456

.gitignore 작동 안할때 -> 캐시삭제

git rm -r --cached .
git add .
git commit -m "fixed untracked files"

MockMvc

image

image

@WebMvcTest 와 @SpringBootTest 차이

@SpringBootTest의 경우 일반적인 테스트로 slicing을 전혀 사용하지 않기 때문에 전체 응용 프로그램 컨텍스트를 시작한다. 그렇기 때문에 전체 응용 프로그램을 로드하여 모든 bean을 주입하기 때문에 속도가 느리다.

@WebMvcTest의 경우는 Controller layer를 테스트하고 모의 객체를 사용하기 때문에 나머지 필요한 bean을 직접 세팅해줘야 한다. @WebMvcTest는 WebSecurityConfigurerAdapter, WebMvcConfigurer, @ControllerAdvice, @Controller를 읽음. 즉, @Repository, @Service, @Component는 스캔 대상이 아님.

따라서 @WebMvcTest 는 SecurityConfig를 생성하기 위해 필요한 @Service 인 CustomOAuth2UserService를 읽지 못함.

  1. secure = false 옵션은 2.1부터 지원하지 않음.
  2. 필터

controllers = HelloController.class,
      excludeFilters = {
       @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)})

Travis CI 가 권한부족으로 gradlew을 실행하지 못할때

gradlew 자체에 권한주기

image

.travis.yml 에 실행권한 추가

image

gradle > test 시에 "Test event were not received" 라고 뜰때

wn

File -> Settings ->Build,Execution, Deployment -> Build Tools -> Gradle

image

Travis 빌드 실패...

-> 2020.4.18 현재 다시 해당 오류 발생함. 도저히 원인을 모르겠음
-> appspec.yml 에 오타가 있어서 빌드가 안됐었음.
-> 로컬에서 build 후 커밋푸쉬 했을때는 travis에서 빌드가 됐다가 안됐다가 반복함.
-> 로컬에서 clean > build 하니까 성공.
-> .gitignore 에 build 관련 등록
-> 2020.08.10 인텔리제이에서 clean -> build 시 test 실패 'EntityManagerFactory is closed' 오류 여전히 발생함. (JPA, H2 db 문제같음 https://stackoverflow.com/questions/52480973/h2-in-memory-test-db-closed-despite-db-close-on-exit-false/52481318)
-> JPA, 동시성, 영속성컨텍스트 관련 같음(https://stackoverflow.com/questions/52480973/h2-in-memory-test-db-closed-despite-db-close-on-exit-false/52481318)

image

image

image

  • 현재 aws IAM(Identity and Access Management) 를 통해 Travis CI는 S3 와 CodeDeploy 권한을 부여받은 상태임
  • Travis CI 에서 S3로 build 파일은 전달이 잘 되었음.

2020.4.18 현재 S3에도 빌드파일이 안올라감.. travis에서 JPA 오류 뜨면서 빌드 자체가 안되는중..

image

  • 그러나 Travis CI가 codedeploy 에 배포요청 시 S3에 있는 파일을 가져오지 못함.

image

  • travis 웹사이트에서 Restart build 하게 되면 빌드 실패뜸..
    image

- Travis 에서 멀티 language 하는 방법 예시

 
   project/ - top-level github directory
   project/backend - Python backend
   project/backend/tests - Python tests
   project/android/AppName - Android app
   project/ios/AppName - iOS app


matrix:
  include:
    - language: python
      python: 2.7
      before_script:
        - cd backend/tests
      script:
        - python -m unittest discover

    - language: android
      dist: trusty
      jdk: oraclejdk8
      android:
        components:
          - tools
          - android-25
          - build-tools-25.0.3
      before_script:
        - cd android/AppName
      script:
        - ./gradlew build connectedCheck

    - language: objective-c
      os: osx
      osx_image: xcode8.3
      before_script:
        - cd ios/AppName
      script:
        - xcodebuild -workspace AppName.xcworkspace -scheme AppName
          -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.3' build test

notifications:
  email:
    - [email protected]

메소드 참조, 생성자 참조

람다식


String [] strings = new String [] {
    "6", "5", "4", "3", "2", "1"
};

List list = Arrays.asList(strings);

for(String s : strings)
    System.out.println(s);

위와 같은 코드를 람다식으로 표현 한다면

list.forEach(x -> System.out.println(x));

java 8 부터 stream() 을 이용해 메소드 들을 체이닝(chaining)을 통해 조합해서 사용할 수 있다.
for, if 등을 훨씬 간략하게 사용가능함. 그러나 무분별하게 사용 시 성능 이슈가 있다.

어떻게 가능한가?

먼저 forEach 의 생김세를 보면 Consumer functional interface를 매개변수로 받는 stream 인터페이스의 추상메소드다.
image

Consumer 함수적 인터페이스는 리턴값이 없는 accept() 메소드를 가지고 있다.
Consumer는 단지 매개값을 소비하는 역할만 하며, 소비한다는 말은 사용만하고 리턴값이 없다는 뜻이다.
image
image

사실 위에서 list.forEach(x -> System.out.println(x)); 이렇게 구현한 방법은 list의 요소를 입력받아, 단순히 println메소드에 전달해주는 역할만 한 것이다. 함수형 인터페이스인 Consumer 가 가지고 있는 accept 메소드의 구현체를 직접 전달한 것이다. 이렇게 될 경우 Consumer가 구현해야 되는 accept 메소드가 실행될때 println메소드를 한번더 실행해주는 형태가되어, 메소드의 call stack 이 1depth 깊어진 결과가 된다.

어차피 forEach에 전달되는 매개변수는 Consumer의 accept 메소드로 가게되어 구현을 해야만 하는데, 미리 구현을 해서 전달을 하게되면 두 번 구현을 하게됨. 아래처럼 accept가 구현해야 할 메소드만 전달하면 된다.

list.forEach(System.out::println);

실제로 Consumer 인터페이스의 accept 메소드는 아래처럼 생겼다. 리턴값이 없다.
image

그리고 System.out.println() 의 모양은 아래처럼 생겼다. 마찬가지로 리턴값이 없다.
image

따라서 accept가 구현해야할 메소드는 System.out의 println 이라고 메소드 참조 방식으로 전달하기만 하면된다.

Stream()

image

image

image

image


image

람다 테스트

Nginx

  • 배포하는 동안 애플리케이션이 잠깐 종료되는 문제가 있음.
  • 이때 클라이언트에서 접속 요청이 오게되면 서비스에 접속을 할 수 없음.
  • 기존 Jar를 종료시키고 새로운 Jar를 실행시키기 까지의 잠깐의 틈이 있기 때문.

Nginx proxy

  1. 클라이언트와 서버 사이에 존재하며, 배포시에 클라이언트 요청을 분기 시킴.
  2. 리버스 프록시 서버(Nginx)는 요청을 전달하고, 실제 요청에 대한 처리는 뒷단의 웹 애플리케이션 서버가 처리함.
  3. 서로 다른 profile을 가진 스프링부트(real1, real2)는 각각 다른 port를 수신받음. (8081, 8082)
  4. 먼저 한쪽 port로 수신을 받아서 스프링부트에 연결시켜 서비스함.
  5. 그리고 나중에 새로운 jar가 배포되면 연결되어 있지 않은 스프링 부트를 종료하고 그 profile 에 새 버전의 스프링부트를 시작함.
  6. 새 스프링 부트가 정상적으로 실행됐는지 확인함.
  7. 이상없으면 port 변경해서 새로운 스프링부트를 수신하게 함.
  8. 배포가 될때마다 nginx가 port를 스위치시킴.

Nginx 흐름 정리

EC2 서버를 재시작 할때마다 Nginx도 시작시켜 줘야함
sudo service nginx start

  1. EC2 서버에 Nginx 설치
  2. 앞으로는 Nginx 기본포트(80)로 요청을 받게됨
  3. /etc/nginx/nginx.conf 내에 설정된 proxy_pass 로 요청을 전달하게 됨.
    ( 이후에 switch.sh 에서 "set \$service_url http://127.0.0.1:${IDLE_PORT};" | sudo tee /etc/nginx/conf.d/service-url.inc 로 인해 계속 포트 변경된다.)
  4. 요청을 분기할 ProfileController 만들기
    ( "/profile" 요청 결과를 가지고 포트변경하기 위함)
  5. profile 만들기 (application-real1.properties, application-real2.properties)
  6. appspec.yml 에서 Jar 파일이 복사된 이후 차례로 실행될 스크립트 정의하기
    stop.sh -> start.sh -> health.sh 순으로 실행됨
    (nginx가 연결되어 있지 않은 스프링부트를 종료시키고 그 profile로 배포 후 작동테스트한 다음 switch !)

"/profile" 요청이 오면 어디로 이동 되는가? :
List<String> realProfiles = Arrays.asList("real", "real1", "real2");
String defaultProfile = profiles.isEmpty()? "default" : profiles.get(0);
return profiles.stream().filter(realProfiles::contains).findAny().orElse(defaultProfile);
-> real, real1, real2 중에 하나라도 있으면 반환, 전부 없을 경우 실행중인 첫번째 profile 반환

Nginx 관련 시행착오..

image

배포를 계속해봐도 8081로만 배포가 됨. 다시 배포하면 8081에서 실행중인 애플리케이션 종료하고 다시 8081로 배포됨.

image

/profile 주소로 들어가도 계속 real 만 나옴. real1, real2 이 번갈아가면서 나와야 되는거 아닌가??
-> application.properties에서 spring.profiles.include=oauth 로 바꾸니까 real1, real2 번갈아가면서 나옴.

브라우저에서 보여지는 값은 application.properties 에서 spring.profiles.include=List<String> realProfiles = Arrays.asList("real", "real1", "real2") 중 하나로 되어 있을때는 그것만 보임. (findAny()).

image
-> 현재 활성화된 프로필은 IDLE_PROFILE 이다

실제 EC2에는 step2에서 배포한 real을 제외하면, step3 에는 실행중인 jar가 없었음. 이후 배포할때마다 8081로만 배포됐음.
image

원인

nginx는 real1(8081), real2(8082)만 관리함. real 은 nginx가 관리하지 않는 profile임.
jar가 spring.profiles.include=real로 실행중이였음.

따라서 8080 port로 실행중인 real은 배포와 상관없이 항상 http_code가 200이기 때문에, profile.sh 에서 첫번째 if 문에서 CURRENT_PROFILE = real 이 되고,
두번째 if문에서 real ≠ real1 이므로 IDLE_PROFILE = real1 이 된다.
image

그러니 계속 real1 으로만 배포가 됨..

spring.profiles.include=oauth 로 변경 후(또는 ProfileController 에서 real을 빼거나.), 배포하게되면 real1(8081), real2(8082) 가 번갈아가면서 배포된다.
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.