Jini's Blog

Ing...

  • Home
  • Business
    • Internet
    • Market
    • Stock
  • Parent Category
    • Child Category 1
      • Sub Child Category 1
      • Sub Child Category 2
      • Sub Child Category 3
    • Child Category 2
    • Child Category 3
    • Child Category 4
  • Featured
  • Health
    • Childcare
    • Doctors
  • Home
  • Business
    • Internet
    • Market
    • Stock
  • Downloads
    • Dvd
    • Games
    • Software
      • Office
  • Parent Category
    • Child Category 1
      • Sub Child Category 1
      • Sub Child Category 2
      • Sub Child Category 3
    • Child Category 2
    • Child Category 3
    • Child Category 4
  • Featured
  • Health
    • Childcare
    • Doctors
  • Uncategorized

WebFlux Error Handling

 Jini     오후 10:07     error, exception, Webflux     No comments   

WebFlux Error Handling

  • doOnError : 예외 발생시 특정행위를 수행한다.
  • onErrorReturn : 예외 발생시 특정 값을 return 한다.
  • onErrorResume : 예외 발생시 다른 Flux형태로 return 한다.
  • onErrorContinue : 예외 발생시 멈추지 않고 해당 영역만 skip 한다(별도 처리 하지 않는 이상 정상 응답을 return한다).
  • onErrorMap : 예외 발생시 다른 Exception으로 변환한다.

doOnError

Source:
@RequestMapping("/error/test")
public Flux<Integer> getNum() {
  return Flux.range(0, 5)
      .map(x -> {
        if (x == 3) {
          throw new IllegalArgumentException("invalid num");
        }
        return x;
      })
      .doOnError(x -> log.error("num generate error"))
      .log();
}
Result:

 INFO 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | onSubscribe([Fuseable] FluxPeekFuseable.PeekFuseableSubscriber)
 INFO 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | request(unbounded)
 INFO 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | onNext(0)
 INFO 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | onNext(1)
 INFO 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | onNext(2)
ERROR 5276 --- [ctor-http-nio-2] c.e.demo.r4.controller.R4Controller      : num generate error
ERROR 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : | onError(java.lang.IllegalArgumentException: invalid num)
ERROR 5276 --- [ctor-http-nio-2] reactor.Flux.PeekFuseable.1              : 

onErrorReturn

Source:

@RequestMapping("/error/test")
public Flux<Integer> getNum() {
  return Flux.range(0, 5)
      .map(x -> {
        if (x == 3) {
          throw new IllegalArgumentException("invalid num");
        }
        return x;
      })
      .onErrorReturn(99)
      .log();
}
Result:

 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onSubscribe(FluxOnErrorResume.ResumeSubscriber)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : request(unbounded)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(0)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(1)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(2)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(99)
 INFO 12068 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onComplete()

onErrorResume

Source:

@RequestMapping("/error/test")
public Flux<Integer> getNum() {
  return Flux.range(0, 5)
      .map(x -> {
        if (x == 3) {
          throw new IllegalArgumentException("invalid num");
        }
        return x;
      })
      .onErrorResume(exec -> {
        log.error("num generate error");
        return Mono.just(99); //어떤 값으로 return을 할지 상황에 맞게 지정한다.
      })
      .log();
}
Result:

 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onSubscribe(FluxOnErrorResume.ResumeSubscriber)
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : request(unbounded)
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(0)
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(1)
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(2)
ERROR 8444 --- [ctor-http-nio-2] c.e.demo.r4.controller.R4Controller      : num generate error
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(99)
 INFO 8444 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onComplete()

OnErrorContinue

Source:

@RequestMapping("/error/test")
public Flux<Integer> getNum() {
  return Flux.range(0, 5)
      .map(x -> {
        if (x == 3) {
          throw new IllegalArgumentException("invalid num");
        }
        return x;
      })
      .onErrorContinue((exec, num) ->
          log.error("num generate error, number is : {}, error msg : {}", num, exec.getMessage()))
      .log();
}
Result:

 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onSubscribe([Fuseable] FluxContextStart.ContextStartSubscriber)
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | request(unbounded)
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onNext(0)
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onNext(1)
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onNext(2)
ERROR 9728 --- [ctor-http-nio-2] c.e.demo.r4.controller.R4Controller      : num generate error, number is : 3, error msg : invalid num
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onNext(4)
 INFO 9728 --- [ctor-http-nio-2] reactor.Flux.ContextStart.1              : | onComplete()

onErrorMap

Source:

@RequestMapping("/error/test")
public Flux<Integer> getNum() {
  return Flux.range(0, 5)
      .map(x -> {
        if (x == 3) {
          throw new IllegalArgumentException("invalid num");
        }
        return x;
      })
      .onErrorMap(exec -> {
        log.error("num generate error, error msg : {}", exec.getMessage());
        throw new RuntimeException("change error type");
      })
      .log();
}
Result:

 INFO 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onSubscribe(FluxOnErrorResume.ResumeSubscriber)
 INFO 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : request(unbounded)
 INFO 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(0)
 INFO 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(1)
 INFO 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onNext(2)
