Nov 11, 2013

Hazelcast trick 1

I was playing with hazelcast for a while. Great tool for java-based distributed systems - simple and elegant.
During our work I've run into some tricky situations. I understand that they can be solved in different ways, I've shosen to write some bits of code. I'll share these bits with explanations in upcoming posts.

Hazelcast Trick 1. Multicast vs TcpIpJoiner

Problem: 

In our network some clusters were in several subnets - and I've not figured out how to fix this yet, but hazelcast has tcp-ip joiner to the resque. There is one disadwantage though. Same config file for different machines makes it hard not to include localhost in config. And hazelcast was not working with hostnames correctly for me.

Solution:

So, I've decided to keep config file uniform, but add following code to my startup procedure:
       Config cfg = new FileSystemXmlConfig(configFile);
        cfg.setInstanceName(configName);
        if (tcpipjoin != null && tcpipjoin.isEnabled()) {
            cfg.getNetworkConfig().getJoin().getTcpIpConfig().clear();
            cfg.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
            cfg.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
            for (String host : tcpipjoin.getHosts()) {
                String resolvedHost = resolveHostToIp(host);
                if (resolvedHost != null) {
                    cfg.getNetworkConfig().getJoin().getTcpIpConfig().addMember(resolvedHost);
                }
            }
        }
This solved 2 issues:

  1. Resolve hostname to IP (oddly, hazelcast was not doing well with hostnames, dont know why yet)
  2. Exclude localhost from list - in this final configuration was simple and effective. Without attempting to call itself and rezolve hostname.
Helper methos is not as straitforward, here it goes:

    static String resolveHostToIp(String host) throws UnknownHostException {
        String[] parts = host.split(":");
        if (parts.length > 2) throw new UnknownHostException("Illegal host format: " + host);
        String ip = InetAddress.getByName(parts[0].trim()).getHostAddress();
        if(isLocal(ip)) {
            logger.info("Host " + host + "filtered out as local");
            return null;
        }
        String resolved = parts.length == 1 ? ip : (ip + ":" + parts[1].trim());
        logger.debug("host " + host + " resolved to " + resolved);
        return resolved;
    }

    private volatile static List localhostIpSynonyms;

    private static boolean isLocal(String ip) {
        if (localhostIpSynonyms != null) {
            return localhostIpSynonyms.contains(ip);
        }
        else {
            try {
                List synonims = new ArrayList<>();
                for (Enumeration ifcs = NetworkInterface.getNetworkInterfaces(); ifcs.hasMoreElements(); ) {
                    NetworkInterface ifc = ifcs.nextElement();
                    if (ifc.isUp()) {
                        for (Enumeration ias = ifc.getInetAddresses(); ias.hasMoreElements(); ) {
                            synonims.add(ias.nextElement().getHostAddress());
                        }
                    }
                }
                localhostIpSynonyms = synonims;
                logger.info("Local IP's resolved to:" + localhostIpSynonyms);
                return localhostIpSynonyms.contains(ip);
            } catch (Exception e) {
                logger.error("Can not resolve list of local ip adress", e);
            }
        }
        return false;
    }

Trick is not only to rezolve hostname to ip with port set, but to lookup all local interfaces in order to drop local ones.

Oct 23, 2013

Trunk Based Development vs Successful-git-branching-model

At work I've faced 2 generic approaches to branching:

  1. "Modern", where we have branch-per-feature policy:
    http://nvie.com/posts/a-successful-git-branching-model/
  2. "Classic", where everybody commit to the trunk and branches are made only for releases:
    http://paulhammant.com/2013/04/05/what-is-trunk-based-development/
Both approaches are very interesting, but my personal favorite is "Classic" one. Because:
  1. CI  (Continious integration)- you merge often, and you have ci server testing your code. In first approach, you'll need job-per-branch, and there are a lot of them! In second, one job will notify you then your commit is breaking something
  2. If your changes are not compiling\not all test pass? Well, in this case solution is to commit but don't push.
  3. Second approach forces some sporadic code review, when 2 developers change some linked source - and this triggers communication and is a good way to common vision.

Sep 23, 2013

Java Puzzle #1

Inspired by Java Puzzlers conference, spotted interesting behaviour of following code:
public class LongNull {
    Long longi = null;

    public long getLongi() {
        return longi;
    }

    public static void main(String[] args) {
        System.out.println(new LongNull().getLongi());
    }
}
What it produces:
  1. NullPointerException
  2. Prints 0
  3. Prints null

Jan 21, 2013

The Role of the Development Manager

I've came across great article about development manager role, and want to share it with you:
http://www.infoq.com/articles/development-manager-role