Spring Boot MSA 적용기- 2탄
TL;DR
안녕하세요, 벌써 2022년 새해네요 🙆♂️ 다들 새해 복 많이 받으세요 🙇
이번 포스팅은 이전과 이어서 MSA 관련 포스팅을 주제로 가겠습니다 😃
Zuul Filtering
-
Zuul Gateway를 통한 요청 처리 시 미인증 요청 혹은 각종 이슈 상황 발생 시 우선 대응을 도와주는 기능
-
Zuul Filter Type
- Pre Filter
- 서비스 처리 전 실행되는 필터 (Security, 인증 처리 등)
- Post Filter
- 서비스 처리 이후 실행되는 필터 (API 처리 통계 처리 등)
- Route Filter
- 각 서비스 컴포넌트 내 라우팅 제어를 위한 필터 (Ribbon, 동적 라우팅 관리)
- Error Filter
- 필터 영역 내 발생되는 이슈 상황 처리 실행을 위한 필터
- Pre Filter
Filter 구현
- ZuulFilter를 상속받는 각 필터 처리 커스텀 클래스를 구현
- 각 커스텀 필터 클래스 내 처리 로직 작성
[PreFilter.java]
public class PreFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(PreFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest httpServletRequest = requestContext.getRequest();
logger.info("===== ZUUL::PRE =====");
logger.info("Request URL :: {} Request Method :: {}",
httpServletRequest.getRequestURI(),
httpServletRequest.getMethod());
return null;
}
}
[PostFilter.java]
public class PostFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(RouteFilter.class);
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
logger.info("===== ZUUL::POST =====");
return null;
}
}
[RouteFilter.java]
public class RouteFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(RouteFilter.class);
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
logger.info("===== ZUUL::ROUTE =====");
return null;
}
}
[ErrorFilter.java]
public class ErrorFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(RouteFilter.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
logger.error("===== ZUUL::ERROR =====");
return null;
}
}
- 구현 한 커스텀 클래스를 Bean 파일로 등록
[DefaultServerApplication.java]
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class DefaultServerApplication {
public static void main(String[] args) {
SpringApplication.run(DefaultServerApplication.class, args);
}
@Bean
public PreFilter preFilter() {
return new PreFilter();
}
@Bean
public PostFilter postFilter() {
return new PostFilter();
}
@Bean
public ErrorFilter errorFilter() {
return new ErrorFilter();
}
@Bean
public RouteFilter routeFilter() {
return new RouteFilter();
}
}
Filter Test
- 테스트 결과 지정한 Filter 클래스를 수행하는걸 확인할 수 있습니다.
추가로 이전 포스팅에 적었던 바와 같이 Python 기반 컴포넌트도 Eureka 서비스로 붙이는 예시를 보여드리고 오늘 포스팅은 마무리 하도록 하겠습니다 :)
Python Flask - Netflex Eureka
필요한 Python Lib
- flask
- flask_restx
- py_eureka_client
Python 이용한 Eureka 컴포넌트 구현
먼저 간단한 컴포넌트로 구성을 할 생각이기 때문에 Flask를 이용한 크롤링을 구현해 보겠습니다.
- 컴포넌트 내 메인이 되는 클래스
[app.py]
from flask import Flask, request
from flask_restx import Api
from flask_cors import CORS
import py_eureka_client.eureka_client as eureka_client
import crawling
import config.server_config as server
app = Flask(__name__)
api = Api(app)
CORS(app)
eureka_client.init(eureka_server=server.EUREKA_SERVER,
app_name=server.SERVICE_NAME,
instance_host=server.SERVICE_HOST,
instance_port=server.SERVICE_PORT)
@app.route("/craw/url", methods=['GET'])
def get_crawling_url():
return crawling.crawler('https://github.com/kdkrkwhr')
@app.route("/craw/get_data", methods=['POST'])
def post_crawling_data():
params = request.get_json()
return crawling.crawler_parsing(params['url'], params['tag'])
@app.route("/craw/test", methods=['GET'])
def test():
args = request.args
param = args['param']
return {"message" : "Hi", "param" : param}
if __name__ == "__main__":
app.run(host=server.SERVICE_HOST, port=server.SERVICE_PORT, debug=True)
- Eureka 설정 파일
[server_config.py]
SERVICE_NAME = 'kdk-eureka-zuul-service-flask'
SERVICE_PORT = 8102
SERVICE_HOST = '127.0.0.1'
EUREKA_SERVER = 'http://localhost:8081/eureka/'
- 실제 크롤링 서비스 로직
- 호출한 Url html을 가져오도록 구현
- 호출한 Url html 내 특정 태그 값을 가져오도록 구현
[crawling.py]
import requests
from bs4 import BeautifulSoup
def crawler(url):
html = requests.get(url)
return html.text
def crawler_parsing(url, tag):
html = requests.get(url)
soup = BeautifulSoup(html.text, 'html.parser')
select = soup.select_one(tag)
return select.text
Test
- 정상적으로 Discovery 된 것을 확인
- 정상적으로 Zuul을 이용한 Routing이 완수 된 것을 확인
마무리
MSA는 계속 흥미를 가지고 있는 주제로 아직까지도 틈틈히 공부를 하고 있습니다.
그래서 앞으로도 관련된 포스팅을 작성할 수가 있을 것 같습니다 😊
다시 한 번 새해 복 많이 받으시고, 편안한 한 해 되길 바랍니다 ~
Thanks .