System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste...
-
date post
20-Dec-2015 -
Category
Documents
-
view
224 -
download
2
Transcript of System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste...
![Page 1: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/1.jpg)
System Programming
Practical session 12
Reactor
![Page 2: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/2.jpg)
Thread-Per-Client downsides1. Each thread waste resources.
2. Blocking I/O.
3. Vulnerability to denial of service attack.
The Reactor design pattern solve these problems.
• One thread deals with communication.
Fixed number of threads deal with work.
communication and work layers are separate and asynchronous.
• Non-blocking I/O.
![Page 3: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/3.jpg)
Non-Blocking I/O
ServerSocketChannel
SocketChannel
SocketChannel
SocketChannel
SocketChannel
Selector
Server
ConnectionAcceptor
key
ProtocolTask
ConnectionHandler
![Page 4: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/4.jpg)
Channels
Channels wrap sockets, and allow non-blocking I/O.
read(), write() , accept() can be non blocking.
Setting up a non-blocking ServerSocketChannel listening on a specific port.
int port = 9999;
ServerSocketChannel ssChannel = serverSocketChannel.open();
ssChannel.configureBlocking(false);
ssChannel.socket().bind(new InetSocketAddress(port));
![Page 5: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/5.jpg)
BuffersByteBuffer are buffers that hold bytes.
Channels know how to read and write to buffers.
final int NUM_OF_BYTES = 1024;
ByteBuffer buf = ByteBuffer.allocate(NUM_OF_BYTES);
From Channel to Buffer and back
Creating a Buffer
numBytesRead = _socketChannel.read(buf1);
numBytesWritten = _socketChannel.write(buf2);
• Return –1 if channel is closed.
• Update position marker of the buffer.
![Page 6: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/6.jpg)
Selector
The selector monitors the channels for new events (new data arrived, new connection).
A Selector is registered to each channel with an attachment to handle the event.
An appropriate attachment is invoked for each new event.
Selector selector = Selector.open();
Object anAttachment = new Object();
socketChannel.register(selector, SelectionKey.OP_READ, anAttachmemt);
![Page 7: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/7.jpg)
select() Method
Blocks until at least one of the channels is ready for the registered event.
selector.select();
A list of SelectionKeys is returned.
Each Selectionkey is associated with one event, and holds the attachment registered with the event.
![Page 8: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/8.jpg)
Reactor Actors
Reactor – The main class.
• Creates ServerSocket channel
• Registers the Selector
• For each event, invokes the appropriate attachment
• ConnectionAcceptor
• ConnectionHandler
![Page 9: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/9.jpg)
ConnectionAcceptor
Reactor Actors
accept()
• Creates SocketChanel.
• Register the Selector.
• Creates ConnectionHandler.
![Page 10: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/10.jpg)
Reactor Actors
ConnectionHandler
Read()
• Reads new data from channel.
• Adds ProtoclTask for yet unprocessed input data to a fixed thread pool.
Write()
• Receives output data from ProtocolTask.
• Writes the data to the channel.
![Page 11: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/11.jpg)
Reactor Actors
ProtocolTask
• Passes unprocessed input data to message tokenizer.
• Processes each complete message.
• Passes output data to ConnectionHandler.
![Page 12: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/12.jpg)
Execution example
ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.configureBlocking( false);
ssChannel.socket().bind(new InetSocketAddress(port));
ssChannel
Selector selector = Selector.open();
selector
ssChannel.register(selector, SelectionKey.OP_ACCEPT, connectionAcceptor);
public class Reactor{
...
ExecutorService executor =
Executors.newFixedThreadPool(
_poolSize);
executor
![Page 13: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/13.jpg)
while (_shouldRun && selector.isOpen()) {
try {
selector.select();
} catch (IOException e) {…}
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
it.remove();
if (selKey.isValid() && selKey.isAcceptable()) {
ConnectionAcceptor acceptor = (ConnectionAcceptor) selKey.attachment();
try {
acceptor.accept();
} catch (IOException e) {…)
if (selKey.isValid() && selKey.isReadable()) { //Handle reading… }
if (selKey.isValid() && selKey.isWritable())
{ //Handle writing… }
}
![Page 14: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/14.jpg)
public class ConnectionAcceptor {
…
public void accept() {
SocketChannel sChannel = _ssChannel.accept();
if (sChannel != null) {
sChannel.configureBlocking(false);
SelectionKey key =sChannel.register( _data.getSelector(), 0);
ConnectionHandler handler =
ConnectionHandler.create(sChannel, _data,
key);
handler.switchToReadOnlyMode();}
}
}
}
ssChannel
selector
Client connection request
sChannel
sChannel
sChannel
![Page 15: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/15.jpg)
ssChannel
selector
sChannel
sChannel
sChannel
“Don’t worry”
![Page 16: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/16.jpg)
while (_shouldRun && selector.isOpen()) {
try {
selector.select();
} catch (IOException e) {…}
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
it.remove();
if (selKey.isValid() && selKey.isAcceptable()) {
… }
if (selKey.isValid() && selKey.isReadable()) {
ConnectionHandler handler = (ConnectionHandler) selKey.attachment();
handler.read();
}
if (selKey.isValid() && selKey.isWritable())
{ //Handle writing… }
}
![Page 17: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/17.jpg)
ssChannel
selector
sChannel
sChannel
sChannel
“Don’t worry”
public class ConnectionHandler {…
public void read() {
ByteBuffer buf =
ByteBuffer.allocate(BUFFER_SIZE);
int numBytesRead = 0;
try {
numBytesRead =sChannel.read(buf);
} catch (IOException e) {
numBytesRead = -1; }
if (numBytesRead == -1) {
closeConnection();
_protocol.connectionTerminated();
return;
}
buf.flip();
_task.addBytes(buf);
_data.getExecutor().execute(_task);
}
}
![Page 18: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/18.jpg)
public class ProtocolTask implements Runnable {
private final Vector<ByteBuffer> _buffers =
new Vector<ByteBuffer>();
…
public synchronized void run() {
synchronized (_buffers) {
while(_buffers.size() > 0) {
ByteBuffer buf = _buffers.remove(0);
this._tokenizer.addBytes(buf); }
}
while (_tokenizer.hasMessage()) {
…
}
}
}
public void addBytes(ByteBuffer b) {
synchronized (_buffers) {
_buffers.add(b);
}
}
}
_buffers
![Page 19: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/19.jpg)
public class ProtocolTask implements Runnable {
private final Vector<ByteBuffer> _buffers =
new Vector<ByteBuffer>();
…
public synchronized void run() {
synchronized (_buffers) {
while(_buffers.size() > 0) {
ByteBuffer buf = _buffers.remove(0);
this._tokenizer.addBytes(buf); }
}
while (_tokenizer.hasMessage()) {
…
}
}
}
public void addBytes(ByteBuffer b) {
synchronized (_buffers) {
_buffers.add(b);
}
}
}
_buffers
D o n ’ t w o r r y
_tokenizer
“Don’t worry”
![Page 20: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/20.jpg)
ssChannel
selector
sChannel
sChannel
sChannel
“be happy\n”
public class ConnectionHandler {…
public void read() {
ByteBuffer buf =
ByteBuffer.allocate(BUFFER_SIZE);
int numBytesRead = 0;
try {
numBytesRead =sChannel.read(buf);
} catch (IOException e) {
numBytesRead = -1; }
if (numBytesRead == -1) {
closeConnection();
_protocol.connectionTerminated();
return;
}
buf.flip();
_task.addBytes(buf);
_data.getExecutor().execute(_task);
}
}
![Page 21: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/21.jpg)
public class ProtocolTask implements Runnable {…
…
public synchronized void run() {
synchronized (_buffers) {
while(_buffers.size() > 0) {
ByteBuffer buf = _buffers.remove(0);
this._tokenizer.addBytes(buf); }
}
while (_tokenizer.hasMessage()) {
String msg = _tokenizer.nextMessage();
String response = this._protocol.processMessage(msg);
if (response != null) {
try { ByteBuffer bytes =
_tokenizer.getBytesForMessage(response);
this._handler.addOutData(bytes);
} catch (CharacterCodingException e) { … }
} } }
public void addBytes(ByteBuffer b) {
synchronized (_buffers) { _buffers.add(b); } }
}
_tokenizer
“Don’t worry be happy\n”
response
“Your message “Don’t
worry be happy” received”
![Page 22: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/22.jpg)
public class ConnectionHandler{
…
public synchronized void addOutData(ByteBuffer buf) {
_outData.add(buf);
switchToReadWriteMode();
}
public void switchToReadWriteMode() {
_skey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
_data.getSelector().wakeup();
}
}
![Page 23: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/23.jpg)
ssChannel
selector
sChannel
sChannel
sChannel
![Page 24: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/24.jpg)
while (_shouldRun && selector.isOpen()) {
try {
selector.select();
} catch (IOException e) {…}
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
it.remove();
if (selKey.isValid() && selKey.isAcceptable()) {
… }
if (selKey.isValid() && selKey.isReadable()){…}
if (selKey.isValid() && selKey.isWritable()){
ConnectionHandler handler =
(ConnectionHandler) selKey.attachment();
handler.write();
}
}
![Page 25: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/25.jpg)
“Your message “Don’t worry be
happy” received”
public synchronized void write() {
if (_outData.size() == 0) {
switchToReadOnlyMode(); return; }
ByteBuffer buf = _outData.remove(0);
if (buf.remaining() != 0) {
try { _sChannel.write(buf);
} catch (IOException e) {…}
if (buf.remaining() != 0) {
_outData.add(0, buf); }
}
if (_protocol.shouldClose()) {
switchToWriteOnlyMode();
if (buf.remaining() == 0) {
closeConnection();
}
}
}
ssChannel
selector
sChannel
sChannel
sChannel
![Page 26: System Programming Practical session 12 Reactor. Thread-Per-Client downsides 1.Each thread waste resources. 2.Blocking I/O. 3.Vulnerability to denial.](https://reader036.fdocuments.in/reader036/viewer/2022062516/56649d535503460f94a2f8c8/html5/thumbnails/26.jpg)
public synchronized void write() {
if (_outData.size() == 0) {
switchToReadOnlyMode(); return; }
ByteBuffer buf = _outData.remove(0);
if (buf.remaining() != 0) {
try { _sChannel.write(buf);
} catch (IOException e) {…}
if (buf.remaining() != 0) {
_outData.add(0, buf); }
}
if (_protocol.shouldClose()) {
switchToWriteOnlyMode();
if (buf.remaining() == 0) {
closeConnection();
}
}
}
ssChannel
selector
sChannel
sChannel