doge 코인 뭐임마 다툴래염?

...진짜 하다하다 별 코인이 다 나오네. WOW

층간소음 매트 추가로 살라고 갔더니 뭐임마 다툴래염?


오우! 장사 좀 할 줄 아는것인가.

항상 말하는거지만 요새 돈이 모이는 핫한 대상은 '아이' '노인' 그리고 '동물' 인데 결국 동물도 추가되었군.



전기세 나옴 뭐임마 다툴래염?

7월 1일부터 31일까지의 전기세가 나왔는데.
우리집 에어컨은 아마 이거였을거임
[삼성 스마트Q9000 AF17M6473WZR]

어쨋거나 6월말부터 지금까지도 24시간 돌림. 

아침부터 거의 자정까지는 56.9㎡ 짜리 돌리고 밤 10시부터 다음날 8시까진 18.7㎡짜리를 돌림.
즉 10시부터 12시까진 두개 다 돌린단 소리.

어쨋거나 인버터 어쩌구 저쩌구 해서 인버터가 얼마나 효과가 좋은지 결과가 나왔다.


대충 기본적인 전기 사용량은 375kw가 나와서 실제 400kw도 안되는 용량이 나옴. 저정도면 대충 5~6만원 나온다고 하는데,
일단 출산할인덕에, 16000원 깎아먹고 42000원 정도 나옴. 거기에 이것저것해서 48000원.

실제 다른 면적보면 다른면적 평균은 288kw정도임. 우리집이 전기쓸게 많아서 쓰는거..

음.. 이정도면 걍 24시간 돌리는게 스트레스도 적고 싸게 먹히겠구만. 인버터 좋네...

[기억저장용] ZooKeeper lock하고 클러스터 써보기 흔한 전산쟁이의 삽질일기

원래라면 메시지 브로커 하나 만들어서 이래저래 메시지 토스를 할라고 했는데... 
어차피 그럴꺼 만들어놓은거 있음 갖다쓰면 되지 라고 해서 뒤져본거...

우선 계획은 주키퍼를 여러개 돌리고 이를 클러스터 묶은다음. 하나 뒤져도 멀쩡히 굴러가게 세팅할거임.
대신 주키퍼 특성이 3개이상 돌려야 뒤져도 살아남음. 주키퍼가 50%이상 뒤지면 아예 전체가 멈추는거라 그렇다.
즉. 2개를 돌려서 하나 죽으면 멈춰버리니까 의미없다.


그래서 적당한걸 다운받아준다. 나는 3.4.12를 받음.

다운받으면 대충 이래 생겨먹었음.

<생겨먹은거>

보면 jar도 있고 한데, client용 example을 쓸라면 저게 있어야 함. 근데 딱히 없어도 됨. 
왜냐면 client는 또 딴거 받을 예정이다.

리눅스는 이렇게 받음. 

wget http://apache.tt.co.kr/zookeeper/zookeeper-3.4.12/zookeeper-3.4.12.tar.gz
그리고 압축풀어서 세팅함.


어쨋든. 저건 윈도우 용이고 리눅스용이고 통합이라 bin안에 들어가면 이래 생겼다.

<어차피 sh하나 cmd하나 같은것을..>

윈도우용 실행하는건 zkServer.cmd를 걍 돌리면 됨. 
일단 그전에 해야하는게 설정파일을 설정해야함. 설정파일은 conf안에 있는데 [zoo_sample.cfg]를 [zoo.cfg]로 잡아주면 된다.
그리고 그걸 열어보면.


여기서 각 설정을 넣어야 한다. 세부 설정중 핵심은 tickTime, initLimit, syncLimit, dataDir 이거고 그중에 직접 작업해야하는건
dataDir다. 여기에 키값이 들어가던데. 자기 id를 지정해주는듯. 그래서 저 경로에 myid라는거 하나 만들고 안에 숫자 하나 넣어줘야함.

근데 지금 나는 클러스터링 그러니까 주키퍼를 여러개 띄워놓고 처리 할거라서 안에 넘버링은 다 달라야 됨.

<윈도꺼 2>


<리눅스꺼 1>

그담에 클러스터를 위해서 안에 서버넘버를 넣어줘야 한다. myid랑 맞춰서 해주면 좋을듯.



<요런식으로 server 1, 2,3 세팅해놓으면 지들끼리 통신함>


그러면 기본적인 작업은 끝. 그담에 서버를 동작한다. 리눅스는 아래와 같다.
[ ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd} ]
zkServer.sh start