ERROR 14204 --- [ctor-http-nio-2] c.e.demo.r4.controller.R4Controller      : num generate error, error msg : invalid num
ERROR 14204 --- [ctor-http-nio-2] reactor.Flux.OnErrorResume.1             : onError(java.lang.RuntimeException: change error type)

[참고링크]
[Webflux Tip] 3. Webflux Error 처리! . (n.d.). https://akageun.github.io/2019/07/26/spring-webflux-tip-3.html.
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

MongoDB Array Query(With MongoTemplate)

 Jini     오후 11:08     mongodb, mongotemplate     No comments   

Mongo Collection 구조

컬렉션명 : bookstore
{
  "_id": "1234567890",
  "books": [
    {
      "bookId": "1",
      "storeList": ["용산", "구로", "신도림A", "신도림B"]
    },
    {
      "bookId": "2",
      "storeList": ["서울역", "영등포A"]
    },
    {
      "bookId": "3",
      "bookNm": "재건축",
      "storeList": ["강남", "개포동"]
    }    
  ]
}

1. books element 추가

Monogo Query:

db.getCollection('bookstore').update(
  { _id: "1234567890" },
  { $push: { books: { bookId: "4", storeList: [ "신사", "대학로", "신촌" ] } } }
)
MongoTemplate:

var query = Query.query(Criteria.where("_id").is("1234567890"));
var update = new Update();
var book = new Book();
book.setBookId("4")
book.setStoreList(Arrays.asList("신사", "대학로", "신촌"));
update.push("books", book);

mongoTemplate.updateFirst(query, update, "bookstore");

2. books element 삭제

Monogo Query:

db.getCollection('bookstore').update(
  { _id: "1234567890" },
  { $pull: { books: { bookId: "4" } } }
)
MongoTemplate:

var query = Query.query(Criteria.where("_id").is("1234567890"));
var pullQuery = new Query();
pullQuery.addCriteria(Criteria.where("bookId").is("4"));
var update = new Update();
update.pull("books", pullQuery);

mongoTemplate.updateFirst(query, update, "bookstore");

3. storeList의 element 추가 - 값이 없는 경우에만

Monogo Query:

db.getCollection('bookstore').update(
  { _id: "1234567890", books: { $elemMatch: { bookId: "3" } } },
  { $addToSet: { "books.$.storeList": "신사동" } }
)
MongoTemplate:

var query = new Query();
var criteria = Criteria.where("_id").is("1234567890")
                  .and("books").elemMatch(Criteria.where("bookId").is("3"));
query.addCriteria(criteria);
var update = new Update();
update.addToSet("books.$.storeList", "신사동");

mongoTemplate.updateFirst(query, update, "bookstore");

4. storeList의 element 삭제

Monogo Query:

db.getCollection('bookstore').update(
  { _id: "1234567890", books: { $elemMatch: { bookId: "3" } } },
  { $pull: { "books.$.storeList": "신사동" } }
)
MongoTemplate:

var query = new Query();
var criteria = Criteria.where("_id").is("1234567890")
                  .and("books").elemMatch(Criteria.where("bookId").is("3"));
query.addCriteria(criteria);
var update = new Update();
update.pull("books.$.storeList", "신사동");

mongoTemplate.updateFirst(query, update, "bookstore");

5. storeList의 element 변경

Monogo Query:

db.getCollection('bookstore').updateOne(
    {_id: "1234567890", books: {$elemMatch:{bookId: "3"}}},
    {$set: {"books.$.bookNm": "재개발"}}
)
MongoTemplate:

var query = new Query();
var criteria = Criteria.where("_id").is("1234567890")
                  .and("books").elemMatch(Criteria.where("bookId").is("3"));
query.addCriteria(criteria);
var update = new Update();
update.set("books.$.bookNm", "재개발");

mongoTemplate.updateFirst(query, update, "bookstore");
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

Kafka session.timeout.ms와 max.poll.interval.ms의 차이

 Jini     오후 10:52     kafka     No comments   

session.timeout.ms

컨슈머가 GroupCoordinator에게 해당시간내에 하트비트를 전송하지 않으면 리밸런싱이 일어난다. 컨슈머가 죽었으나 연결이 정상적으로 끊어지지 않는 상황이 발생하면 해당 값에 의해서 인지가 가능하다.
group.min.session.timeout.ms와 group.max.session.timeout.ms 범위 값만 설정가능
default : 10000(10초)

max.poll.interval.ms

다음 poll까지 대기하는 시간. 값이 300000ms인데 poll 내부로직이 300000ms가 넘어가는 경우 리밸런싱이 일어난다.
default : 300000(5분)

아래 코드 참고

