2020년 11월 12일 목요일

Apache Nifi [2] - Queued 설정


Queued 우측클릭->구성설정 버튼을 클릭하면 아래와 같이
설정할 수 있는 창이나온다.





FlowFile Expiration

FlowFile Expiration은 특정기간에 쌓인 데이터들 중 처리할 수 없는 데이터를 자동으로 제거할 수 있는 개념이다. 예를 들어 큐의 데이터 볼륨이 초과할 것으로 예상됬을 때, 유통기한을 우선 순위자와 함께 사용하여 우선 순위가 가장 높은 데이터를 먼저 처리한 후 일정 기간(예: 1시간) 내에 처리할 수 없는 것은 모두 삭제할 수 있다. 

만료 기간은 데이터가 NiFi 인스턴스에 들어간 시간을 기준으로 한다. 즉, 특정 연결의 FlowFile Expiration가 '1시간'으로 설정되어 있고 NiFi 인스턴스에 1시간 동안 있었던 파일이 해당 연결에 도달하면 만료된다. 

기본값 0초는 데이터가 절대 만료되지 않음을 나타낸다. '0초' 이외의 파일 만료를 설정하면 연결 라벨에 작은 시계 아이콘이 나타나기 때문에 흐름을 한눈에 볼 수 있다.







Back pressure

NiFi는 Back Pressure를 위한 두 가지 구성 요소를 제공한다. 임계값은 원본 데이터소스가 대기열에 존재할 수 있는 데이터 양을 나타낸다. 이를 통해 시스템이 데이터 오버런을 방지할 수 있다. 

제공되는 첫 번째 옵션은 "Back pressure object threshold"이다. 이것은 Back pressure를 적용하기 전에 대기열에 포함될 수 있는 FlowFiles 수를 나타낸다. 

두 번째 구성 옵션은 "Back pressure 데이터 크기 임계값"이다. 이것은 Back pressure를 적용하기 전에 대기열에 넣어야 하는 최대 데이터 양(크기)을 지정한다. (바이트의 경우 B, 킬로바이트의 경우 KB, 메가바이트의 경우 MB, 기가바이트의 경우 GB 또는 테라바이트의 경우 TB)

기본적으로 새로 추가된 각 연결dml  기본 Back pressure설정 값은 임계값 10,000개와 데이터 크기 임계값 1GB이다. 

활성화되면 연결 라벨에 작은 진행 표시줄이 나타나므로 캔버스의 흐름을 볼 때 이를 한눈에 볼 수 있다. 대기열 백분율에 따라 진행률 표시줄의 색 변경: 녹색(0~60%), 황색(61~85%), 적색(86~100%) 등이었다.




Load Balancing (부하 분산 전략)

NiFi는 데이터의 흐름을 클러스터 노드 전체에 분산시키기 위해 다음과 같은 로드 밸런싱 전략을 제공한다.
























Do not load balance : 클러스터의 노드 간에 FlowFiles를 로드 밸런싱하지않는다(기본값).

Partition by attribute : 사용자 지정 FlowFile 특성의 값에 따라 데이터를 보낼 노드를 결정한다. 속성 값이 동일한 모든 FlowFiles는 클러스터의 동일한 노드로 전송된다. 대상 노드가 클러스터에서 분리되거나 통신할 수 없는 경우, 노드가 다시 사용 가능해질 때까지 기다린다. 

Round robin : FlowFiles는 라운드 로빈 방식으로 클러스터의 노드에 배포된다. 노드가 클러스터에서 분리되거나 노드와 통신할 수 없는 경우, 해당 노드에 대기 중인 데이터는 자동으로 다른 노드로 재분산된다. 노드가 클러스터의 다른 노드처럼 데이터를 빠르게 수신할 수 없는 경우, 클러스터 전체의 데이터 배포 처리량을 극대화하기 위해 노드를 하나 이상 반복하여 건너뛸 수도 있다.

