반응형
구글 검색엔진의 검색 결과를 프로그램에서 사용하고 싶으시다면, Google Custom Search API를 사용할 수 있습니다.
 
다음 문서를 참고합니다.
 
Custom Search API를 활성화 합니다.
 
그러면 API Key가 생성됩니다ㅏ.
 
Control Panel에 가서 검색 엔진을 설정합니다.
 
검색 엔진 생성
 
검색 엔진 ID를 구해서 API 호출에 사용합니다.
 
다음과 같이 하면 특정 도메인이 아닌 모든 싸이트 검색 결과를 받아올 수 있습니다.
 
검색 API 호출하는 예제입니다.
[jerryj@jerrydev search-api]$ cat query.sh
API_KEY=AIzaSyA6UWNS3FoWoomibgWvnTMICLJt65vb8Xc
ENGINE_ID=010328994824229770323:3v-oregc47y
curl "https://www.googleapis.com/customsearch/v1?key=${API_KEY}&cx=${ENGINE_ID}&q=javalove93"
 
검색 결과입니다.
...
"items": [
  {
   "kind": "customsearch#result",
   "title": "javalove93 (Jerry Jeong) · GitHub",
   "htmlTitle": "\u003cb\u003ejavalove93\u003c/b\u003e (Jerry Jeong) · GitHub",
   "link": "https://github.com/javalove93",
   "displayLink": "github.com",
   "snippet": "javalove93 has 21 repositories available. Follow their code on GitHub.",
   "htmlSnippet": "\u003cb\u003ejavalove93\u003c/b\u003e has 21 repositories available. Follow their code on GitHub.",
   "cacheId": "MuQL2KxJQmQJ",
   "formattedUrl": "https://github.com/javalove93",
   "htmlFormattedUrl": "https://github.com/\u003cb\u003ejavalove93\u003c/b\u003e",
 
 
실제 구글 싸이트 검색 결과와 비교해 봅니다.
 
 
RU5DMKCweyHDKrQJE9BIJoi+fzXxgWiAf3gmBZgU6tOfKOb/+74bBArivRogfdslL1hfk4fP1xNUKrguhHeV7KLw8Q2b63bmOwlchzJzcMoayDysBXmK26L4RBKPdNjNZfH0YLkgNw7BjWKqWyqGrUCFRvGGTNDm4Ji6F5YDrJA4Wj1M2wfNLV1hQ4+knogz/ueyf2EFx2+/+MwOxlufg3/OYr1T1WrA8cjahbIenRTUt6lBE4YGzIxVZ3zZSO1HIgeuqAD76d4aOzfws3uu51Qj19tptjWlBfkbf2lV2poc+RfopI3OGAiYPrKCYg8INSeW3N0NlyGJ4VsLw9v65eJpCKxRNIPbu/bH7CSYPWvo4EAB2PGuSz//oq22BvNIdInFjG8IIVDL09OFUXwyF2I1BSeyNQmrcLz0sucOvxHhd7P9mp0SgT14NVQhsqn1+YoRy4ZTe17hirjWdBLhUQ4UEp9QrCJp/vY0AKmPe8pRQeooYX6a9NdsuaoYY51MUu0jAZnrH4qlCnP8S+HNqs/UqNPeOcvffZUPVR6SmQ1mltZ+bSe+6j2My/iEqSiy/JOqTOaDZTCN0NjkB+hb3wBt4xW/wucygO8vInOKl3soNyII
 
Posted by Hey Jerry
,
반응형
Google Cloud Compute Engine 내에서 외부 IP를 알려면 어떻게 해야 할까?
다음과 같이 한다고 알 수 있는 것은 VM 내부 IP 뿐이다.
[jerryj@jerrydev tmp]$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:17ff:febe:3c2f  prefixlen 64  scopeid 0x20<link>
        ether 02:42:17:be:3c:2f  txqueuelen 0  (Ethernet)
        RX packets 2051  bytes 113494 (110.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2033  bytes 15436457 (14.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1460
        inet 10.183.0.2  netmask 255.255.255.255  broadcast 10.183.0.2
        inet6 fe80::4001:aff:feb7:2  prefixlen 64  scopeid 0x20<link>
        ether 42:01:0a:b7:00:02  txqueuelen 1000  (Ethernet)
        RX packets 7848752  bytes 46045286889 (42.8 GiB)
        RX errors 0  dropped 0  overruns 0  frame 69
        TX packets 8503481  bytes 2354506702 (2.1 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 
다음의 문서를 참고해서 VM의 Metadata를 조회하면 된다. 조회 가능한 항목들 역시 아래 문서에 나와 있다
 
 
VM 인스턴스 이름을 구하는 Metadata 조회 방법 (아래 헤더가 반드시 포함되어야 함)
[jerryjg@jerrydefault-4cpu-template-1 ~]$ curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/name
 
jerrydefault-4cpu-template-1
 
External IP를 구하는 Metadata 항목 확인 (recursive=true 옵션 사용)
[jerryj@jerrydev tmp]$ curl -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/?recursive=true  | python -m json.tool
 
[
    {
        "accessConfigs": [
            {
                "externalIp": "104.199.xxx.xxx",
                "type": "ONE_TO_ONE_NAT"
            }
        ],
        "dnsServers": [
            "169.254.169.254"
        ],
        "forwardedIps": [],
        "gateway": "10.183.0.1",
        "ip": "10.183.0.2",
        "ipAliases": [],
        "mac": "42:01:0a:b7:00:02",
        "mtu": 1460,
        "network": "projects/249965614499/networks/jerry-default",
        "subnetmask": "255.255.240.0",
        "targetInstanceIps": []
    },
    {
        "accessConfigs": [
            {
                "externalIp": "",
                "type": "ONE_TO_ONE_NAT"
            }
        ],
        "dnsServers": [
            "169.254.169.254"
        ],
        "forwardedIps": [],
        "gateway": "10.10.10.1",
        "ip": "10.10.10.2",
        "ipAliases": [],
        "mac": "42:01:0a:0a:0a:02",
        "mtu": 1460,
        "network": "projects/249965614499/networks/nat-test-jerryjg",
        "subnetmask": "255.255.255.0",
        "targetInstanceIps": []
    }
]
 
[jerryj@jerrydev tmp]$ curl -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip
104.199.xxx.xxx
 
Posted by Hey Jerry
,
반응형
 
에서 Squid HTTP Proxy를 이용하여 Google Cloud API를 방화벽을 우회해 호출 방법에 대해 알아보았습니다.
 
지금부터 소개하는 방법은 HTTP Proxy를 사용할 수 없고 Reverse Proxy 밖에 없는 환경에서 사용할 수 있는 방법입니다.
 
Private Google Access를 이용한 방법
 
사실 이 문제의 근본적인 해결은 VPN이나 Interconnect를 사용하여 On-Premise 환경을 Google Cloud와 직접 연결하고 다음의 Private Google Access를 사용하는 것입니다.
 
 
이 방법은 On-Prem 환경의 DNS 설정에 다음을 CNAME(alias)로 추가하고 
즉, *.googleapis.com에 대한 DNS 조회 요청을 모두 restricted.googleapis.com으로 리턴하고
 
*.googleapis.com    CNAME    restricted.googleapis.com
 
다음의 restricted.googleapis.com에 해당하는 IP 대역을 VPN 또는 Interconnect를 통해 Google Cloud로 전달하도록 라우팅 테이블을 조정합니다.
 
199.36.153.4/30
 
그러면 Google Cloud API에 대한 모든 액세스가 199.36.153.4/30 대역으로 Google Cloud에 전달되고, Public IP가 아닌 내부 IP를 통해 처리됩니다.
 
dnsmasq를 이용한 방법
 
위의 방법은 먼저 VPN이나 Interconnect를 연결되어 있어야 하고, 두 번째는 199.36.153.4/30 IP 대역에 대한 라우팅 규칙을 On-Premise에 추가할 수 있어야 합니다.
만약 어느 하나라도 불가능한 경우에는 지금 소개하는 방법을 사용할 수 있습니다.
 
그림으로 보면 다음과 같은 구조를 가지게 됩니다.
 
필요한 소프트웨어 설치와 구성은 다음과 같습니다.
 
dnsmasq
  • 위치: On-Premise 상의 특정 서버 또는 gsutil(또는 Google Cloud API 클라이언트)을 실행할 서버
  • 설정: 아래와 같이 *.googleapis.com에 대한 A 레코드로 Google Cloud 상의 haproxy가 설치된 VM IP(여기서는 1.1.1.1)을 지정
    ping storage.googleapis.com 을 해 보면 1.1.1.1이 lookup이 되면 정상
address=/googleapis.com/1.1.1.1
 
haproxy
  • 위치: Google Cloud 상의 VM (파이어월에서 이 VM으로 Outbound 통신이 가능해야 함)
  • 설정: 아래와 같이 443 포트로의 요청을 restricted.googleapis.com:443 으로 포워딩(Reverse Proxy) 하도록 함
frontend  mainj *:443
    mode tcp
    default_backend             javalove93
 
backend javalove93
    balance     roundrobin
    mode tcp
    server      static restricted.googleapis.com:443
 
Google Cloud API 클라이언트
  • 위치: On-Premise 상의 서버
  • 설정: dnsmasq가 DNS 서버로 /etc/resolv.conf에 등록이 되어 있으면 됨 (아래는 동일한 서버에 설치된 경우를 가정)
nameserver 127.0.0.1
 
그러면 실행되는 순서는 다음과 같습니다.
 
  1. Google Cloud API 클라이언트(예: gsutil)에서 API를 호출하기 위해 DNS lookup 수행 (예: storage.googleapis.com)
  2. dnsmasq에서 storage.googleapis.com의 IP로 haproxy가 설치된 VM의 IP(예: 1.1.1.1)를 반환
  3. API 클라이언트에서 haproxy VM으로 HTTPS 요청 호출
  4. haproxy 서비스에서 HTTPS 요청을 restricted.googleapis.com으로 포워딩 (Private Google Access에서 제공)
  5. 실제 Google Cloud API 실행
 
그러면 On-Premise 환경에서는 Google Cloud 상의 VM의 IP인 1.1.1.1만 Outbound로 개방하면 됩니다.
 
 
 
Posted by Hey Jerry
,
반응형

에버노트 원본: https://www.evernote.com/l/ABqNPV5LBCVPZ5ptuQSNUrtepNsGMr_IPGI 

 
1. 시나리오
 
다음과 같은 시나리오를 Drools BRMS 및 Fusion(CEP)로 구현하였다.
 
  • 온도, 연기 센서에서 데이터를 수집
  • 2초 사이에 두 개의 센서가 동시에 온도는 80도를 넘고, 연기 센서는 18을 넘어선 경우 화재로 감지
  • 화재가 감지되면 팬 Actuator를 가동
  • 온도가 다시 40도 미만, 연기 센서의 수치가 10 미만으로 2초간 지속되면 화재가 종료된 것으로 감지
  • 온도 센서만 80도를 넘어서면 고온 경고
  • 연기 센서만 18을 넘어서면 연기 경고
 
다음은 별도로 구현하는 것으로 가정하였다.
 
  • 센서 데이터 수집: 아두이노에 센서를 장착하여 수집
  • 수집된 센서 데이터 입력: 센서 데이터는 REST API를 통해 입력 됨
  • Actuator 가동은 별도의 REST API를 통해 기기로 전달
 
따라서 이 예제에서는 REST API를 통해 수집되었다고 가정되는 센서 데이터 값을 Drools 엔진에 넣어 CEP가 문법을 감지하는 것만 구현하여
Drools Fusion을 통한 CEP 기능을 시연하는데 중점을 두었다.
 
 

2. 개발 도구
 
개발 도구는 다음과 같이 준비한다.
 
  • Eclipse Neon 기준
 
 
  • Eclipse Marketplace에서 다음 모듈들을 설치 설치
 
 
 
다음 과정을 거쳐 프로젝트를 생성한다.
 
  • 프로젝트 생성
 
  • 아래와 같이 예제를 포함하여 프로젝트를 생성 가능
 

3. Rule 실행 준비
 
기본적으로 Drools는 META-INF/kmodule.xml에 정의된 선언적 내용을 통해 Rule 리소스를 읽어 오지만
다음과 같은 방법으로 DRL 파일을 직접 읽어 들일 수도 있다.
 
DRL을 파일에서 읽어 들임 (6.3)
 
KieServices ks = KieServices.Factory.get();
KieRepository
kr = ks.getRepository();
KieFileSystem
kfs = ks.newKieFileSystem();

kfs.write(ResourceFactory.newClassPathResource("rules/cep.drl", CEPTest.class));

KieBuilder
kb = ks.newKieBuilder(kfs);

kb.buildAll(); // kieModule is automatically deployed to KieRepository if successfully built.
if (kb.getResults().hasMessages(Message.Level.ERROR)) {
   
throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
}

KieContainer
kContainer = ks.newKieContainer(kr.getDefaultReleaseId());

KieSession
kSession = kContainer.newKieSession();

 
DRL을 파일에서 읽어 들임 (6.3 CEP)
CEP(Fusion) 기능을 사용하려면 Drools를 Stream 모드로 실행해야 하며, 이 경우에는 일반 Rule과 달리 다음과 같이 코드를 작성한다.
 
KieBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption(EventProcessingOption.STREAM);

KnowledgeBuilder
kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("rules/cep.drl", CEPTest.class), ResourceType.DRL);
if (kbuilder.hasErrors()) {
   
throw new RuntimeException("Build Errors:\n" + kbuilder.getErrors().toString());
}

KnowledgeBase
kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages())

StatefulKnowledgeSession
ksession = kbase.newStatefulKnowledgeSession();

return ksession
;
DRL Rule은 실행 시, 해당 파일에 정의된 모든 Rule들이 실행(검사)되고 결과가 업데이트 될 경우
다시 Rule들을 검사하여 규칙에 일치하는 것들이 없을 때까지 실행된다.
따라서 A Rule의 실행 결과로 B Rule이 만족될 경우 A, B Rule은 같이 실행 된다.
문제는 A Rule의 실행 결과 A Rule 자신이 다시 조건을 만족하여 실행되는 Loop 현상이 발생할 수 있는데, 이것을 방지하려면
Rule에 다음과 같은 no-loop 옵션을 준다. 또는 A Rule의 실행 결과 B Rule이 실행되고, 다시 B Rule의 실행 결과 A Rule이 실행되는
복합적인 Loop 현상도 발생할 수 있는데 이것을 방지하기 위해서는 lock-on-active 옵션을 준다.
 
 
Loop 방지
 
no-loop: Self-Loop 방지
lock-on-active: Complex Rule에서 하나의 Rule에 의해 다른 Rule이 Trigger 되는 것 방지
 
rule "Fire Alarm Rule"
no-loop true
lock-on-active true
   
when
        fad: FanActuatorData(on ==
false) &&
        tsd: ThermoSensorData(temperature > 80.0, t: temperature) &&
        ssd: SmokeSensorData(smokeLevel > 18.0, s: smokeLevel) over window:time(0.1s)
   
then
        System.out.println(
"*** Fire Alarm ***");
fad.setOn(
true);
update(fad);

end

 

4. Rule 정의
 
 
위의 시나리오를 구현한 CEP Rule은 다음과 같이 정의할 수 있다.
 
//created on: 2017. 3. 26
package com.sample.cep

//list any import classes here.

import com.sample.cep.*;

//declare any global variables here

declare ThermoSensorData
@role(event)
end

declare SmokeSensorData
@role(event)
end


rule "High Temperature Rule"
no-loop true
lock-on-active true
// Fire Alarm이 활성화 되지 않은 상태에서, 온도가 80도를 넘을 경우
   
when
        fad: FanActuatorData(on ==
false) &&
        tsd: ThermoSensorData(temperature > 80.0, value: temperature)
from entry-point thermometer
   
then
        System.out.println(
"*** High Temperature Alert: " + value + " ***");

end

rule "Dense Smoke Rule"
no-loop true
lock-on-active true
// Fire Alarm이 활성화 되지 않은 상태에서, 연기 농도가 18을 넘을 경우
   
when
        fad: FanActuatorData(on ==
false) &&
        ssd: SmokeSensorData(smokeLevel > 18.0, value: smokeLevel)
from entry-point smoke
   
then
        System.out.println(
"*** Dense Smoke Alert: " + value + " ***");

end

rule "Fire Alarm Rule"
no-loop true
lock-on-active true
// Fire Alarm이 활성화 되지 않은 상태에서, 2초 사이에 한 번이라도 온도가 80도를 넘고 연기 농도가 18을 넘을 경우
   
when
        fad: FanActuatorData(on ==
false) &&
        tsd: ThermoSensorData(temperature > 80.0, t: temperature) over window:time(2s)
from entry-point thermometer &&
        ssd: SmokeSensorData(smokeLevel > 18.0, s: smokeLevel) over window:time(2s)
from entry-point smoke
   
then
        System.out.println(
"*** Fire Alarm !!!!!!!!!!!!!!!!!!! ***");
fad.setOn(
true);
update(fad);

end

rule "Fire Alarm Off Rule"
no-loop true
lock-on-active true
// Fire Alarm이 활성화 된 상태에서, 2초 동안 한 번도 온도가 40도를 넘지 않고 연기 농도가 18을 넘지 않을 경우
   
when
        fad: FanActuatorData(on ==
true) &&
   
accumulate(
ThermoSensorData(temperature >= 40.0) over window:time(2s)
from entry-point thermometer;
$cnt1: count(1);
$cnt1 == 0
    ) &&
   
accumulate(
SmokeSensorData(smokeLevel >= 10.0) over window:time(2s)
from entry-point smoke;
$cnt2: count(1);
$cnt2 == 0
    )
   
then
        System.out.println(
"*** Fire Alarm Off ***");
fad.setOn(
false);
update(fad);

end


위의 화재 종료(File Alarm Off Rule)를 감지하는 CEP 규칙은 일반적으로 가장 많이 사용하는 문법으로서
accumulate 함수를 통해 센서 데이터가 2초 Time Window 상에서 몇 번 조건에 일치하는지를 count하고 있다.
여기서는 온도가 40도 이상인 경우과 연기 수치가 10이상인 경우를 세는데, 그것이 2초간 한 번도 없다면 화재는 종료된 것으로 인정한다.
 
DRL 문법에서는 다음과 같이 입력한 Java Bean의 Attribute를 읽어 들일 수 있으며
 
rule "High Temperature Rule"

   
when
        tsd: ThermoSensorData(temperature > 80.0, value: temperature)
   
then
        System.out.println(
"*** High Temperature Alert: " + value + " ***");

end


또는 다음과 같이 직접 getter/setter 메소드 호출하는 것도 가능하다.
 
 
public class ThermoSensorData extends SensorData {
public ThermoSensorData(double value) {
setTemperature(
value);
}

public double getTemperature() {
return getDoubleValue();
}

public void setTemperature(double value) {
setDoubleValue(
value);
}
}

 
rule "High Temperature Rule"

   
when
        tsd: ThermoSensorData(tsd.getTemperature() > 80.0, value: temperature)
   
then
        System.out.println(
"*** High Temperature Alert: " + tsd.getTemperature() + " ***");

end

 

5. 센서 데이터를 입력하여 Rule 실행
 
센서 데이터는 다음과 같이 상수로 정의하였다. 실제 시나리오에서는 REST API 등으로 받아 처리하면 된다.
 
final static double[] THERMO_DATA = new double[] {
20.0, 19.0, 23.3, 85.2, 49.5, 20.0, 21.2, 80.5, 90.9, 74.3, 38.2, 37.1, 20.0, 88.0, 79.0
};

final static double[] SMOKE_DATA = new double
[] {
22.0, 08.2, 03.3, 05.2, 01.5, 02.0, 01.2, 18.5, 19.9, 12.3, 12.8, 09.9, 08.8, 17.9, 18.1
};
CEP에서 처리할 두 개의 센서 데이터를 각각 다른 스트림으로 분리한다.
 
EntryPoint ep1 = kSession.getEntryPoint("thermometer"); // 온도 센서 입력 스트림
EntryPoint
ep2 = kSession.getEntryPoint("smoke"); // 연기 센서 입력 스트림

그리고 다음과 같이 센서 데이터를 발생하는 즉시 입력하고, Rule을 실행한다.
 
// 센서 값이 지속적으로 들어온다고 가정
for(int i = 0; i < THERMO_DATA.length; i++) {
System.
out.println(i);
Thread.sleep(1000);
// 두 개의 센서 값이 각각 다른 시점에 들어온다고 가정
ThermoSensorData
tsd = new ThermoSensorData(THERMO_DATA[i]);
ep1.insert(tsd);
System.
out.println("  T: " + THERMO_DATA[i]);
kSession.fireAllRules();
Thread.sleep(100);
// 두 개의 센서 값이 각각 다른 시점에 들어온다고 가정
SmokeSensorData
ssd = new SmokeSensorData(SMOKE_DATA[i]);
ep2.insert(ssd);
System.
out.println("  S: " + SMOKE_DATA[i]);
kSession
.fireAllRules();
}
중단에 Sleep을 넣은 이유는 실제로 두 개의 센서 데이터가 동시에 들어오지 않고, 발생할 때마다 들어 온다는 것을 가정하였다.
이렇게 일정하거나 동시에 발생하지 않는 두 개 이상의 센서 데이터에서 일정한 규칙을 감지하기 위한 로직을 구현할 때 Drools CEP는 매우 유용하다.
 
 
 
 
 
 
 

"

Posted by Hey Jerry
,
반응형









Posted by Hey Jerry
,
반응형
SSH로 원격 서버에 접속할 때 매번 패스워드를 입력하는 것은 상당히 귀찮은 작업이다.

특히 여러 개의 노드를 관리할 때는 패스워드를 잊어 먹을 수도 있고 심지어는 패스워드를 메일이나 메신저로 쉽게 주고 받기도 한다.


그것보다는 PKI 방식으로 Private Key를 개인이 가지고, 접속 대상 서버에 Public Key를 올려서 PKI 방식으로 접속하는 것이

패스워드 입력도 막고 암호를 노출하는 보안 위험도 줄일 수 있다.


그런데 이게 노드가 많으면 여간 귀찮은 작업이 아니다. 그래서 그 과정을 자동화 할 수 있는 Python 프로그램을 만들어 봤다.


다음과 같이 서버에서 다운 받아서 (첨부 파일을 서버에 올려 놨음)

wget http://tinyurl.com/autosshosc
(또는 https://www.dropbox.com/s/kkdsvad3ulau2dw/AutoSSH.py?dl=0)

mv autosshosc autossh
cmmod 755 autossh

한 다음에 다음과 같이 실행하면

./autossh <대상 호스트 IP or hostname> <ID> <Password. 1회만 입력) [옵션: 서버의 alias로 사용하고 싶은 이름]

==> 대상 호스트 명을 IP:Port 형식으로 지정할 수 있는 기능이 추가되었다 (2014/12/04)


다음과 PKI 가 자동으로 대상 서버에 심어지고 alias와 계정 명이 .ssh/config 파일에 등록이 되어

전체 호스트 명을 칠 필요 없이 alias 이름 만으로 접속이 가능해 진다. (계정 명도 칠 필요 없음)


ssh alias명

scp alias명:/<경로> ... (.ssh/config에 alias로 있기 때문에 scp 등에서도 사용 가능)


물론 아래와 같이 접속도 가능하다.


ssh <전체 도메인 또는 IP>


툴의 사용 방법은 다음과 같다.

Usage autossh <hostname> <username> <password> [alias]


소스: 매번 첨부가 귀찮아 아래 링크 공유합니다.

https://www.dropbox.com/s/kkdsvad3ulau2dw/AutoSSH.py?dl=0








Posted by Hey Jerry
,
반응형

누군가의 질문을 받고 만들어 줬습니다.
OS 상에서 CLOSE_WAI와 FIN_WAIT가 생길 때 어떻게 해야 하냐고...

정답은 프로그램에서 닫아 주어야 합니다.

소켓 클라이언트와 서버 사이에 어느 한 쪽에서 close를 했음에도(FIN 신호를 상대방으로 보냄)
상대방에서 close를 하지(FIN ACK를 보내지 않음) 않으면 close 한 쪽에는 FIN_WAIT가
close를 하지 않은 쪽에는 CLOSE_WAIT가 발생합니다.

TCP 파라미터를 조정해서 해결할 수 없냐는 경우도 있는데, 이것은 절대로 TCP 파라미터로 해결할 문제가 아니라
프로그램을 잘 짜야 하는 문제입니다. 특히 CLOSE_WAIT가 많이 발생하는 서버는 memory leak이 발생할 가능성도 매우 높습니다.

그 과정을 보여주는 예제코드를 올리니 궁금하면 테스트 해 보시기 바랍니다.
다음은 프로그램에 대한 설명입니다.

SocketServer 에서 stream으로 데이터를 클라이언트하고 다주고 받고,
클라이언트쪽 소켓이 닫히면 stream 종료(Java에서는 -1... 언어 마다 다름)를 만나면 닫아줘야 하는데 그것을 닫지 않으면fin/close_wait 현상이 발생합니다. 다음과 같이 실행하고 Server 소스에서 close 부분의 remark를 풀고도 테스트해 보시기 바랍니다.

java SocketServer


java SocketClient



SocketClient.java


SocketServer.java


Posted by Hey Jerry
,
반응형

WebLogic이 웹서버와 연결되어 있고 웹서버를 통해 JSP/Servlet에 대한 요청을 백엔드 WLS로 포워딩 하고 있다.

그런데 만약 파일 업로드 기능을 사용해서 WLS 서버로 파일을 저장할 경우 웹서버에서 그것을 보여주려면

WLS쪽에 File Download를 위한 Servlet을 짜야 할 것이다.

그런데 간단한 Tip으로 코딩 없이 설정으로도 해결할 수 있는데... 아래와 같이 WebApp을 하나 만들어 Deploy 하고

weblogic.xml에 다음과 같이 특정 디렉토리(여기서는 파일이 업로드되어 저장되는 디렉토리)를 virtual-directory-mapping으로 잡아 놓고

disable-implicit-servlet-mappings 설정을 통해 JSP 설정을 막아 놓으면 업로드 되는 파일들을 그냥 일반 static contents처럼 다운받을 수 있게 된다.


<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:weblogic-version>12.1.1</wls:weblogic-version>
    <wls:context-root>mywebapp</wls:context-root>
    <wls:virtual-directory-mapping>
        <wls:local-path>/home/oracle/website</wls:local-path>
        <wls:url-pattern>/downloads/*</wls:url-pattern>
    </wls:virtual-directory-mapping>
    <wls:container-descriptor>
        <wls:index-directory-enabled>true</wls:index-directory-enabled>
        <wls:disable-implicit-servlet-mappings>true</wls:disable-implicit-servlet-mappings>
    </wls:container-descriptor>
</wls:weblogic-web-app>


JSP에 대한 실행이 막혔지만 그럼에도 불구하고 보안상 File Upload 프로그램을 작성할 때는 JSP와 같은 코드는 절대로 업로드하지 못하게 하는 것이 바람직 하다.


다음은 실행 결과이다.

Posted by Hey Jerry
,
반응형

WebLogic에서는 JMX 연결을 하려면 RMI/IIOP를 사용한다. (아래 블로그 참고)


http://blog.naver.com/javalove93/130031031944


그런데 Zabbix에서는 JMX 연결 시(Java Agent를 통해) 프로토콜을 지정할 수 없어 WebLogic JMX에 직접 접속할 수 없다.

Zabbix에 Zapcat이라는 다른 방식이 있는 것 같은데 이것은 Application 내에 JAR를 포함시켜야 하는 것으로 보여 역시 일반적으로 사용하기에는

쉽지 않아 보인다 (http://www.kjkoster.org/zapcat/How_To.html)


https://support.zabbix.com/browse/ZBXNEXT-1935


Java gateway server only support RMI protocol, but WebLogic doesn't support RMI. It's necessary to use IIOP protocol.
http://docs.oracle.com/cd/E13222_01/wls/docs90/jmx/accessWLS.html

Also, there is a difference in environment parameter of JMXConnectorFactory.connect method for WebLogic JMX

Current java gateway code:

env = new HashMap<String, String[]>();
env.put(JMXConnector.CREDENTIALS, new String[]

{username, password}

);

Sample code from WebLogic documentation:

Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, username);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");


결론적으로는 애매해 보이는데 Zabbix의 Java Gateway를 조금 수정해서 IIOP를 지원하게 하거나

WLS JMX 를 일반적인 RMI기반 JMX로 Wrapping할 수 있는 프로그램을 만들면 어떨까 하는 생각이다.


Posted by Hey Jerry
,
반응형

원문: https://www.zabbix.com/wiki/howto/monitor/db/orabbix_monitor_oracle_with_zabbix


아래는 오라클 DB 에서 모니터링 가능한 내용의 예이다.

  • DB Version (i.e. Validity of package)
  • Archiving (Archive log production with trend analysis)
  • Event Waits (Files I/O, single block read, multi-block read, direct path read, SQLNet Messages, Control file I/O, Log Write)
  • Hit Ratio (Hit Ratio on Triggers, Tables/Procedures, SQL Area, Body)
  • Logical I/O (Server performance on Logical I/O of: Current Read, Consistent Read, Block Change)
  • Physical I/O (Redo Writes, Datafile Writes, Datafile Reads)
  • PGA
  • SGA (In particular; Fixed Buffer, Java Pool, Large Pool, Log Buffer, Shared Poolm Buffer Cache)
  • Shared Pool (Pool Dictionary Cache, Pool Free Memory, Library Chache, SQL Area, MISC.)
  • Pin Hit Ratio (Oracle library cache pin are caused by contention with the library cache, the area used to store SQL executables for re-use)
  • Sessions / Processes
  • Sessions (Active Sessions, Inactive Sessions, System Sessions)
  • DBSize/DBFileSize (DBSize size of database really used space and of Filesize)


그래프로 생성 가능한 항목들이다.

  • Archivelog
  • DBSize and DBFileSize
  • Events Wait
  • HIT Ratio
  • Logical I/O
  • PGA
  • Pin HIT Ratio
  • Session
  • SGA
  • Shared Pool
  • Sessions Processes

Events Wait 모니터링 화면

SGA Memory 모니터링 화면

Session 써머리




Posted by Hey Jerry
,