Erlang从远程代码服务器加载模块

在分布式开发过程中涉及代码更新是一件很痛苦的事,需要手动去更新所有服务器上的代码。其实Erlang可以通过boot server来远程加载代码,从而只需更新代码服务器就可以完成系统升级。

首先需要启动boot server,有两种方式:

手动启动

erl_boot_server:start(Slaves) % Slaves是被允许连接到该boot server的客户端IP,可以为空

通过配置kernel启动 boot_server.config

[
    {kernel, 
      [
          {start_boot_server, true},
          {boot_server_slaves, [{192,168,0,101},{192,186,0,102}]}
      ]
    }  
].

示例

在代码服务器启动boot server

erl -name master@192.168.0.100 -config boot_server -setcookie freecnpro

子节点连接boot server

erl -name slave01@192.168.0.101 -setcookie freecnpro -loader inet -hosts '192.168.0.100' -id slave01@192.168.0.101

连接上boot server,子节点就从boot server启动并加载相应模块。子节点所有的模块都是从boot_server通过erl_prim_loader加载。

相关操作

erl_boot_server:add_slave(Slave) % 动态添加Slave
erl_boot_server:delete_slave(Slave) % 动态删除Slave
erl_boot_server:which_slave() % 列出被允许的Slave

read more

强健而漂亮的Erlang

erlang
Erlang是什么

Erlang is a programming language used to build massively scalable soft real-time
systems with requirements on high availability. Some of its uses are in telecoms,
banking, e-commerce, computer telephony and instant messaging. Erlang's runtime s
ystem has built-in support for concurrency, distribution and fault tolerance.

这是官方的定义,说白了Erlang无非就是一个编程语言,它内置高并发、容错、扩展、分布式等特性。

都有谁在使用Erlang

  • SimpleDB, a distributed database that is part of Amazon Web Services
  • ejabberd, an Extensible Messaging and Presence Protocol (XMPP) instant messaging server
  • Facebook Chat system was running on ejabberd based servers, before switching to Java.
  • RabbitMQ, an implementation of Advanced Message Queuing Protocol (AMQP)
  • GitHub, a web-based hosting service for software development projects that use the Git version control system. Erlang is used for RPC proxies to ruby processes.
  • WhatsApp, mobile messenger
  • T-Mobile uses Erlang in its SMS and authentication systems.
  • Yahoo! uses it in its social bookmarking service, Delicious, which has more than 5 million users and 150 million bookmarked URLs.

以上数据摘抄自Wikipedia,其实国内也有很多公司使用,例如淘宝、腾讯、百度等。

Erlang到底能做什么
如果你问我这个问题,其实我想说的是Any。任何一个语言都能做任何事,只是它擅长不擅长而已。Erlang所擅长的就是高并发、高稳定性、分布式编程,当然其弱点在于计算能力,不过这个可以通过NIF来弥补。

Erlang美在哪
首先,Erlang是一个函数式语言,语法代码都很简洁明了。

-module(hello).
-export([hello_world/0]).

hello_world() -> io:fwrite("hello, world\n").

其次,Erlang天生就适合分布式开发,很多适合你都忘记你是在做分布式开发。

Node@whatsapp.com ! "Hello Whatsapp" % 没错,就这么简单地向远程机器打了个招呼

read more

使用OpenCV做图像特征提取与匹配

目前图像识别仍然是一个重要的研究课题,主要用到的图像匹配方法有颜色直方图、模版匹配、特征匹配等。特征匹配是目前主流的也是准确率较高的匹配方式,例如Google、百度等主流搜索引擎的图像搜索。
下面是使用OpenCV实现的一个简单的图像特征匹配程序

main.cpp

#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include "feature.h"

using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        cout << "wrong usage!" << endl;
        cout << "usage: ./bin queryImage trainImage" << endl;
        return -1;
    }

    string detectorType = "SURF";
    string extractorType = "SIFT";
    string detectors[] = {"SIFT", "SURF", "SURF", "MSER", "STAR", "HARRIS", "FAST"};
    string extractors[] = {"SIFT", "SURF", "SIFT", "SIFT", "SIFT", "SIFT", "SIFT"};
    string matchType = "FlannBased";
    string queryImagePath = argv[1];
    string trainImagePath = argv[2];

    Mat queryImage = imread(queryImagePath, CV_LOAD_IMAGE_GRAYSCALE);
    Mat trainImage = imread(trainImagePath, CV_LOAD_IMAGE_GRAYSCALE);
    if (queryImage.empty() || trainImage.empty())
    {
        cout<<"read failed"<< endl;
        return -1;
    }

    for(int i = 0; i < 7; ++i)
    {
        string detectorType = detectors[i];
        string extractorType = extractors[i];

        Feature feature(detectorType, extractorType, matchType);

        vector<KeyPoint> queryKeypoints, trainKeypoints;
        feature.detectKeypoints(queryImage, queryKeypoints);
        feature.detectKeypoints(trainImage, trainKeypoints);

        Mat queryDescriptor, trainDescriptor;

        feature.extractDescriptors(queryImage, queryKeypoints, queryDescriptor);
        feature.extractDescriptors(trainImage, trainKeypoints, trainDescriptor);

        vector<DMatch> matches;
        feature.bestMatch(queryDescriptor, trainDescriptor, matches);

        double max_dist = 0;
        double min_dist = 100;

        for(int i = 0; i < queryDescriptor.rows; ++i)
        {
            double dist = matches[i].distance;
            if(dist < min_dist) min_dist = dist;
            if(dist > max_dist) max_dist = dist;
        }
        //printf("-- Min dist: %f \n", min_dist);
        //printf("-- Max dist: %f \n", max_dist);

        vector< DMatch > good_matches;
        for(int i = 0; i < queryDescriptor.rows; ++i)
        {
            if( matches[i].distance <= max(2*min_dist, 0.02) )
            {
                good_matches.push_back(matches[i]);
            }
        }
        feature.saveMatches(queryImage, queryKeypoints, trainImage, trainKeypoints, good_matches, "./");
    }
	  printf("Done\n");
    return 0;
}

read more