@KafkaListener(topics = "xx", groupId = "yy")
public void kafkaListen(String message) throws InterruptedException {
    for (int x = 0; x < 10_000; x++) {
        Thread.sleep(15_000);
    }
}
컨슈머가 GroupCoordinator에게 하트비트는 전송하지만 실제로 아무일도 하지 않는 경우 컨슈머에 문제가 있는 것으로 판단하고 해당 파티션을 제외처리한다.

  • 카프카 0.10.1 버전부터 폴링 간에도 하트비트를 전송할 수 있도록 별도의 하트비트 스레드가 추가되었다고 알고 있음
  • 그래서 poll 내부로직이 오래 걸리더라도 하트비트는 계속 보내기 때문에 리밸런싱이 당연히 발생하지 않을 것으로 예상
  • 하지만 poll 내부로직이 오래 걸리자 리밸런싱이 발생함
  • 의아하게 생각하고 session.timeout.ms를 늘려봤지만 동일한 문제가 발생함
  • 원인을 찾다보니 max.poll.interval.ms 시간을 초과했기 때문이였음
  • poll 내부로직이 오래 걸리면 max.poll.interval.ms 시간을 늘리자
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
최근 게시물 이전 게시물 홈

Popular Posts

  • 구글 Blog + Markdown(StackEdit)
    구글 Blog + Markdown(StackEdit) StackEdit 구글 블로그는 글에 스타일을 적용하기 힘들다. 쉽게 스타일을 적용하기 위해 Markdown 문법 적용을 고려함. 방법을 찾던 중 Sta...
  • Design Patterns
    01. Iterator Pattern 왜 for문을 사용하지 않고 Iterator를 구현할까? 기존 구문 변경없이 loop 순환이 가능함. 즉 특정 구현에 의존하지 않을 수 있게 디자인이 가능함. 02. Adapter Pat...
  • 자신의 목표를 설정하는 방법
    1. 목표세우기 : 목표를 세울때는 가능한한 구체적이어야 한다. 또한 평가할 수 있고 실현 가능성이 있는 목표를 정한다. 장기 목표와 단기 목표로 나누고 데드라인을 분명히 하는 것이 좋다. 2. 우선순위 정하기 : 자신의 생활에서 중요한 순서대...
  • Redmine Text Format
    1. 글자색상 변경 %{color:red}dev% 2. 음영색상 변경 %{background:lightgreen} lightgreen% 3. 문단 넘버링(띄어쓰기 주의) # 큰 제목 ## 큰제목의 하위 제목 # 두번째 큰 제목 # ...

Recent Posts

Recent Posts Widget

Blog Archive

  • ►  2023 (4)
    • ►  3월 (1)
    • ►  2월 (1)
    • ►  1월 (2)
  • ►  2022 (1)
    • ►  2월 (1)
  • ▼  2020 (8)
    • ►  7월 (1)
    • ▼  4월 (3)
      • WebFlux Error Handling
      • MongoDB Array Query(With MongoTemplate)
      • Kafka session.timeout.ms와 max.poll.interval.ms의 차이
    • ►  3월 (4)
  • ►  2018 (1)
    • ►  7월 (1)
  • ►  2015 (1)
    • ►  5월 (1)
  • ►  2014 (5)
    • ►  8월 (1)
    • ►  7월 (1)
    • ►  6월 (1)
    • ►  5월 (1)
    • ►  1월 (1)
  • ►  2013 (10)
    • ►  12월 (1)
    • ►  11월 (1)
    • ►  9월 (2)
    • ►  8월 (3)
    • ►  7월 (3)
  • ►  2012 (1)
    • ►  3월 (1)

Categories

  • 객체지향 (1)
  • 도서요약 (1)
  • 문법에서 문장까지 (2)
  • 일상 (1)
  • 자기계발 (1)
  • 책 (1)
  • 키보드 (1)
  • 키크론 (1)
  • blogspot (2)
  • error (1)
  • exception (1)
  • GIT (1)
  • JAVA (6)
  • JUNIT (1)
  • K8 PRO RGB (1)
  • kafka (1)
  • markdown (1)
  • mongodb (2)
  • mongotemplate (1)
  • optional (1)
  • Oracle (4)
  • Redmine (1)
  • spring (1)
  • stackedit (1)
  • troubleshooting (1)
  • Visual Studio (1)
  • Webflux (1)

Unordered List

Pages

  • 홈

Text Widget

Categories

Tags

Facebook

  • Home
  • Features
  • _Multi DropDown
  • __DropDown 1
  • __DropDown 2
  • __DropDown 3
  • _ShortCodes
  • _SiteMap
  • _Error Page
  • Documentation
  • Video Documentation
  • Download This Template

Footer Menu Widget

  • Home
  • About
  • Contact Us

Social Plugin

JINI. Powered by Blogger.

Copyright © Jini's Blog | Powered by Blogger
Design by Hardeep Asrani | Blogger Theme by NewBloggerThemes.com | Distributed By Gooyaabi Templates