Wednesday, January 13, 2016

Is Java the right language for Micro Services?

[work in progress]
Micro Server for Micro services

Micro services are becoming slowly but steady mainstream programming architecture. People often compare them to web services or rest services witch gives more problems than understanding. And when you look at implementation you'll see that developers are running away from Java to Scala, Nodejs or Python or name it. Is Java old? Is it time to close Java book and learn something new? Learning new things is always good, but I think reason why developers run away from Java is not a language problem, but Java legacy.

Biggest problem why developers avoid Java to make micro services is that there are not so many good tools and servers for micro services in Java or put it better there are many old wrong tools and server to start with. If you are old Java developer you will have problems to grasp this.

When you start to create micro service your focus should be on micro. Project should compile in less than 10s.Your service should have only packages, libraries and frameworks that it really needs, everything else should be striped away. Start of the server should be fast less than 10 sec.

Problem is when you start web project in Java you are entering in dependency hell of big application servers, heavy blocking databases that have ALL that you do NOT need and frameworks that solve all problems that you do not have and have support for everything you do not need.

You will write in Java 10-15 classes that will solve problem of your service, and then you will deploy that on heavy J2EE server, with some REST framework that will add to your project tones of jars you do not need. You will create war package that ziped is 20-200MB, that you need to deploy and start server.

That is wrong J2EE legacy, heavy over engineered solution that should fit all web problems. Problem is not Java itself. Example of wrong tools in Java for micro services are dropwizard, spring roo, tomcat, jetty, any JDBC database.

What do you really need?

You need for your project of 10-15 classes a server that runs as a jar or exe. No deployment, no other applications on that server. You need non blocking fully asynchronous server written in 2-6 classes that starts in less than 5s and it doesn't have ANY additional dependencies. You need asynchronous NoSQL storage. There are few alternative server options from which you can start or you can choose to get your hands dirty and fight yourself for things how they should be.

New simple server will have just 2-6 classes. It will use just java. It will use NIO2 java classes. It will start as simple java app. No wars to deploy, simple start and stop. So it should work almost as nodejs, in one thread. We can add reactor jar if we need better multi-threaded support.


  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