윈도우는 걍 zkServer.cmd 실행하면 됨.


그리고 로그는 bin 밑에 zookeeper.out에 있는데 여기 내용은 다음과 같다.
<적당히 로그찍히는걸 확인할 수있다>

그중에 status옵션으로 출력해보면 leader나 follower로 구분된다.
 ./zoo.sh status
Mode: follower나 Mode: leader로 나옴

그담에 client를 짜야지. client는 보통 apache의 curator를 쓴다. 원래 넷플릭스껀데 apache에 줬다고 함. 
어쨋든 큐레이터가 넷플릭스 수천대의 서버관리하는데 쓰다가 넘긴거라고 하니 쓸만할듯.

근데 최신껄 쓰니까 뭐가 안되서 검색 좀 해봤더니. 이 버전엔 2.xx대를 쓰라고 해서 2.12.0을 가져다 씀.
그래서 일반적으로 노드를 생성하고 변경하고 삭제하고 하는데,  기본적 경로의 노드는 고정으로 만들고, 
client 연결시 임시로 만들고 연결 끊기는 노드는 다른걸로 만들어야 된다.


클라이언트는 우선 고정 path을 위해서. 인스턴트 node path가 아닌 고정 node. 즉 연결이 끊어져도 사라지지 않는 node가 하나 있어야 한다.(그래야 안에서 뭔가 하지) 
그래서 끊었다 새로 연결되도 삭제되지 않는 node를 생성한다

여기는 lock으로 검색하니 좀 나오드라. 


client.create().creatingParentsIfNeeded().forPath("/recovery", "recovery".getBytes());

이후 연결되는 child node는 인스턴트로 생성을 해서 락 처리를 하는데...

client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/recovery/" + serverInfo, "init".getBytes());
보통 이딴식으로 생성한다.  EPHEMERAL_SEQUENTIAL를 쓸수도 있지만 이러면 child node가 UUID로 생성해서 알아먹기 어렵다.


이렇게 해서. 만든 Listener와 테스트용 Client를 테스트 해봤다.

Listener는 다음과 같이 3개 IP로 다 접속하게 했다. 이러면 121이 죽어있어도 알아서 접속한다.
<주키퍼 서버 IP 2개이상 넣은 상황>


3개 서버중 하나는 죽여놓고 2개가지고 테스트를 했다.

client 1 : 접속 192.168.1.50 생성노드 192.168.1.50
client 2 : 접속 192.168.1.120 생성노드 192.168.1.120

Client 순서 : 
1. client 1접속 
2. client 2 접속
3. client 1 192.168.1.50노드의 데이터 변경
4. client 2 192.168.1.50노드의 데이터 변경
5. client 1 하위 노드 전체 조회
6. client 2 하위 노드 전체 조회
7. client 1 종료
8. client 2 종료

Client 순서 : 
1. 리스너 등록
2. remove 일경우 하위 노드 전체 조회


<리스너 측 로그>

보시다시피 노드가 등록되고 변경되고 삭제되는걸 확인했다. 특히 Remove시에 [Watch]에서 나오지 않은걸 봐서
client1이 생성한 192.168.1.50노드도 사라짐을 확인했다. 이후 client2가 종료되며 120노드도 사라진 것을 확인했다.

<client 측 노드>

client측을 보면 순서대로 생성 업데이트 조회 삭제를 했고, 192.168.1.50서버로 붙든 192.168.1.120서버로 붙든
아무상관 없이 노드들이 업데이트 종료 등이 되는것을 확인했다.


maven 세팅을 보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.egloos.scblood.demo</groupId>
  <artifactId>zookeeper</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>zookeeper</name>
  <url>http://maven.apache.org</url>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>2.12.0</version>    
    </dependency>
  </dependencies>
</project>
 
cs

위에 curator를 넣어주면 됨.

그담에 리스너 풀 소스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package com.egloos.scblood.demo.zookeeper.test;
 
import java.util.Arrays;
import java.util.List;
 
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.utils.CloseableUtils;
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.CreateMode;
 
import com.egloos.scblood.demo.zookeeper.ThreadTemp;
 
public class ServerListener {
    
    CuratorFramework client =null;
    public ServerListener() {
        addListener(getServerList());
        
    }
    