Single node : 모든 FlowFiles는 클러스터의 단일 노드로 전송된다. 어떤 노드로 전송되는지는 구성할 수 없다. 노드가 클러스터에서 분리되거나 노드와 통신할 수 없는 경우, 해당 노드에 대해 대기 중인 데이터는 노드를 다시 사용할 수 있을 때까지 대기열에 남아 있게 된다.



연결에 대해 로드 밸런싱 전략을 실행한 경우 연결에 로드 밸런싱 표시기(Load Balance Icon)가 나타난다.












Available Prioritizers (우선 순위 지정)

첫번째 이미지 탭의 오른쪽은 더 높은 우선순위 데이터가 먼저 처리되도록 대기열에서 데이터의 우선순위를 지정할 수 있는 기능을 제공한다. 우선순위 지정자를 위에서 아래로 끌 수 있다. 






참고 : https://nifi.apache.org/docs/nifi-docs/html/user-guide.html

Apache Zeppelin [5] - 인증 및 접근권한 설정


제플린의 인증은 shiro.ini파일로 설정한다.


sudo cp /usr/local/zeppelin/conf/shiro.ini.template /usr/local/zeppelin/conf/shiro.ini

sudo vi /usr/local/zeppelin/conf/shiro.ini

sudo /usr/local/zeppelin/bin/zeppelin-daemon.sh restart


재시작후 웹페이지에서 제플린메인을 접속하면,

기존 anonymous계정으로 로그인과 인터프리터, 설정등 페이지에 접근이 불가능하다.



[ Shiro.ini Config ]

설정파일은 main, users, roles, urls와 같이 4파트로 나뉘는데 

각 파트별 설정내용은 다음과 같다.


[main] :Realm과 같은 Security Managerd의 object와 properties가 정의

[users] : 사용자 계정과 관련된 properties가 정의

[roles] : 계정의 roles와 관련된 설정값

[urls] : URL 기반 보안에 사용


* Realm

사용자, 역할 및 권한과 같은 애플리케이션별 보안 데이터에 액세스할 수 있는 구성 요소다. Realmssms 애플리케이션별 데이터를 Shiro가 이해한 형식으로 변환하여 데이터 소스가 얼마나 많든, 애플리케이션별로 어떻게 존재하든 Shiro가 이해하기 쉬운 단일 프로그래밍 API를 제공할 수 있도록 한다.

Realms는 관계형 데이터베이스, LDAP 디렉토리, 파일 시스템 또는 기타 유사한 리소스와 같은 데이터 소스와 1 대 1의 상관관계를 가진다. Realms의 인터페이스의 구현은 데이터 소스별 API를 사용하여 JDBC, 파일 IO, 최대 절전 모드 또는 JPA와 같은 권한 부여 데이터(역할, 권한 등)의 Data Access API를 제공한다.

참조 : http://shiro.apache.org/realm.html




1. MAIN

Active Directory 

activeDirectoryRealm = org.apache.zeppelin.realm.ActiveDirectoryGroupRealm
activeDirectoryRealm.systemUsername = userNameA
activeDirectoryRealm.systemPassword = passwordA
activeDirectoryRealm.hadoopSecurityCredentialPath = jceks://zeppelin/conf/zeppelin.jceks
activeDirectoryRealm.searchBase = CN=Users,DC=SOME_GROUP,DC=COMPANY,DC=COM
activeDirectoryRealm.url = ldap://ldap.test.com:389
activeDirectoryRealm.groupRolesMap = "CN=aGroupName,DC=COMPANY,DC=COM":"group1"
activeDirectoryRealm.authorizationCachingEnabled = false
activeDirectoryRealm.principalSuffix = @corp.company.net


LDAP

LDAP Realms를 구성하기 위해 가장 사용하기 쉬운 것은 LdapGroupRealm이다.

LDAP 그룹을 사용자에 매핑하고 사용자 그룹에 대한 권한 부여를 위한Realms 설정은 다음과 같다.