180
181
182
183
184
185
186
187
188
189
190
191
package org.avenger.sts.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SingleThreadedServer implements Runnable {

 protected int serverPort = 8080;
 protected ServerSocketChannel serverSocketChannel = null;
 protected Selector selector = null;
 protected boolean isStopped = false;

 public SingleThreadedServer(int port) {
  this.serverPort = port;
 }

 public void run() {

  openServerSocket();
  SocketChannel socketChannel = null;

  while (!isStopped()) {
   System.out.println("is running");
   try {
    int readyChannels = selector.select();
    if (readyChannels == 0) {
     System.out.println("none");
     continue;
    }

    Set<selectionkey> selectedKeys = selector.selectedKeys();
    Iterator<selectionkey> keyIterator = selectedKeys.iterator();

    while (keyIterator.hasNext()) {
     System.out.println("while");

     SelectionKey lkey = keyIterator.next();

     if (lkey.isAcceptable()) {
      // a connection was accepted by a ServerSocketChannel.
      System.out.println("accept");
      try {
       socketChannel = serverSocketChannel.accept();
       if (socketChannel != null) {
        socketChannel.configureBlocking(false);
        socketChannel.socket().setTcpNoDelay(true);
        socketChannel.register(selector,
          SelectionKey.OP_READ);
       }

      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }

     } else if (lkey.isConnectable()) {
      // a connection was established with a remote server.
      System.out.println("connected");
     } else if (lkey.isReadable()) {
      // a channel is ready for reading
      System.out.println("read");
      socketChannel.register(selector, SelectionKey.OP_WRITE);
     } else if (lkey.isWritable()) {
      System.out.println("write");
      try {
       processClientRequest(socketChannel);
      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }

     keyIterator.remove();
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

  }

  System.out.println("Server Stopped!");
 }

 private void processClientRequest(SocketChannel socketChannel)
   throws IOException {
  if (socketChannel == null)
   return;

  long time = System.currentTimeMillis();

  // TODO should direct buffer be used if we need large capacity?,
  // allocate vs allocateDirect
  // when allocateDirect is used socketchannel throws exception
  // TODO create one buffer if possible
  ByteBuffer inbuf = ByteBuffer.allocate(48);
  int bytesRead = socketChannel.read(inbuf);

  //System.out.println(bytesRead);
  //System.out.println("new String(inbuf.array()) 1: "
   // + new String(inbuf.array()));

  // char[] cctest = inbuf.array();

  String read = "";
  while (bytesRead &gt; 0) {
   read = read + new String(((ByteBuffer) inbuf.flip()).array());
   bytesRead = socketChannel.read(inbuf);
   // System.out.println(bytesRead);
   // System.out.println("new String(inbuf.array()) 0: " + new
   // String(inbuf.array()));
   // System.out.println("READ: " + read);
   inbuf.compact();
  }
  System.out.println("READ: " + read);

  // use charBuffer or Trove char listS
  /*
   * CharBuffer read = CharBuffer.allocate(1024); while (bytesRead &gt; 0) {
   * char[] rr = ((ByteBuffer)inbuf.flip()).asCharBuffer().array();
   * read.put(rr); bytesRead = socketChannel.read(inbuf); inbuf.compact();
   * } System.out.println(read.array());
   */

  // TODO parse char[] not string
  HttpRequestParser parser = new HttpRequestParser();
  try {
   parser.parseRequest(read);
   System.out.println("RequestLine: " + parser.getRequestLine());
   System.out.println("Host: " + parser.getHeaderParam("Host"));
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

  String newData = "HTTP/1.1 200 OK\n\n<html><body>"
    + "Singlethreaded Server: " + time + "</body></html>";

  ByteBuffer outbuf = ByteBuffer.allocate(newData.getBytes().length);
  outbuf.clear();
  outbuf.put(newData.getBytes());

  outbuf.flip();

  while (outbuf.hasRemaining()) {
   socketChannel.write(outbuf);
  }

  socketChannel.close();

  System.out.println("Request processed: " + time);
 }

 private synchronized boolean isStopped() {
  return this.isStopped;
 }

 public synchronized void stop() {
  this.isStopped = true;
  try {
   this.serverSocketChannel.close();
  } catch (IOException e) {
   throw new RuntimeException("Error closing server", e);
  }
 }

 private void openServerSocket() {
  try {
   this.serverSocketChannel = ServerSocketChannel.open();
   this.serverSocketChannel.socket().bind(
     new InetSocketAddress(this.serverPort));
   this.serverSocketChannel.configureBlocking(false);

   selector = Selector.open();
   SelectionKey key = this.serverSocketChannel.register(selector,
     SelectionKey.OP_ACCEPT);
  } catch (IOException e) {
   throw new RuntimeException("Cannot open port: " + this.serverPort,
     e);
  }
  System.out.println("Server started ! on port: " + this.serverPort);
 }
}


no J2ee
no big tools
fast compile less than 10s
start jar, no war no deploy,


github link
https://github.com/sasajovancic/avenger

parse url
String Parsing.... Boon has really fast String parsing about 2x
https://github.com/boonproject/boon



links
http://technologyconversations.com/2015/01/07/monolithic-servers-vs-microservices/
http://martinfowler.com/articles/microservices.html
https://www.quora.com/Can-micro-services-be-developed-only-in-Node-js-Cant-we-develop-them-in-other-languages-like-Java
http://blog.erlware.org/monolith-vs-microservices-where-to-start/

Friday, January 1, 2016

New Year's card

Today is a new day, a new clean start. I wish you to feel well for what used to hurt you before, and that you are loved by whomever didn't loved you before.

I wish you that your children are better than you, and that you brag more with them than your kids brag with you.

I wish you healthy and strong (feet) legs and to have more work than time.
I wish you to be more needed by others than others are needed to you.

I wish you to dream and do more than you need, and share with those that can not.
Do not take more than you give.
I wish you to acquire, win or get what you dream of and to respect and enjoy what you already have.
 
I wish you a Happy New Year and little bit more luck than in previous one.

Friday, October 23, 2015

My Tilt-Shift exercise


I love photos, much more just to look at enjoy and admire then to be active in taking some. Mainly because, when I look at what I shoot it looks to me that I always snap at wrong moment, that just few mili-seconds before (or after) it was a perfect moment, or that I did it with wrong camera or wrong camera settings. Prices of good cameras are very affordable nowadays but I stay with love to simple idiot cameras that have one or few setting modes. So afterwards I stay longer time in-front of my PC trying to filter them and take best of what I actually did.

Key point for me is to take a lot more pictures than needed. Here are few latest work with Tilt shift filter on common image. To make tilt shift effect you do not need support from editing tool you can do it with simple filters, blur+hue+contrast, there a lot of tutorials on the net.

Original:
















Tell me what you think, or share with me your experience.