올해 결제내역이 있는 회원들의 현재 보유한 잔액, 쿠폰 잔여량을 조회해 달라는 요청이 들어왔다.
조회에필요한 테이블을 찾다보니 무려 6개..!
쿼리는 바로 포기ㅎ
문득 각 회원별로 로그인 할 때 보유 잔액을 api 호출을 사용해 구현이 되어있다는 것이 생각났다.
api 가이드를보니 로그인 user_id를 파라미터로 던지면 끝이었다
이렇게 간단할 수가?!?!
-
첫 시도
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "api url";
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("user_id", "홍길동");
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<(map,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);
구글링을 통해 소스를 찾아봤다.
- header를 셋팅하고
- map에 파라미터로 넣을 key, value 값을 넣고
- HttpEntity에 파라미터와 헤더 정보를 담는다.
- restTemplate의 메소드인 postForObject를 사용해 위에서 설정한 정보를 담아 넘겨준다.
(각각의 함수에 대해서는 따로 정리를 할 예정이다.)
결과는 당연히 실패 ㅎㅎ 처음부터 될리가
Bad Request 400 error
발생
음,, 헤더 문제인가?
-
header 수정
headers.add("Content-Type", MediaType.APPLICATION_JSON.toString());
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
헤더를 바꿔줬다.
실패ㅎ
-
header에 Authorization 추가
웹에서 호출된 header를 보니 Authorization 값이 있었다. 그래서 이것도 추가해봤다.
headers.add("Content-Type", MediaType.APPLICATION_JSON.toString());
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("Authorization", "웹 헤더에 있던 값");
실패ㅎㅎ
- Authorization는 그럼 회원별로 값이 다 다를텐데 이건 아니지 않을까?
- 헤더문제는 아닌 것 같다.
파라미터를 수정해보자.
콘솔 디버그에
{"user_id":[홍길동]} 이런식으로 출력이 되어있었다.
그럼이건가..?
-
갓택오버플로우
스택오버플로우에
String requestJson = "{\"user_id\":\"dlrudtn108\"}";
를 사용해서 map이 아닌 string으로 해결한 것을 보고 바로 시도했더니 성공!!
-
JSON 으로 파라미터를 넘겨줬어야 했다.(당연한건데..)
-
근데 지금보니 map으로 넣더라도
JSONObject feedback = (JSONObject) new JSONParser().parse(result);
이런식으로 출력하면 된다는 글을 보았는데, 내일 해봐야겠다.
-
- 디비에서 대상자를 뽑자. 3천명 정도가 나왔다.
- 3천명을 배열에 넣어서 파라미터에 대입해주면 끝날 것 같은데.. 3천명을 언제 다 넣고있지?
무슨 방법이 좋을까
질문찬스
텍스트 파일에 3천명을 넣어서 파일을 한 줄 씩 읽으면 끝!
크으으
거의 최종 코드
ArrayList<String> userList = new ArrayList<>();
try{
File file = new File("C:\\Sample.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = "";
while((line = bufferedReader.readLine()) != null){
userList.add(line);
}
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException ez){
System.out.println(ez);
}
System.out.println("사이즈 :"+userList.size());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "api URL";
JSONObject jsonObject = new JSONObject();
ArrayList<String> list = new ArrayList<>();
String answer = "";
for(int i=0; i<userList.size(); i++) {
jsonObject.put("user_id", userList.get(i));
HttpEntity<String> entity = new HttpEntity<String>(jsonObject.toString(),headers);
answer = restTemplate.postForObject(url, entity, String.class);
list.add(answer);
}
System.out.println(Arrays.toString(new ArrayList[]{list}));
}catch(Exception e){
e.printStackTrace();
}
기대에 부푼채 실행. 가즈아
근데 1700명 정도 읽더니 갑자기 connection failed
검색해보니 아마도 너무 많은 요청으로 인해 끊겼을 것 같았다.
또 구글링, 구글 없었으면 개발 못함
연결이 끊기면 재 연결시도를 해주는 코드를 찾았다! (마찬가지로 추가 정리 필요)
private static final int HTTP_CLIENT_RETRY_COUNT = 3;
private static final int MAXIMUM_TOTAL_CONNECTION = 10;
private static final int MAXIMUM_CONNECTION_PER_ROUTE = 5;
private static final int CONNECTION_VALIDATE_AFTER_INACTIVITY_MS = 10 * 1000;
HttpClientBuilder clientBuilder = HttpClients.custom();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// Set the maximum number of total open connections.
connectionManager.setMaxTotal(MAXIMUM_TOTAL_CONNECTION);
// Set the maximum number of concurrent connections per route, which is 2 by default.
connectionManager.setDefaultMaxPerRoute(MAXIMUM_CONNECTION_PER_ROUTE);
connectionManager.setValidateAfterInactivity(CONNECTION_VALIDATE_AFTER_INACTIVITY_MS);
clientBuilder.setConnectionManager(connectionManager);
clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(HTTP_CLIENT_RETRY_COUNT, true, new ArrayList<>()) {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
return super.retryRequest(exception, executionCount, context);
}
});
- 이렇게 해서 성공적으로 데이터 추출 완료.
++
하지만, 3천명보다 훨씬 많은 데이터를 호출해야 된다면?
위의 인공호흡 코드로는 역부족일 것이다.
마찬가지로 질문찬스를 통해, 파일을 읽을 때 100명씩 끊어서 읽고, api 호출도 100명씩 끊어서 서버에 부하를 덜 주는 방식을 고려해야 한다는 답변을 받았다.
또한 jvisualvm
로 파일을 읽을 때나, api 호출 부분에서 메모리가 얼마나 치솟는지도 확인해야 한다고 한다.
사용법을 익혀야겠다.
이 부분까지 추가 개발을 해보고 2탄에 올려야겠다.
끝.
'Spring Boot' 카테고리의 다른 글
JPA repository.save is Null (NullPointerException) - feat. @RunWith & @SpringBootTest & @DataJpaTest (2) | 2019.11.13 |
---|---|
스프링부트 Rest API Post 방식 호출하기 - (2) (0) | 2019.10.24 |
마이크로 서비스 구축 - (1) (0) | 2019.09.28 |
마이크로서비스 @PathVariable, @RestController, @EnableEurekaClient, @ HystrixCommand, @EnableCircuitBreaker (1) | 2019.08.31 |
스프링부트 parameterType alias 지정하기 (0) | 2019.05.27 |
댓글