본 문서(Java API 서비스 미터링 적용개발 가이드)는 파스-타 플랫폼 프로젝트의 미터링 플러그인과 Java API 미터링 서비스 애플리케이션을 연동시켜 API 서비스를 미터링 하는 방법에 대해 기술 하였다.
1.1.2. 범위
본 문서의 범위는 파스-타 플랫폼 프로젝트의 JAVA API 서비스 애플리케이션에 대한 미터링 방법에 대한 개발과 CF-Abacus 연동에 대한 내용으로 한정되어 있다.
본 문서는 API 미터링 서비스 애플리케이션을 Java 언어로 작성 하는 것에 대해 기술 한다.
본 문서는 API 서비스 고유의 비즈니스 로직은 구현 하지 않으며, API 서비스 호출 시의 미터링을 하는 기능만 구현 한다.
본 문서에서 언급 하는 “API 서비스를 사용하는 애플리케이션”은 별도로 제공 하는 Node.js API 미터링 개발 가이드를 참고 하여 개발 한다.
1.1.3. 참고 자료
2. JAVA API 서비스 미터링 개발가이드
2.1 개요
API 서비스 애플리케이션을 Java 언어로 작성 한다. API 서비스는 서비스 요청을 처리함과 동시에 API 사용 내역을 CF-ABACUS에 전송하는 애플리케이션을 작성 한다.
기능
설명
Runtime
미터링/등급/과금 정책
API 서비스 제공자가 제공하는 서비스에 대한 각종 정책 정의 정보. JSON 형식으로 되었으며, 해당 정책을 CF-ABACUS에 등록하면 정책에 정의한 내용에 따라 API 사용량을 집계 한다.
정책은 서비스 제공자가 정의해야 하며, JSON 스키마는 다음을 참조한다.
https://github.com/cloudfoundry-incubator/cf-abacus/blob/master/doc/api.md
서비스 브로커 API
Cloud Controller와 Service Broker 사이의 규약으로써 서비스 브로커 API 개발에 대해서는 다음을 참조한다.
https://github.com/OpenPaaSRnD/Documents/blob/master/Development-Guide/ServicePack_develope_guide.md#11
서비스 API
서비스 제공자가 제공하는 API 서비스 기능 및 API 사용량을 CF-ABACUS에 전송하는 기능으로 구성되었다.
대시보드
서비스를 제공하기 위한 인증, 서비스 모니터링 등을 위한 대시보드 기능으로 서비스 제공자가 개발해야 한다.
CF-ABACUS
CF-ABACUS 핵심 기능으로써 수집한 사용량 정보를 집계한다.
CF-ABACUS은 CF 설치 후, CF에 마이크로 서비스 형태로 설치한다. 자세한 사항은 다음을 참조한다.
https://github.com/cloudfoundry-incubator/cf-abacus
※ 본 개발 가이드는 API 서비스 개발에 대해서만 기술하며, 다른 컴포넌트의 개발 또는 설치에 대해서 링크한 사이트를 참조한다.
2.2 개발환경 구성
Java 애플리케이션 개발을 위해 다음과 같은 환경으로 개발환경을 구성 한다.
CF release: v226 이상
java version "1.8.0_101"
springBootVersion : 1.3.0.BUILD-SNAPSHOT
gradle 2.14
Spring Tool Suite 혹은 Eclipse
2.2.1 CF-Abacus 설치
별도 제공하는 Abacus 설치 가이드를 참고하여 CF-Abacus를 설치한다.
2.3 샘플 API 서비스 개발
샘플 api 서비스는 서비스 요청이 있는 경우, 해당 요청에 대한 응답 처리와 api 서비스 요청에 대한 미터링 정보를 CF-ABACUS에 전송하는 처리를 한다.
2.3.1 gradle 프로젝트를 생성
프로젝트 디렉터리를 생성하고, gradle 프로젝트로 초기화 한다
$ mkdir sample_api_java_service // 프로젝트 디렉토리
$ cd sample_api_java_service/
~/sample_api_java_service $ gradle init --type java-library // gradle 초기화
: wrapper
: init
BUILD SUCCESSFU
Total time: 2.435 secs
This build could be faster, please consider using the Gradle Daemon:
https://docs.gradle.org/2.14/userguide/gradle_daemon.html
2.3.2 샘플 API 서비스 형상
의존성 및 프로퍼티 형상 설명
파일
목적
build.gradle
애플리케이션에 필요한 의존성 정보를 기술
.gitignore
Git을 통한 형상 관리 시, 형상 관리를 할 필요가 없는 파일 또는 디렉토리를 설정한다.
manifest.yml
애플리케이션을 파스-타 플랫폼에 배포 시 적용하는 애플리케이션에 대한 환경 설정 정보
애플리케이션의 이름, 배포 경로, 인스턴스 수 등을 정의할 수 있다.
gradlew
Linux 환경에서 사용하는 gradlew 빌드 실행 파일
gradle 초기화 시 자동 생성 된다.
gradlew.bat
Window 환경에서 사용하는 gradle 빌드 실행 파일
gradle 초기화 시 자동 생성 된다.
settings.gradle
gradlew 실행 시 적용하는 환경 설정 파일
gradle 초기화 시 자동 생성 된다.
Java 파일 형상 설명
파일
목적
MeteringConfig
애플리케이션 구동 시 metering.properties를 로드 한다
MeteringAuthService
파스-타 플랫폼 상의 UAA 서버에서 abacus-usage-collector 에 대한 접근 권한 토큰을 취득하여 리턴 한다.
MeteringService
API 서비스 사용 요청 이 SampleApiJavaServiceController 에서 처리 될 때 API 서비스 처리에 대해 미터링이 적용된 사용량 보고서를 abacus-usage-collector 에 리포팅 한다.
SampleApiJavaServiceApplication
SpringBoot이 구동할 때, SpringBoot애플리케이션에 필요한 context 객체 들을 로드 한다.
SampleApiJavaServiceController
API 서비스 사용 요청을 처리하는 REST Controller.
본 샘플 애플리케이션에서는 API 서비스 고유의 비즈니스 로직은 구현 하지 않았으며, API 사용량을 abacus-collector에 전송하는 기능만 수행 한다.
application.properties
SpringBoot이 구동할 때, spring 에 필요한 property
metering.properties
API 사용량을 abacus-collector 전송 시에 설정 할 property 들이 정의 되어 있다.
앱을 CF에 배포할 때 필요한 설정 정보 및 앱 실행 환경에 필요한 설정 정보를 기술 한다.
```yml applications:
name: sample-api-node-service # 애플리케이션 이름
memory: 512M # 애플리케이션 메모리 사이즈
instances: 1 # 애플리케이션 인스턴스 개수
host: sample-api-java-service
path: ./build/libs/sample_api_java_service.jar # 배포될 애플리케이션의 위치
env:
SPRING_PROFILES_ACTIVE : cloud
```
metering.properties
API 서비스의 사용량 정보를 abacus-collector에 전송 할 때, 필요한 설정 정보 및 계정 정보를 기술 한다.
# abacus usage collector RESTAPI 의 주소
abacus.collector = https://abacus-usage-collector.<CF도메인/v1/metering/collected/usage
# abacus usage collector 가 secured 모드 true / 아닐 경우 false
abacus.secured = true
# 파스-타 플랫폼의 uaa server
uaa.server = https://uaa.<CF도메인>
# abacus usage collector RESTAPI 계정 정보 및 사용권한 (UAA server에 미리 설정)
uaa.client.id = <abacus.usage.read/write scope 권한을 가진 ID>
uaa.client.secret = <abacus.usage.read/write scope 권한을 가진 ID 비밀번호>
uaa.client.scope = abacus.usage.object-storage.write,abacus.usage.object-storage.read
2.3.4 MeteringAuthService 클래스
UAA 서버 URL 및 계정 정보를 참조 하여, UAA token 을 취득하여 리턴 한다.
public String getUaacTokenHTTPS () throws MalformedURLException {
String authToken = "";
String urlStr = authServer + "/oauth/token?grant_type=client_credentials&scope=" + encodeURIComponent(scope);
StringBuffer sb = new StringBuffer();
try {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
String authHeader = getAuthKey(clientId, clientSecret);
conn.setRequestProperty("authorization", authHeader);
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader br = new BufferedReader(in);
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
authToken= parseAuthToken(sb.toString());
br.close();
in.close();
conn.disconnect();
} catch (Exception e) {
System.out.println(e.toString());
}
return authToken;
}
metering.properties 에서 취득한 계정 정보를 BASE64 로 인코딩 한다.
$ cf create-service <서비스명> <플랜 명> <서비스 인스턴스 명>
예)
$ cf create-service standard_obejct_storage_light_api_calls standard sampleNodejslightCallApi
##서비스 확인
$ cf services
Getting services in org real / space ops as admin...
OK
name service plan bound apps last operation sampleNodejslightCallApi standard_obejct_storage_light_api_calls standard create succeeded
2.6.4. API 서비스 연동 샘플 애플리케이션 배포 및 서비스 연결
애플리케이션과 서비스를 연결하는 과정을 '바인드(bind)라고 하며, 이 과정을 통해 서비스에 접근할 수 있는 접속정보를 생성한다.
애플리케이션과 서비스 연결
## API 서비스 연동 샘플 애플리케이션 배포
$ cd <샘플 애플리케이션 경로>/sample_api_node_caller
$ npm install && npm run babel && npm run cfpack && ./cfpush.sh
## 서비스 바인드
$ cf bind-service <APP_NAME> <SERVICE_INSTANCE> -c <PARAMETERS_AS_JSON>
예)
$ cf bind-service sample-api-node-caller sampleNodejslightCallApi -c '{"serviceKey": "cloudfoundry"}'
## 서비스 연결 확인
$ cf services
Getting services in org real / space ops as admin...
OK
name service plan bound apps last operation
sampleNodejslightCallApi standard_obejct_storage_light_api_calls standard sample-api-node-caller create succeeded
## 애플리케이션 실행
$ cf start <APP_NAME>
예)
$ cf start sample-api-node-caller
## 형상 확인
$ cf a
Getting apps in org real / space ops as admin...
OK
name requested state instances memory disk urls
sample-api-node-service started 1/1 512M 512M sample-api-node-service.bosh-lite.com
sample-api-java-broker started 1/1 512M 1G sample-api-java-broker.bosh-lite.com
sample-api-node-caller started 1/1 512M 512M sample-api-node-caller.bosh-lite.com
2.7. API 및 CF-Abacus 연동 테스트
API 연동 샘플 애플리케이션의 url을 통해 웹 브라우저에서 접속하면 API 연동 및 API 사용량에 대한 CF-Abacus 연동 테스트를 진행 할 수 있다.
CF-Abacus 연동 확인
## 조직 guid 확인
$ cf org <샘플 애플리케이션을 배포한 조직> --guid
예)
$ cf org real --guid
877d01b2-d177-4209-95b0-00de794d9bba
## 샘플 애플리케이션 guid 확인
$ cf env <샘플 애플리케이션 명>
예)
$ cf env sample-api-node-caller
Getting env variables for app sample-api-node-caller in org real / space ops as admin...
OK
<<중략>>
{
"VCAP_APPLICATION": {
"application_id": "58872d8a-edfc-44df-97f0-df67cf9033a7",
"application_name": "sample-api-node-caller",
"application_uris": [
"sample-api-node-caller.bosh-lite.com"
],
"application_version": "55678102-584c-4fca-8304-82f727506b1d",
"limits": {
"disk": 512,
"fds": 16384,
"mem": 512
},
"name": "sample-api-node-caller",
"space_id": "2ce08996-f463-406c-a971-adbbaf4e4ca5",
"space_name": "ops",
"uris": [
"sample-api-node-caller.bosh-lite.com"
],
"users": null,
"version": "55678102-584c-4fca-8304-82f727506b1d"
}
}
<<후략>>
## API 사용량 확인
$ curl 'http://abacus-usage-reporting.<파스-타 도메인>/v1/metering/organizations/<샘플 애플리케이션을 배포한 조직>/aggregated/usage'
예)
$ curl 'http://abacus-usage-reporting.bosh-lite.com/v1/metering/organizations/877d01b2-d177-4209-95b0-00de794d9bba/aggregated/usage'