    private void addListener(List<ServerInfoVo> serverInfo){
        StringBuffer ipInfo = new StringBuffer();
        serverInfo.stream().forEach(s -> {
            ipInfo.append(s.getIp() + ":" + s.getPort() + ",");
        });
 
        client = getCuratorClient(ipInfo.substring(0, ipInfo.length() - 1),1000,3);
        client.start();
        
        TreeCache treeCache =null;
        try{
            /*
             * connection 시도 하고 실패시.
             */
            if(!client.getZookeeperClient().blockUntilConnectedOrTimedOut()){
                   CloseableUtils.closeQuietly(client); //접근 안되는거
                   doLogMsg("[Listener] Connection failed");
                  
                   return;
            }
            
            //삭제하는거
//            client.delete().deletingChildrenIfNeeded().forPath("/recovery");
            /*
             * recovery 작업 root node가 없으면 생성
             */
            if (client.checkExists().forPath("/recovery"== null) {
                client.create().creatingParentsIfNeeded().forPath("/recovery""recovery".getBytes());
//                client.create().creatingParentsIfNeeded().withProtection().forPath("/recovery", "recovery".getBytes());
                 doLogMsg("[Listener] Root node created");
            }
            
            treeCache = new TreeCache(client, "/recovery");
            treeCache.start();
            treeCache.getListenable().addListener(getCacheListener(treeCache));
            new ThreadTemp();            
        }catch(Exception e){
            e.printStackTrace();
            CloseableUtils.closeQuietly(treeCache);
            CloseableUtils.closeQuietly(client); 
        }
      
    }
    
    private List<ServerInfoVo> getServerList(){
        
        List<ServerInfoVo> list =Arrays.asList(
                  new ServerInfoVo("192.168.1.50"2181),
                  new ServerInfoVo("192.168.1.120"2181),
                  new ServerInfoVo("192.168.1.121"2181)
                  );
        return list;
    }
        
    
    private CuratorFramework getCuratorClient(String serverInfo, int timeout, int retryCnt){
        /*
         * ip:port,ip:port... 접근시도
         * 1초 3번 연결 재시도 
         * 연결,세션 timeout 3초
         * 요건 튜토리얼에 있던거
         * CuratorFramework client = CuratorFrameworkFactory.newClient(ip+":2181", new RetryUntilElapsed(3000, 1000)); 
         */
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(serverInfo)
                .retryPolicy(new ExponentialBackoffRetry(timeout, retryCnt)).connectionTimeoutMs(3000).sessionTimeoutMs(3000)
                .build();
        
        return client;
    }
 
    
    
    private void getCuratorInfo() {
        /*
         * 전체 내부 내용 다 뽑아보는거.
         */
        List<String> key;
        try {
            if(client !=null){
                key = client.getChildren().watched().forPath("/recovery");                
                for (String string : key) {
                    String val = new String(client.getData().forPath("/recovery/" + string));
                    doLogMsg("[Watch][%s][%s]", string, val);
                }                
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    private void doNodeMsgRecieve(NodeInfoVo info){
        
        switch (info.getNodeType()) {
            case NODE_ADDED: {
                doLogMsg("[Node Add][%s][%s]",info.getNodePath(),info.getNodeValue());
                break;
            }
            case NODE_REMOVED: {
                doLogMsg("[Node Remove][%s][%s]",info.getNodePath(),info.getNodeValue());
                getCuratorInfo();
                break;
            }
            case NODE_UPDATED: {
                doLogMsg("[Node Update][%s][%s]",info.getNodePath(),info.getNodeValue());
                break;                
            }
            default:
                doLogMsg("[%s]",info.getNodeType().name());
                
        }
        
        
    }
    
    private TreeCacheListener getCacheListener(TreeCache cache) {
        TreeCacheListener listener = new TreeCacheListener() {
            public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                doNodeMsgRecieve(
                        new NodeInfoVo(event.getType(),
                                        ZKPaths.getNodeFromPath(event.getData().getPath()),
                                        new String(event.getData().getData()))
                );
            }
        };
        return listener;
    }
    
    private void doLogMsg(String logMsg, String ... msgs){
        System.out.println(String.format(logMsg, msgs));
    }
    
 
    public static void main(String[] args) throws Exception{
        new ServerListener();
    }
}
 
cs



다음 테스트 client 소스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package com.egloos.scblood.demo.zookeeper.test;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
 
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryUntilElapsed;
import org.apache.curator.utils.CloseableUtils;
import org.apache.zookeeper.CreateMode;
 
 
public class ClientTwoCrud {
    
    
    public void init() throws Exception{
        CuratorFramework client1 = CuratorFrameworkFactory.newClient("192.168.1.50:2181"new RetryUntilElapsed(30001000));;
        CuratorFramework client2 = CuratorFrameworkFactory.newClient("192.168.1.120:2181"new RetryUntilElapsed(30001000));;
        boolean isCreate1 = false;
        boolean isCreate2 = false;
        
        isCreate1= create(client1,"192.168.1.50");
        doLogMsg("[%s] create [%b]","192.168.1.50",""+isCreate1);
        //가독성
        TimeUnit.SECONDS.sleep(3);
        isCreate2 = create(client2,"192.168.1.120");
        doLogMsg("[%s] create [%b]","192.168.1.120",""+isCreate2);
        TimeUnit.SECONDS.sleep(3);
        
        boolean tmp = update(client1,"/recovery/192.168.1.50","running");
        doLogMsg("[%s] update [%b]","192.168.1.50",""+tmp);
        TimeUnit.SECONDS.sleep(3);
        tmp = update(client2,"/recovery/192.168.1.50","complete");
        doLogMsg("[%s] update [%b]","192.168.1.120",""+tmp);
        TimeUnit.SECONDS.sleep(3);
        
        read(client1);
        TimeUnit.SECONDS.sleep(3);
        read(client2);
        TimeUnit.SECONDS.sleep(3);
        CloseableUtils.closeQuietly(client1); 
        TimeUnit.SECONDS.sleep(3);
        CloseableUtils.closeQuietly(client2);
    }
    
    public void initLab() throws Exception{
        
        CuratorFramework client1 = getCuratorClient("192.168.1.51:2181",1000,3);
        CuratorFramework client2 = CuratorFrameworkFactory.newClient("192.168.1.120:2181"new RetryUntilElapsed(30001000));;
        boolean isCreate1 = false;
        boolean isCreate2 = false;
        
        
        Optional<Boolean> result = Optional.of(isCreate1 = create(client1,"192.168.1.50"));
        result.filter(b -> b).ifPresent(b -> doLogMsg("[%s] create [%b]","192.168.1.50",""+b));
        TimeUnit.SECONDS.sleep(3);
        
        result = Optional.of(isCreate2 = create(client2,"192.168.1.120"));
        result.filter(b -> b).ifPresent(b -> doLogMsg("[%s] create [%b]","192.168.1.120",""+b));
        TimeUnit.SECONDS.sleep(3);
        
        
        result = Optional.of(isCreate1);
        result.filter(b -> b).ifPresent(b -> {boolean tmp = update(client1,"/recovery/192.168.1.50","running");
                                             doLogMsg("[%s] update [%b]","192.168.1.50",""+tmp);});
        TimeUnit.SECONDS.sleep(3);
        
        result = Optional.of(isCreate2);
        result.filter(b -> b).ifPresent(b -> {boolean tmp = update(client2,"/recovery/192.168.1.50","complete");
                                              doLogMsg("[%s] update [%b]","192.168.1.120",""+tmp);});
        TimeUnit.SECONDS.sleep(3);
        
        read(client1);
        TimeUnit.SECONDS.sleep(3);
        read(client2);
        TimeUnit.SECONDS.sleep(3);
        
        CloseableUtils.closeQuietly(client1); 
        TimeUnit.SECONDS.sleep(3);
        CloseableUtils.closeQuietly(client2);
    }
    
    
    
    public ClientTwoCrud() throws Exception{
        init();
    }
    
    private void read(CuratorFramework client) {
        List<String> key;
        try {
            key = client.getChildren().watched().forPath("/recovery");
            doLogMsg("---------------");
            for (String string : key) {
                String val = new String(client.getData().forPath("/recovery/" + string));
                doLogMsg("[Watch][%s][%s]",string,val);                
            }
            doLogMsg("---------------");
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
         
    
    
    private boolean create(CuratorFramework client, String serverInfo)  {
        client.start();
//        client.blockUntilConnected();
        try{
        if(!client.getZookeeperClient().blockUntilConnectedOrTimedOut()){
               CloseableUtils.closeQuietly(client); //접근 안되는거
               doLogMsg("[%s] Connection failed",serverInfo);
               return false;
        }
        
        if (client.checkExists().forPath("/recovery"== null) {
            client.create().creatingParentsIfNeeded().forPath("/recovery""recovery".getBytes());
        }
        if (client.checkExists().forPath("/recovery/" + serverInfo) == null) {
            client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/recovery/" + serverInfo,    "init".getBytes());
        }
        }catch(Exception e){
            e.printStackTrace();
            CloseableUtils.closeQuietly(client); 
            return false;
        }
        
        return true;
    }
    
    private boolean update(CuratorFramework client, String path,String msg){
        try {
            client.setData().forPath(path,msg.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
        return false;
    }
    
 
    
    public static void main(String[] args) throws Exception{
        new ClientTwoCrud();
    }
    
    private void doLogMsg(String logMsg, String ... msgs){
        System.out.println(String.format(logMsg, msgs));
    }
    
 
    private CuratorFramework getCuratorClient(String serverInfo, int timeout, int retryCnt){
        /*
         * ip:port,ip:port... 접근시도
         * 1초 3번 연결 재시도 
         * 연결,세션 timeout 3초
         * 요건 튜토리얼에 있던거
         * CuratorFramework client = CuratorFrameworkFactory.newClient(ip+":2181", new RetryUntilElapsed(3000, 1000)); 
         */
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(serverInfo)
                .retryPolicy(new ExponentialBackoffRetry(timeout, retryCnt)).connectionTimeoutMs(3000).sessionTimeoutMs(3000)
                .build();
        
        return client;
    }
}
 
cs







       기타 각종 스택오버플로의 페이지
       zookeeper
       샘플 깃허브

[책]오버 더 초이스 봤던거


오디오 북이 나왔길래 지금 살포시 읽어보는 중. 읽기는 무슨 듣고있음.
사실 얌전히 앉아서 뭘 할 시간이 집에선 없어서 출퇴근이나 간간히 듣고있는데, 무료공개 구간까진 사실 예전에 글로 읽었단 말이지.
근데 오디오로 듣는건 또 다르구만. 브금이 보조가 돼서 얌전히 집중해서 보지 않는 이상 잘 이입되지 않는 긴박감등등
감정이입이 잘 되는 편. 책으로 읽으면 보통 2~3시간안에 끝나는데 이건 한 20시간 분량이니 좀 더 오래걸리긴 한데, 이동중에 들을수 있어 좋긴 함. 

아주 흥미진진한 부분까진 들었는데 여윽시나 이영도다 싶은 느낌이 드는구만.



슬슬 준비할 JDK 8 람다 및 akka 및 Scala 흔한 전산쟁이의 삽질일기

https://github.com/Kevin-Lee/modern-java-untold

http://www.hanbit.co.kr/store/books/look.php?p_code=E3400029901

http://javacan.tistory.com/entry/akka-1-start
http://hamait.tistory.com/653

https://docs.scala-lang.org/ko/tutorials/scala-for-java-programmers.html

http://scblood.egloos.com/4972242

Optional

뭐여 모르는사이에 JDK10나왔네. 흔한 전산쟁이의 삽질일기


var 지원

var list = new ArrayList<String>(); 
ArrayList<String> var stream = list.stream(); 

var numbers = List.of(1, 2, 3, 4, 5);

이런것도 되네..

그담에 jdk 9에 나온 jshell이란게 있는데 쉘스크립트처럼 쓸수있는거. 
당연히 람다식은 말할것도 없고..

CG모듈이 좀 이쁘게 바뀜.

Java 9에서 default Garbage Collector인 G1은 full GC를 피하도록 설계되었지만, concurrent GC에서 충분한 young area를 확보하지 못하면 full GC가 발생합니다. 
기존 G1에서 full GC를 수행할 때 싱글 쓰레드 방식으로 동작하는 mark-sweep-compact 알고리즘을 사용하였습니다. 
G1 이전의 default 였던 parallel collector 처럼 G1에서도 full GC를 병렬화 시켜 G1의 최악의 케이스에서 지연 시간을 개선시켰습니다.

mark-sweep-compact 알고리즘을 병렬로 수행하도록 변경되었으며, 이 때 Young 과 Mixed GC와 동일한 쓰레드 수를 이용힙니다.
-XX:ParallelGCThreads 옵션을 이용해 쓰레드 수를 조절할 수 있으며, 이 옵션을 수정하면 Young 과 Mixed GC에도 변경사항이 적용됩니다.
라고 바뀜.


또한 stop the world 회피용 뭔가 작업을 좀 함.

JVM safepoint는 Stop the World를 의미합니다. 
Thread-Local Handshake는 이런 safepoint가 발생하는 지점들을 줄이기 위한 프로젝트입니다. 
모든 쓰레드를 동시에 멈춰야 했던 기존과 달리 쓰레드를 개별로 멈출 수 있게 되었고, VM safepoint를 수행하지 않고도 개별 Thread에서 콜백을 실행할 수 있습니다.

라고 하네


자바 HEAP을 NVDIMM에 세팅가능하게 됨.

JVM heap 영역을 NVDIMM(비휘발성 NAND 플래시 메모리) 혹은 사용자 지정과 같은 대체 메모리 장치에 할당할 수 있게됩니다. 
(이제 정전 걱정은 할 필요 없는 것일까요?) 이 기능은 새로 추가된 옵션인 -XX:AllocateHeapAt=<path>를 이용해 사용할 수 있습니다.

별로 쓸일은 없을듯. 


뭐 이정도인데 9가 뭐바꼈는지 아직 못봐서 일단 10에 내부위주로 가고 var 추가된건 좋네.



자바 9
고정 픽 가능
List immutableList = List.of();
List immutableList = List.of(“one”, “two”, “thress”);
Map immutableMap = Map.of(1, "one", 2, "two");


필요한 라이브러리나 패키지만 로딩 가능(!!!)
// Java 코드 최상위에 module-info.java 파일을 만들고, 아래와 같이 사용함
module java.sql {
    requires public java.logging;
    requires public java.xml;
    exports java.sql;
    exports javax.sql;
    exports javax.transaction.xa;
}

http://openjdk.java.net/projects/jigsaw/quick-start
오픈이나 오라클이나 어차피 오라클이 더 큰 패키지라..

프로세스 API가 개선되었다고 함.

ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();
Optional<String[]> args = procInfo.arguments();
Optional<String> cmd =  procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();
// Destroying Processes
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
    assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});


TRY CATCH 변경

void tryWithResourcesByJava7() throws IOException {
    BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
    try (BufferedReader reader2 = reader1) {
        // do something
    }
}
// final or effectively final이 적용되어 reader 참조를 사용할 수 있음
void tryWithResourcesByJava9() throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
try (reader) {
        // do something
    }
}

밖에서 해놓고 걍 따로 정리하네.


Interface에서 private가능(!!!)

interface NewInterface {
    
    private static String staticPrivate() {
        return "static private";
    }
    privat


HTTP2 클라이언트 라는게 생김

동기/비동기 지원가능 
 // 동기 호출
HttpResponse response = HttpRequest
               .create(new URI("http://www.ocado.com"))
               .body(noBody())
               .GET().send();
int responseCode = response.responseCode();
String responseBody = response.body(asString());
System.out.println(responseBody);
// 비동기 호출
HttpRequest request = HttpRequest
               .create(new URI("http://www.ocado.com"))
               .body(noBody())
               .GET();
CompletableFuture<HttpResponse> future = request.sendAsync();
Thread.sleep(10);
if (!future.isDone()) {
    future.cancel(true);
    System.err.println("timeout");
    return;
}
HttpResponse response = future.get();




기타

/ 50초후에 새로운 Executor 생성
Executor executor = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);




아놔 9가 더럽게 기능은 많이 바꼈네..



OECD 한국 보고서 똘끼넘치는 주식

요오기 읽다가 발견한건데.


OECD 2018 한국 PDF -> 한국 경제보고서 참고했다고 함








이래저래 경제동향 알아보는데는 괜츈한듯.

PDF가 더 자세함. 


요새 정전이 많다는데.. 뭐임마 다툴래염?

요새 정전이 많음.. 예전에 살 집 구할라고 이것저것 알아볼 때도 이게 중요했는데. 이 문제는 구형 아파트, 즉
은마아파트나 1기 신도시 아파트에서 발생하는 쪽에 속함. 이게 뭐가 문제냐면. 
가구당 전기 공급량을 적게 설계해놓고 너무 많이 쓰니 아파트내 변압기가 죽어버리는 문제인 거시다.

뭐 대충 여름마다 왜 기사가 자꾸나는가 보면 대충알거같긴한데. 

실제 건물의 건축일자를 봐야지


오래된 것이 많은데.. 실제 이 아파트들의 변압기가 후달리는것으로 추정된다.
그렇다고 하면 얼마나 후달리는지 봐야 하는데. 보통은 한전과 계약한 전기량을 추정해보면 되는데,
보통 이를 수전용량이라고 한다.
그럼 이 수전용량을 가구수로 나누면 되는데, 이건 어디서 보느냐. 공동주택관리정보시스템 에서 보면 된다. 관리비만 보는게 아닌 거시다.

우리집을 예시로 들면,

432세대에 2300kw인 것. 그러면 단순 계산하면 5.324074074074074 즉. 5.3kw를 한 가구당 쓸수 있는 것.
너무적은거 아니냐 라고 할 수도있는데 그럼 저 아파트를 가서 보자.

요래요래 클릭하면 정보가 나오는데 기본정보를 보면

자 582세대임. 
그러면 옆에 관리시설 정보를 보자.

수전용량이 1150kw이다. 단순계산을 하면 1150/582 = 1.975945017182131 즉. 1.97kw를 쓴다. 우리집 1/3밖에 안됨.

그러면 문제의 은마 아파트를 보자.

4424세대!!

8800kw!! 그래서 8800/4424하면.  1.989150090415913 ... 1.98kw. 약간 높긴한데 비슷비슷. 

이게 어떤 상황이냐면

실제 우리집 에어컨 용량보면
1.85 kw정도 즉 1800w 정도라는것.
근데 요새 덥잖아?  모든가구가 에어컨을 빵빵하게 틀면 무슨일이 벌어지냐.. 변압기가 터지는거지.
근데 변압기 교체를 하면 되는거 아니냐 하는데 그게 가격이...

정리를 해서 교체를 한다고 해보자. 몰드변압기는 온도 관리를 잘해서 규정의 두배까지 버틴다고 하니 그걸로 교체하기도 한다고 하지만..


500짜리를 550으로 올리니까 373-> 410.3 kw로 변경 사업이 대충 2억이네.
그러니까 일산 1150kw를 바꾸는데 대충 1150kva로 교체한다고 하면 대충 1150/400 하면 대충 3나오니. 6억정도 나오겠군.
물론 +- 몇억은 더들어가겠지. 내가 전문가가 아니라서.. 설마 풀교체 하겠나.


이걸로 모르겠는데 물가는 얼마인가..



그럼 증설한다고 봤을때
위에 일산아파트가 1746kw가 되어야 가구당 3kw가 되니 1150kw짜리니까 596kw가 더 필요하다. 
그럼 596/0.746하면 798.9276139410188 대충 800kva네. 순수 가격으로 2억이니 공사비까지 하면 한참 더나오니 
대충 3~4억으로 치자. 실제는 훨 더나오겠지만.

그러면  대충 3억으로 하고 /582하면 가구당 5백15네. 6억으로 하면 천이고.
50만하더라도 부담이 상당한데 가구당 몇백단위로 올라가네.. 빡세긴 하구만. 게다가 1기 신도시는 변압기 노후화도 생각해야지.

그렇다면 대규모를 보면. 8800짜리를 교체하는데 400이 2억이니 22배라 EE!  44억. 44억 /4400세대. 어? 일인당 100만원! 더싸네.
그리고 증설 하면 13200이니 대충 5천이네. 2500 2개가 10억이니 인건비 몇억 하면 대충 15억으로 잡고 일인당 340만원. 음.. 싸다!

물론 이게 엉터리계산인건 알고있는데 일단 억단위로 돈이 들어가는거와 가구당 부담률이 백단위에서 천단위라는거가 있는거고.
아무래도 부담이 될수밖에 없네.

결론은 새아파트 들어가는게 낫다. 라는거구만.








에어컨 청소일지[Q9000] 뭐임마 다툴래염?

어제 뜬금포로 거실 에어컨에서 곰팡이 냄새가 나서 틀 수가 없다고 연락이 옴.
그래서 생각해보니, 요새 에어컨을 하도 틀어대니 습기가 많이 차서 곰팡이가 낀게 아닌가 추정.
일단 방안 에어컨으로 버티고있긴 한데 그렇다고 업자를 부르면 돈은 둘째치고 요새같이 더운날 언제올지도 모르고...
그래서 걍 닦는거 뜯는법을 찾기 시작함.

모델은 Q9000. 2017에 산거. 16+24였나 AF17M6473WZK 대충 이거랑 비슷해서 좀 뒤져봄.


그래서 뒤져보니 전체 분해가 아니면 그다지 큰 문제는 없겠다 싶어 작업을 시작함.

누구나 쉽게 뜯는 아래쪽을 당겨서 뽑는다. 저기에 리모콘 넣는대도 있으니 누구나 다 한번씩 뜯어봤을듯.

그담이 문젠데. 링크하고 생긴게 좀 다르더라. 어쨋든 위쪽은 나사 다 풀고 아래 PUSH라는게 있음 거길 눌러야됨.


이걸 당겨서 풀어놓고 해야하는데 손 놓으면 안될수도 있긴 함. 일단 다음단계를 가면 대충 다음과 같다

PUSH쪽을 누른상태로 아래로 누르면 약간 눌려지는데 그러면 위쪽 경계선부분이 빠진다. 그러면서 당기면 쭉 빠져나옴. 
도로 넣을때도 반대로 누른상태에서 넣으면 됨. 
느낌이 창틀끼우거나 뺄때 누르거나 올려서 빼는 느낌으로 하면 됨.

그러면 저기 기판박스가 나오는데 왼쪽 2개나사 오른쪽 하나 나사 풀고 걸려있는 박스 뚜껑을 뺀다.
어차피 위쪽 바람나오는데를 뜯으려면 연결된 선을 떼야 하기 때문. 근데 이 에어컨은 꽂는 사이즈가 다 달라서
왠만하면 해멜일 없으니 정 그러면 미리 사진찍어놓음 됨.

그리고 부품중 위에서 직접적으로 내려오는 회색 2개만 뽑으면 됨. 나는 멋모르고 전부 다 뽑았다가 다 뜯고 난다음 도로 끼움.
즉 위쪽에서 내려오는 선 두개만 뜯는다. 만 핵심. 만일 다른모델은 안그러면 선이 위에서 내려오는거만 뜯으면 됨.

요거랑
요거


그리고 어느선이 어디들어가는지 사진을 찍어놓던지 아니면 잘 기억해놓으면 됨. 어차피 저기 선 꽂는게 크기가 다 달라서
맞지도 않음.

그담에 사다리를 가져와서 꼭대기로 올라가면 다음과 같음.

이런식으로 나사를 전부 풀고 껍데기를 살짝 떼내면...

살짝 옆으로 치워버리고 


선이 연결된 상태로 뜯을수 있다. 그리고 나사를 풀고 기판에 연결된 케이블은 뽑지않아도 된다. 
상부를 뜯을때 바구니 들듯이 회색 테두리를 들면 같이 빠져나오기 때문. 나는 멋모르고 저거 다 풀었다가 뜯어낸 다음 
도로 끼움. 위쪽을 들어낼 여유가 없을거같으면 저 선을 뽑고 나중에 꺼낸다음 도로 끼워도 됨.

실제로 뚜껑만 따로 빠진다는 증거. 앞판과 같이 들어내도 되긴하지만 처음시도하는거라면 분해하고 하는게 좋다. 
떨어뜨렸다가 망가지면 어휴...


그리고 위쪽으로 밀어올린다 생각하고 윗판을 당기면 덜컹하고 빠진다. 나중에 끼울때도 저게 잘 끼워졌나 봐야됨.
그리고 뽑아낸다.

그럼 이렇게 빠짐 적당히 나사풀고 닦으면 됨. 여기도 때가 많이 있었음. 산지 1년인데 시꺼먼 때.. 그러니 아마 
곰팡이일듯. 여기 붙은거 닦고 알콜뿌리고 말렸음. 

여기서부터 중요한데 저 빨간색에 전기가 쌔게 통하기 때문에 재수없음 감전됨. 그러니 전기 끄고 작업시작.
그리고 저 노란색은 4군데를 누르고 반시계로당겨야 함. 

저 빨간데를 눌러서 반시계로 돌려야됨.

실제로 어찌 생겼냐면..



저렇게 되어있어서 누른상태로 돌려야 하는데. 나는 하나씩 누르고 약간 힘준상태로 다른데 누르고 식으로 처리함.

그리고 닦아본 결과 저리 더러움. 실제는 더 더러웠는데 한번 닦고 두번째 닦을때 찍은거임. 그리고 알콜뿌려서 닦아야 잘닦임.
거의 시꺼먼 곰팡이가 가득있었는듯. 그리고 안쪽도 소독용 알콜로 쫙쫙 뿌리고 약간 말림.


그리고 역순으로 조립.



다 조립하고 전원넣고 한동안 알콜을 말리기위해 계속 트는데... 온도 보소.. 

삽질포함 소요시간 1시간 30분. 원인은 작업용 벨트가 없어서 드릴들었다 핸드폰들었다 나사들었다 하는게 많아서 시간낭비와
아까처럼 삽질이 포함되어있기때문.
게다가 풀분해가 아니라서 40분 이내로 다음은 땡길수 있을듯.


1 2 3 4 5 6 7 8 9 10 다음