ldapRealm = org.apache.zeppelin.realm.LdapGroupRealm
# search base for ldap groups (only relevant for LdapGroupRealm):
ldapRealm.contextFactory.environment[ldap.searchBase] = dc=COMPANY,dc=COM
ldapRealm.contextFactory.url = ldap://ldap.test.com:389
ldapRealm.userDnTemplate = uid={0},ou=Users,dc=COMPANY,dc=COM
ldapRealm.contextFactory.authenticationMechanism = simple


PAM

PAM 인증 지원을 통해 제플린이 실행 중인 호스트에서 기존 인증 모듈을 재사용할 수 있다. 일반적인 시스템 모듈에서는 /etc/pam.d/에 따라 sshd, passwd 등의 서비스별로 구성된다. 이러한 서비스 중 하나를 재사용하거나 Zeppelin을 위해 자신만의 서비스를 만들 수 있다.

[main]
 pamRealm=org.apache.zeppelin.realm.PamRealm
 pamRealm.service=sshd



Secure Cookie for Zeppelin 세션

세션 쿠키에서 HttpOnly 플래그를 설정하도록 제플린을 구성할 수 있다. 이 구성으로 제플린 쿠키는 클라이언트 쪽 스크립트를 통해 액세스할 수 없으므로 대부분의 XSS(Cross-Site Scripting) 공격을 차단한다.

cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = JSESSIONID
cookie.secure = true
cookie.httpOnly = true
sessionManager.sessionIdCookie = $cookie

그 외에 ZeppelinHub, Knox SSo등의 Realm관련 설정을 할 수 있다.

참고 : https://zeppelin.apache.org/docs/0.8.0/setup/security/shiro_authentication.html#active-directory




2. USERS

Users 섹션에서는 정적 사용자 계정을 정의할 수 있다. 사용자 계정의 수가 매우 적거나 사용자 계정을 런타임에 동적으로 만들 필요가 없는 환경에서 유용하다.


위와 같이 설정포맷은 username = password, role1, role2 .... roleN 이다.

[users]

admin = 1234, admin

kail = pwd1, role1

jack = pwd2, role2, role3


users파트 암호를 일반 텍스트로 만들지 않으려면 해시 알고리즘(MD5, Sah1, Sah256 등)을 사용하여 암호화할 수 있다. 기본적으로 암호 문자열은 Hex 인코딩이며, Base64 인코딩으로도 구성할 수 있다.




3. ROLES

Roles파트의 예시는 아래와 같다.

[roles]
admin = *
hr = *
finance = *
group1 = *




4. URLS

기본적으로 user파트에 정의된 모든 사용자는 아파치 제플린의 인터프리터 설정, 인증 정보 및 구성 정보를 공유할 수 있다. 경우에 따라 사용 사례를 위해 이러한 정보페이지를 숨기고 싶을 수 있다. 

Shiro는 URL 기반 보안을 제공하므로 conf/shiro.ini에서 아래 줄에 주석을 달거나 압축을 해제하여 정보를 숨길 수 있다.


변경전

[urls]

