Scala에서 Socket.IO
배경
Socket.IO로 pub/sub를 실현하고 싶다면 Node.js로 서버를 세우는 것이 철판? 라고 생각합니다만, 다른 시스템간에 제휴하고 싶은 일도 있지요.
Scala에서 Socket.IO
그림과 같이 센서로 데려온 데이터를 Scala로 작성된 서버에 보내고 있습니다만, 갱신 정보를 서버로부터 클라이언트측에 리얼타임으로 전하고 싶은 경우, Scala의 서버와 클라이언트간에 websocket를 사용하면 됩니다만 , 클라이언트측의 브라우저의 대응 유무등을 신경쓰고 싶지 않기 때문에 이번은 Socket.IO를 사용합니다.
Scala에서 Socket.IO와 호환되는 라이브러리가 있는지 찾았지만 Play Framework의 모듈로 존재하는 것을 확인할 수 있었지만 범용 라이브러리를 찾을 수 없습니다.
이번 서버측은 AkkaHTTP로 쓰고 있어, 다른 방법으로 실현할 필요가 나왔습니다.
Redis pub/sub 활용하기
그림과 같이 Redis를 중개역으로 이용하는 방법을 생각합니다.
Node.js측은, 이하와 같이 조금 코드를 더하는 것만으로 대응할 수 있습니다.
const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
Scala 측은 그렇다면 Redis에 직접 쓰러 가야합니다.
Scala용 Redis 클라이언트에 대해 정리해 주었던 기사를 참고로 선정합니다.
타케조 빈사 블로그
Sedis는 차단만이므로 제외. 남은 'scala-redis' 또는 'rediscala'가 후보가 됩니다.
redis에 쓰는 데이터의 형식은 다음과 같습니다.
여기서는 data 배열의 두 번째 요소로 보낼 데이터를 설정합니다.
[
"emitter",
{
"type": 2,
"data": [
"イベント名",
{
"message": "Hello World!"
}
],
"nsp": "namespace"
},
{
"rooms": ["ルーム名"],
"flags": []
}
]
이것을 MessagePack로 직렬화한 바이너리 데이터를 redis에 기입합니다.
여기서 이전의 라이브러리 중 「scala-redis」는 바이너리 기입의 메소드를 가지고 있지 않기 때문에, 「rediscala」일택이 됩니다.
Scala에서 MessagePack의 라이브러리는 MessagePack 본가가 내고 있는 "msgpack-scala"를 이용합니다.
msgpack-scala
이 라이브러리가 조금 곡자로 위의 JSON을 표현하는 코드는 다음과 같습니다.
다른 언어의 라이브러리라면 메소드 일발로 바이너리로 해주거나 하는 것 같습니다만, 이 라이브러리에는 보이지 않았습니다...
val out = new ByteArrayOutputStream
val packer = MessagePack.newDefaultPacker(out)
packer.packArrayHeader(3)
// set emitter
packer.packString("emitter")
// set type 2
packer.packMapHeader(3)
packer.packString("type")
packer.packString("2")
// set data
packer.packString("data")
packer.packArrayHeader(2)
// set event name
packer.packString("イベント名")
// set data body
packer.packMapHeader(1)
packer.packString("message")
packer.packString("Hello World!")
// set namespace
packer.packString("nsp")
packer.packString("/")
packer.packMapHeader(2)
packer.packString(roomName)
packer.packArrayHeader(1)
packer.packString("ルーム名")
packer.packString("flags")
packer.packMapHeader(0)
packer.flush()
packer.close()
out.toByteArray
여기에서 얻은 바이너리 데이터를 rediscala를 사용하여 Redis에 씁니다.
※RedisClient의 생성자는 ActorSystem을 implict로 받게 되어 있으므로, 각각의 환경에 따라 준비해 주세요.
val redis = RedisClient(server,port)
redis.publish("チャンネル名", バイナリデータ)
데이터 수신
클라이언트 측에서는 설정한 이벤트 이름으로 데이터를 수신할 수 있습니다.
socketio.on('イベント名', function(msg){
console.log('receive:' + JSON.stringify(msg));
});
요약
Scala에서 소개했지만 다른 언어에서도 같은 구조를 이용하여 Redis에 쓸 수 있으면 제휴를 할 수 있을까 생각합니다.
※이번 참고로 한 사이트
이 사람은 비슷한 것을 파이썬으로 실현되었습니다.
파이썬을 사용하여 socket.io-redis에 이벤트를 emit
Reference
이 문제에 관하여(Scala에서 Socket.IO), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/naokism/items/d9be06842df2f403fb32
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
그림과 같이 센서로 데려온 데이터를 Scala로 작성된 서버에 보내고 있습니다만, 갱신 정보를 서버로부터 클라이언트측에 리얼타임으로 전하고 싶은 경우, Scala의 서버와 클라이언트간에 websocket를 사용하면 됩니다만 , 클라이언트측의 브라우저의 대응 유무등을 신경쓰고 싶지 않기 때문에 이번은 Socket.IO를 사용합니다.
Scala에서 Socket.IO와 호환되는 라이브러리가 있는지 찾았지만 Play Framework의 모듈로 존재하는 것을 확인할 수 있었지만 범용 라이브러리를 찾을 수 없습니다.
이번 서버측은 AkkaHTTP로 쓰고 있어, 다른 방법으로 실현할 필요가 나왔습니다.
Redis pub/sub 활용하기
그림과 같이 Redis를 중개역으로 이용하는 방법을 생각합니다.
Node.js측은, 이하와 같이 조금 코드를 더하는 것만으로 대응할 수 있습니다.
const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
Scala 측은 그렇다면 Redis에 직접 쓰러 가야합니다.
Scala용 Redis 클라이언트에 대해 정리해 주었던 기사를 참고로 선정합니다.
타케조 빈사 블로그
Sedis는 차단만이므로 제외. 남은 'scala-redis' 또는 'rediscala'가 후보가 됩니다.
redis에 쓰는 데이터의 형식은 다음과 같습니다.
여기서는 data 배열의 두 번째 요소로 보낼 데이터를 설정합니다.
[
"emitter",
{
"type": 2,
"data": [
"イベント名",
{
"message": "Hello World!"
}
],
"nsp": "namespace"
},
{
"rooms": ["ルーム名"],
"flags": []
}
]
이것을 MessagePack로 직렬화한 바이너리 데이터를 redis에 기입합니다.
여기서 이전의 라이브러리 중 「scala-redis」는 바이너리 기입의 메소드를 가지고 있지 않기 때문에, 「rediscala」일택이 됩니다.
Scala에서 MessagePack의 라이브러리는 MessagePack 본가가 내고 있는 "msgpack-scala"를 이용합니다.
msgpack-scala
이 라이브러리가 조금 곡자로 위의 JSON을 표현하는 코드는 다음과 같습니다.
다른 언어의 라이브러리라면 메소드 일발로 바이너리로 해주거나 하는 것 같습니다만, 이 라이브러리에는 보이지 않았습니다...
val out = new ByteArrayOutputStream
val packer = MessagePack.newDefaultPacker(out)
packer.packArrayHeader(3)
// set emitter
packer.packString("emitter")
// set type 2
packer.packMapHeader(3)
packer.packString("type")
packer.packString("2")
// set data
packer.packString("data")
packer.packArrayHeader(2)
// set event name
packer.packString("イベント名")
// set data body
packer.packMapHeader(1)
packer.packString("message")
packer.packString("Hello World!")
// set namespace
packer.packString("nsp")
packer.packString("/")
packer.packMapHeader(2)
packer.packString(roomName)
packer.packArrayHeader(1)
packer.packString("ルーム名")
packer.packString("flags")
packer.packMapHeader(0)
packer.flush()
packer.close()
out.toByteArray
여기에서 얻은 바이너리 데이터를 rediscala를 사용하여 Redis에 씁니다.
※RedisClient의 생성자는 ActorSystem을 implict로 받게 되어 있으므로, 각각의 환경에 따라 준비해 주세요.
val redis = RedisClient(server,port)
redis.publish("チャンネル名", バイナリデータ)
데이터 수신
클라이언트 측에서는 설정한 이벤트 이름으로 데이터를 수신할 수 있습니다.
socketio.on('イベント名', function(msg){
console.log('receive:' + JSON.stringify(msg));
});
요약
Scala에서 소개했지만 다른 언어에서도 같은 구조를 이용하여 Redis에 쓸 수 있으면 제휴를 할 수 있을까 생각합니다.
※이번 참고로 한 사이트
이 사람은 비슷한 것을 파이썬으로 실현되었습니다.
파이썬을 사용하여 socket.io-redis에 이벤트를 emit
Reference
이 문제에 관하여(Scala에서 Socket.IO), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/naokism/items/d9be06842df2f403fb32
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
[
"emitter",
{
"type": 2,
"data": [
"イベント名",
{
"message": "Hello World!"
}
],
"nsp": "namespace"
},
{
"rooms": ["ルーム名"],
"flags": []
}
]
val out = new ByteArrayOutputStream
val packer = MessagePack.newDefaultPacker(out)
packer.packArrayHeader(3)
// set emitter
packer.packString("emitter")
// set type 2
packer.packMapHeader(3)
packer.packString("type")
packer.packString("2")
// set data
packer.packString("data")
packer.packArrayHeader(2)
// set event name
packer.packString("イベント名")
// set data body
packer.packMapHeader(1)
packer.packString("message")
packer.packString("Hello World!")
// set namespace
packer.packString("nsp")
packer.packString("/")
packer.packMapHeader(2)
packer.packString(roomName)
packer.packArrayHeader(1)
packer.packString("ルーム名")
packer.packString("flags")
packer.packMapHeader(0)
packer.flush()
packer.close()
out.toByteArray
val redis = RedisClient(server,port)
redis.publish("チャンネル名", バイナリデータ)
클라이언트 측에서는 설정한 이벤트 이름으로 데이터를 수신할 수 있습니다.
socketio.on('イベント名', function(msg){
console.log('receive:' + JSON.stringify(msg));
});
요약
Scala에서 소개했지만 다른 언어에서도 같은 구조를 이용하여 Redis에 쓸 수 있으면 제휴를 할 수 있을까 생각합니다.
※이번 참고로 한 사이트
이 사람은 비슷한 것을 파이썬으로 실현되었습니다.
파이썬을 사용하여 socket.io-redis에 이벤트를 emit
Reference
이 문제에 관하여(Scala에서 Socket.IO), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/naokism/items/d9be06842df2f403fb32
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
이 사람은 비슷한 것을 파이썬으로 실현되었습니다.
파이썬을 사용하여 socket.io-redis에 이벤트를 emit
Reference
이 문제에 관하여(Scala에서 Socket.IO), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/naokism/items/d9be06842df2f403fb32텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)