/api/interpreter/** = authc, roles[admin]
/api/configurations/** = authc, roles[admin]
/api/credential/** = authc, roles[admin]


변경후

[urls]

/api/interpreter/** = roles[admin]
/api/configurations/** = roles[admin]
/api/credential/** = roles[admin]


위와 같이 설정하면 admin roles가 아닌 모든 계정은 Interpreter, Configuration, Credential 페이지 접근이 불가하다.















[ zeppelin permission ]

각 노트마다 접근권한을 지정해주어 해당노트의 crontab이나 쿼리, 대쉬보드 추가 삭제 등 유저마다 노트에 대한 권한을 달리 줄 수 있다.

아래 이미지와 같이 우측상단의 자물쇠 그림을 눌러 설정한다.









예를 들어 user1이 Note1을 Read만하고 쿼리실행이나 다른 작업을 못하게 하려면 Owners설정은 admin, Reader는 user1으로 설정한다.( Writers랑 Runners는 자동으로 Owners설정값을 따른다.)

또한 다른유저 user2는 Readers권한도 없으므로 로그인해도 해당 Note1이 보이지 않는다.


Readers권한이 있는 User가 다른 권한접근시 알림 메세지가 나온다.








결과적으로 제플린의 인증과 접근권한은 Shiro.ini파일의 users, roles, urls파트 설정과 자물쇠버튼의 Permission설정으로 어느 정도 가능하다. 그러나 유저가 많아 파생되는 그룹이 커지고 동적 유저또한 필요하다면 Realms manager 설정또한 추가되야 할 것이다.  


2020년 11월 10일 화요일

Hive [6] - Json데이터 컨트롤 (json to hive)


Hive에서 Json파일 컨트롤


1. get_json_object

hive 0.7.0 이하로는 아래와 같이 사용한다.










[ 쿼리문 ]

SELECT

    get_json_object(StudentsOneLine, '$.StudentDetails.FirstName'),

    get_json_object(StudentsOneLine, '$.StudentDetails.LastName')

FROM StudentsOneLine;




2. json_tuple 사용

{"memberId":817090,"campaigns":[{"id":"40718","amount":"10"},{"id":"40801","amount":"26"},{"id":"40584","amount":"0"},{"id":"40685","amount":"0"}],"eventTime":"1604847624784","createdAt":"2020-11-09:00:00:25"}

위와 같은 json파일이 있다고 하면 hive 0.7.0이상부터는 json_tuple함수를 이용하여 json데이터를 추출한다.


[ 쿼리문 ]

SELECT memberid, id, amount, eventtime

from tableName 

LATERAL VIEW JSON_TUPLE(campaigns) campaigns as id, amount;




3. Explode

그러나 데이터가 아래와 같이 String 타입이 아니고 Int타입 Json이라면

{"memberId":817090,"campaigns":[{"id":40718,"amount":10},{"id":40801,"amount":26},{"id":40584,"amount":0},{"id":40685,"amount":0}],"eventTime":1604847624784,"createdAt":"2020-11-09:00:00:25"}

아래와 같은 에러가 나타난다.

Error while compiling statement: FAILED: UDFArgumentException json_tuple()'s arguments have to be string type

그럴땐 Explode함수를 사용하여 Json을 추출한다.


[ 쿼리문 ]

SELECT memberid, ca.id, ca.amount, eventtime

from tablename

LATERAL VIEW EXPLODE(campaigns) campaigns as ca


[ 결과 ]








그외로, 

4. 사용자 지정 SerDe사용

Hive에서는 json, csv뿐 아니라 커스텀으로 만들어 SerDe를 사용할 수 있다.

참조 URL : https://web.archive.org/web/20190217104719/https://blogs.msdn.microsoft.com/bigdatasupport/2014/06/18/how-to-use-a-custom-json-serde-with-microsoft-azure-hdinsight/


5. 프로그래밍

Python, Java를 이용하여 Json파일을 컨트롤 한다.



참조 :

https://docs.microsoft.com/ko-kr/azure/hdinsight/hadoop/using-json-in-hive

2020년 11월 8일 일요일

Hive [5] - 조인 (Join)


테이블 간의 Join은 부하가 매우크므로 스키마설계시 Join을 하지 않도록 구성해야 한다.

하이브에서 조인 사용시 왼쪽에서 오른쪽 FROM절 순서로 쿼리가 실행되므로 일반적으로 가장 데이터가 큰 테이블을 맨 오른쪽(마지막)에 실행되도록 쿼리를 짠다. 


* HUE이용시 

  • Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask

와 같은 오류시 SET hive.auto.convert.join=false 로 설정



[ Join 명령문 ]

   table_reference JOIN table_factor [join_condition]
   | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference
   join_condition
   | table_reference LEFT SEMI JOIN table_reference join_condition
   | table_reference CROSS JOIN table_reference [join_condition]



[ Example 테이블 ]

직원테이블 (CUSTOMER)

+----+----------+-----+-----------+----------+ 
| ID | NAME     | AGE | ADDRESS   | SALARY   | 
+----+----------+-----+-----------+----------+ 
| 1  | Ramesh   | 32  | Ahmedabad | 2000.00  |  
| 2  | Khilan   | 25  | Delhi     | 1500.00  |  
| 3  | kaushik  | 23  | Kota      | 2000.00  | 
| 4  | Chaitali | 25  | Mumbai    | 6500.00  | 
| 5  | Hardik   | 27  | Bhopal    | 8500.00  | 
| 6  | Komal    | 22  | MP        | 4500.00  | 
| 7  | Muffy    | 24  | Indore    | 10000.00 | 
+----+----------+-----+-----------+----------+

주문테이블 (ORDERS)

+-----+---------------------+-------------+--------+ 
|OID  | DATE                | CUSTOMER_ID | AMOUNT | 
+-----+---------------------+-------------+--------+ 
| 102 | 2009-10-08 00:00:00 |           3 | 3000   | 
| 100 | 2009-10-08 00:00:00 |           3 | 1500   | 
| 101 | 2009-11-20 00:00:00 |           2 | 1560   | 
| 103 | 2008-05-20 00:00:00 |           4 | 2060   | 
+-----+---------------------+-------------+--------+



1. INNER JOIN [ 내부 조인 ]







RDBMS와 개념은 같지만 하이브는 동등조인(EQUI-JOIN)만을 제공한다.

( ON절에 = 만 사용)


[ 쿼리문 ]

SELECT c.id, c.name, c.age, o.amount

FROM customer JOIN orders o

ON c.id = o.customer_id

WHERE o.amount> 1500 AND o.amount< 3000;


SELECT c.id, c.name, c.age

FROM customer JOIN orders o

ON c.id = o.customer_id AND c.salary = o.amount

where c.name='khilan';


SELECT t1.var1, t1.var2, t2.var3

FROM table1 t1 JOIN table2 t2 ON t1.var1 = t2.var1

                     JOIN table3 t3 ON t1.var1 = t3.var1



[ 첫번째 쿼리문 결과 ]

+----+----------+-----+--------+ 
| ID | NAME     | AGE | AMOUNT | 
+----+----------+-----+--------+ 
| 2  | Khilan   | 25  | 1560   | 
| 4  | Chaitali | 25  | 2060   | 
+----+----------+-----+--------+



2. LEFT SEMI-JOIN











  • 오른쪽테이블에서 ON에 일치하는 레코드를 찾으면 더 이상 찾는 행동을 멈추고 왼쪽테이블의 데이터를 반환한다. 
  • 따라서 내부조인보다 빠르다.
  • 하이브는 RIGHT SEMI-JOIN은 지원하지 않는다.

[ 쿼리문 ]

SELECT t1.var1, t1.var2, t1.var3

FROM table1 t1 LEFT SEMI JOIN table2 t2

ON t1.var1 = t2.var1 AND t1.var2 = t2.var2;



3. LEFT(RIGHT) OUTER JOIN










  • Left Outer Join : Table1에 있는 모든 행과 Table2에 함께 있는 행을 얻는다.
  • Rigth Outer Join : Table2에 있는 모든 행과 Table1에 함께 있는 행을 얻는다.


[ 쿼리문 ]

SELECT c.id, c.name, o.amount, o.date

FROM customers c

LEFT OUTER JOIN orders o

ON c.id = o.customer_id;


[ 결과 ]

+----+----------+--------+---------------------+ 
| ID | NAME     | AMOUNT | DATE                | 
+----+----------+--------+---------------------+ 
| 1  | Ramesh   | NULL   | NULL                | 
| 2  | Khilan   | 1560   | 2009-11-20 00:00:00 | 
| 3  | kaushik  | 3000   | 2009-10-08 00:00:00 | 
| 3  | kaushik  | 1500   | 2009-10-08 00:00:00 | 
| 4  | Chaitali | 2060   | 2008-05-20 00:00:00 | 
| 5  | Hardik   | NULL   | NULL                | 
| 6  | Komal    | NULL   | NULL                | 
| 7  | Muffy    | NULL   | NULL                | 
+----+----------+--------+---------------------+



4. FULL OUTER JOIN 












  • left table과 right table의 합집합을 얻는다. left table에는 데이터가 있고 right table에는 없는 경우 null로 표현된다.


[ 쿼리문 ]

SELECT c.id, c.name, o.amount, o.date

FROM customers c

FULL OUTER JOIN ORDERS o

ON c.id = o.customer_id;


[ 결과 ]

+------+----------+--------+---------------------+ 
| ID   | NAME     | AMOUNT | DATE                | 
+------+----------+--------+---------------------+ 
| 1    | Ramesh   | NULL   | NULL                | 
| 2    | Khilan   | 1560   | 2009-11-20 00:00:00 | 
| 3    | kaushik  | 3000   | 2009-10-08 00:00:00 | 
| 3    | kaushik  | 1500   | 2009-10-08 00:00:00 | 
| 4    | Chaitali | 2060   | 2008-05-20 00:00:00 | 
| 5    | Hardik   | NULL   | NULL                | 
| 6    | Komal    | NULL   | NULL                |
| 7    | Muffy    | NULL   | NULL                |  
| 3    | kaushik  | 3000   | 2009-10-08 00:00:00 | 
| 3    | kaushik  | 1500   | 2009-10-08 00:00:00 | 
| 2    | Khilan   | 1560   | 2009-11-20 00:00:00 | 
| 4    | Chaitali | 2060   | 2008-05-20 00:00:00 | 
+------+----------+--------+---------------------+



5. UNION ALL

하이브 Join의 On절에서는 Or 조건의 사용을 할 수 없다. 그럴 때 UNION ALL절 이 쓰는데 예시는 아래와 같다.


  • 변경전

SELECT * 

FROM table1 t1 JOIN table2 t2

ON (t1.val1=t2.val1) or (t1.var2=t2.var2);


  • 변경후

SELECT * 

FROM table1 t1 JOIN table2 t2

ON t1.val1=t2.val1

UNION ALL

SELECT * 

FROM table1 t1 JOIN table2 t2

ON t1.var2=t2.var2;





참조 :

https://www.tutorialspoint.com/hive/hiveql_joins.htm


2020년 11월 5일 목요일

Apache Kafka [4] - 명령어

 

* 카프카 PATH로 cd하여 실행함을 가정한다.


실행중지

[ 카프카 실행 ]

./bin/kafka-server-start.sh ./config/server.properties --daemon


[ 카프카 중지 ]

./bin/kafka-server-stop.sh



토픽

[ 토픽생성 ]

./bin/kafka-topics.sh --create --zookeeper 172.123.123.111:2181, 172.123.123.222:2181, 172.123.123.333:2181 --replication-factor 3 --partitions 3 --topic kafka-topic-name

: 카프카 서버3대 (broker)에 복제를 3번하는 토픽을 만든다.


[ 토픽확인 ]

./bin/kafka-topics.sh --bootstrap-server kafkahost_IP:9092 --list

or

./bin/kafka-topics --zookeeper 172.123.123.111:2181 --topic kafka-topic-name --describe

or

./bin/kafka-topics.sh --list --zookeeper 172.123.123.111:2181


[ 지노드확인 ]

zookeeperPath/bin/zkCli.sh 

: 주키퍼접속

zk] ls /hadoop-kafka/brokers/ids 

: znode를 통해 확인



프로듀서/컨슈머

[ Producer messages 보내기 ]

./bin/kafka-console-producer.sh --broker-list 172.123.123.111:9092 --topic kafka-topic-name


[ Producer에 파일로 message 보내기 ]

./bin/kafka-console-producer.sh --broker-list 172.123.123.111:9092 --topic kafka-topic-name < /home/ubuntu/sample.json


[ Consume messages 받기 ]

./bin/kafka-console-consumer.sh --bootstrap-server 172.123.123.111:9092 --topic kafka-topic-name



컨슈머그룹

[ Consumer group 생성 ]

./bin/kafka-console-consumer.sh --bootstrap-server 172.123.123.111:9092 --topic kafka-topic-name --consumer-property group.id=kafka-group-id


[ Comsumer groupID 확인 ]

./bin/kafka-consumer-groups.sh --bootstrap-server 172.123.123.111:9092 --list


[ Comsumer group 삭제 ]

./bin/kafka-consumer-groups.sh --zookeeper 172.123.123.111:2181 --delete --group kafka-group-id


[ Consumer group상태 및 offset 확인 ]

./bin/kafka-consumer-groups.sh --bootstrap-server 172.123.123.111:9020 --group kafka-group-id --describe



설정

[ 로그 보관 주기설정 ]

./bin/kafka-topics.sh --zookeeper 172.123.123.111:2181 --alter --topic kafka-topic-name --config retention.ms=86400000 (초단위 10일)

: 카프카의 디스크 공간이 부족하다면 로그보관주기설정을 짧게하여 retention.ms값을 낮추는 것이다.


[ 로그 보관 주기변경확인 ]

./bin/kafka-topics.sh --zookeeper 172.123.123.111:2181 --describe --topic kafka-topic-name 

2020년 11월 2일 월요일

[Algorithm] 배열합계 ( Simple Array Sum )

 

Simple Array Sum


문제 ]

Sample Input

6
1 2 3 4 10 11

Sample Output

31

Explanation

We print the sum of the array's elements: .



제출 ]

import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.regex.*;

public class Solution {

    static int simpleArraySum(int[] ar) {
        int sum = 0;
        for(int i=0; i < ar.length; i++){
            sum += ar[i];
        }
        return sum;

    }

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

        int arCount = Integer.parseInt(scanner.nextLine().trim());
        int[] ar = new int[arCount];

        String[] arItems = scanner.nextLine().split(" ");

        for (int arItr = 0; arItr < arCount; arItr++) {
            int arItem = Integer.parseInt(arItems[arItr].trim();
            ar[arItr] = arItem;
        }

        int result = simpleArraySum(ar);

        bufferedWriter.write(String.valueOf(result));
        bufferedWriter.newLine();

        bufferedWriter.close();
    }
}



풀이 ]

- scanner.nexLine()으로 배열 길이를 입력받는다. scanner클래스의 next()와 nextLine()의 차이점은 전자는 스페이스로 입력값이 종료되고 후자는 엔터이다. 

- simpleArraySum함수로 입력값만큼 for문을 돌려 합계를 리턴한다.

- bufferWriter.write() 함수는 인자값이 string형이여야 함으로 valeOf를 이용하여 형변환한다. 



HADOOP HDFS [3] = FileSystem Shell 명령어

 

FS Shell은 HDFS와 직접 상용작용할 뿐만 아니라 WebHDFS, AmazonS3 Azure WASB 등 하둡에서 지원하는 다른 파일시스템도 포함되어있다.

FS Shell은 " bin/hadoop fs <args>" 에 의해 호출된다. 

HDFS가 이미 사용되고 있다면 hdfs dfs는 동의어이다.(=hadoop fs)


* 'hadoop fs'와 'hdfs dfs' 명령어차이는 전자는 다른 응용프로그램(WebHDFS, AmazonS3 Azure 등) 에서도 사용하는 포괄적인 명령어고 후자는 HDFS에서만 사용할 수 있는 명령어이다. 



cat

hadoop fs -cat /user/hive/text1.txt

: 해당 파일내용을 stdout(콘솔) 출력한다.


chgrp

hadoop fs -chgrp [-R] 변경할그룹 변경할 파일or디렉토리명

: 디렉토리 또는 파일의 소유 그룹을 변경한다. 옵션 -R은 디렉토리 하위모든 파일까지 변경.


chmod

hadoop fs -chmod 744 hdfs파일or디렉토리먕

: hdfs파일의 권한을 변경한다.


chown

hadoop fs -chown 변경할소유자 hdfs파일or디렉토리명

: 파일 소유권을 변경한다. 옵션 -R은 디렉토리 하위모든 파일까지 변경.


copyFromLocal / moveFromLocal / appendToFile / put

hadoop fs -copyFromLocal <로컬파일경로> <hdfs파일경로>

: 로컬파일을 hdfs파일시스템에 복사/이동 시킨다.


copyToLocal / moveToLocal

hadoop fs -copyFromLocal <hdfs파일경로> <로컬파일경로>

: hdfs파일을 로컬경로에 복사/이동 시킨다.


cp / mv

hadoop fs -copyFromLocal <이동시킬 hdfs파일경로> <이동할 hdfs파일경로>

: hdfs파일을 지정한 hdfs경로에 복사/이동 시킨다.


count

hadoop fs -count [-q] [-h] [-v] [t (storage type) ] [-u] <hdfs경로>

: hdfs경로의 파일 및 바이트 수, 디렉토리수 할당량 등을 출력한다.

  • -q : 할당량 함께 표시
  • -u : 할당량과 사용량 표시
  • -t : -q, -u옵션과 사용되며 저장소 유형에 대한 할당량과 사용량 표시
  • -h : 파일크기를 사람이 읽을 수 있는 형식으로 표시
  • -v : 헤더라인을 표시


createSnapshot

hdfs dfs -createSnapshop <hdsf경로> <snapshot이름>

: hdfs 스냅샷 생성


renameSnapshot

hdfs dfs -createSnapshop <hdsf경로> <old snapshot이름> <new snapshot이름>

: hdfs 스냅샷 파일이름 변경


deleteSnapshot

hdfs dfs -deleteSnapshot<hdsf경로> <snapshot이름>

: hdfs 스냅샷 삭제


* 스냅샷 관련 참조내용 

: https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsSnapshots.html


df

hadoop fs -df <hdfs경로>

: 할당가능량(free space)를 표시


du

hadoop fs -du [옵션] <hdfs경로>

: 지정된 경로의 파일 및 디렉토리 길이를 표시

  • -s : 개별파일이 아닌 전체 파일길이의 요약이 표시. 
  • -h : 사람이보기편한 방식으로 표시.
  • -v : 열이름을 헤드라인으로 표시.


find

hadoop fs -find / -name test -print ( hadoop fs -find <path> -name filename <expression> )

: 파일을 찾는다. 


getmerge

hadoop fs -getmerge -nl <hdfs경로> <로컬경로>

: hdfs경로 안에 있는 파일들을 합병한 결과파일을 로컬경로에 생성한다. 


head / tail

hadoop fs -head <hdfs경로>

: 지정된 파일의 앞부분/뒷부분을 stdout출력한다.


ls

hadoop fs -ls <hdfs경로>

: 해당경로의 파일or디렉토리를 조회한다.


mkdir

hadoop fs -mkdir <생성할 디렉토리명>

: 디렉토리를 생성


rm

hadoop fs -rm [옵션] <hdfs파일or디렉토리>

: 파일or디렉토리 삭제

  • - f : 진단메세지 무시
  • - R : 디렉토리와 하위파일모두 삭제


touch

hadoop fs -touch <pathname>

: 지정경로의 파일의 수정시간을 현재시간으로 업데이트. 파일이 없으면 길이0의 파일로 생성


touchz

hadoop fs -touchz <hdfs경로>

: 길이 0의 파일을 생성, 기존 파일이 있다면 오류


truncate

hadoop fs -truncate <파일길이> <hdfs경로>

: 지정된 경로의 지정한 길이로 파일을 잘라낸다.