Category Archives: Uncategorized

Running LMDBService WS NoSQL in Azure Container Instance

Now that LMDBService runs in a docker image, it is possible to run it into Azure Container Instance.

Here are the steps to follow:

  • Build the docker image locally with its dockerfile
    • docker image build –tag mydocker/myserver d:\dev\docker
  • Create a Repository in Azure Repository
  • Connect in docker shell to the repo
    • docker login lmdbwsprod.azurecr.io -u lmdbwsprod -p xxxxxxxxxxxxxxxxxxxxxxxxxx
  • Tag the prod repository
    • docker tag mydocker/myserver lmdbwsprod.azurecr.io/prod
  • Push the docker image to the Azure repository
  • Go to Azure portal and choose Azure Repository
    • Choose prod repository
    • Check tags and choose latest
    • Click Run Instance in […] button
    • Open port 7001
    • Click OK
  • Go to Azure Container Instance
    • choose the container and click Overview
    • Retrieve the IP address

Test the URL : http://40.114.209.198:7001/MyServer/LMDB/?request=set-data&key=Key_v99&value=Value_v99&name=cache_NET

 

Advertisements

Architecture of the Windows Service LMDBService

Here is it:

Architecture_LMDBService

Running a Windows Service with LMDB as a REST Web API Web Server in a Docker container

To make the test, I use the Microsoft/IIS image available at : https://hub.docker.com/r/microsoft/iis/

This image is managed by Microsoft and regulary updated. Size is around 1.8 GB. To get the image in Docker, run:

  • docker pull microsoft/iis

Then, we to create a Docker file to instruct Docker how to setup the environment :

FROM microsoft/iis
COPY *.* c:/
RUN sc create LMDBService start=auto binpath=”C:\LMDBService.exe”
#RUN net start LMDBService
EXPOSE 80
EXPOSE 7001
RUN md c:\temp

Then, we need to build the image :

  • docker image build –tag mydocker/myserver d:\dev\docker

And now, we can run the container as a deamon:

  • docker run -d -p 7001:7001 -it mydocker/myserver

In order to test the Web Server in a browser, we need to know the IP address of the web server… We need to know the IP of the container… We begin by listing the containers :

  • docker ps –a
  • we take the first item of the list

And we run the following command using the id of the container:

  • docker inspect -f “{{ .NetworkSettings.Networks.nat.IPAddress }}” 543e57f54047
  • response is displayed => 172.26.255.203

Now we can test the web server in the container.

iis

The container runs the windows service who host the web server… Let’s use this url :

web

It works !

 

LMDB – I love that stuff !

Since few months, I work on LMDB for Azure stuff. First, I have:

  • migrated the library from Linux to Windows x64
  • adapted the .NET Layer Interop
  • made custom clients code

Now, I have setup the Azure Web App Svc for hosting a simple file uploader where files will be stored in LMDB NoSQL database. The way of using it is so simple :

        private static void StoreFile(string path)
        {
            string key = path;
            string value = String.Empty;
            byte[] buffer = File.ReadAllBytes(path);

            LMDBEnvironment _env;
            string dir = "c:\\temp\\cache_net10B";
            _env = new LMDBEnvironment(dir);
            _env.MaxDatabases = 2;
            _env.MapSize = 10485760 * 100;
            _env.Open();

            DateTime dtStart = DateTime.Now;
            var tx = _env.BeginTransaction();
            var db = tx.OpenDatabase("DB", new DatabaseConfiguration { Flags = DatabaseOpenFlags.Create });
            var enc = System.Text.Encoding.UTF8;
            tx.Put(db, enc.GetBytes(key), buffer);
            tx.Commit();
            db.Dispose();

            DateTime dtStop = DateTime.Now;
            TimeSpan ts = dtStop - dtStart;
            string str = String.Format("Time elapsed for set:{0} ms", ts.TotalMilliseconds);
            Logger.LogInfo(str);

            _env.Dispose();
        }

 

If you want to test LMDB in your environement, download that stuff:

Download the LMDB Windows DLL and console_app.Exe
Download the LMDB Windows DLL, the .NET WRapper DLL and console_app.Exe

LMDB in DLL in Release x64 under Windows

Using OpenLDAP-LMDB in Relase x64, I can put elements at this stages:

  • 10.000  simples key/values in 16 ms
  • 100.000 simples key/values in 140 ms
  • 300.000 simples key/values in 421 ms. My record  !
  • 1.000.000 simples key/values in 6s -> in this case, the DATA.MDB work data file is 820MB in size.

 

lmdbdll_release

LMDB is one of the fastest NoSQL it exists and I know.

 

.NET Rangers

I am proud to announce that the .NET Rangers community is back ! We have 3 MVP !

We have a blog : http://www.dotnetrangers.org and a Twitter account:

.NET Rangers @RangersNet

Members of the community:

  • Jean-Baptiste B. Sogeti
  • Cdric G. Sogeti
  • Jean-Nicolas B. Sogeti
  • Guilhem M. C-S
  • Cdric T. Sogeti
  • Keelan C. Sogeti
  • Eva D. Neos-SDI
  • Frederic S. Sydev
  • Michel F. Indep
  • Jean-Nol G. Indep
  • Christophe P. Neos-SDI

Creating the Ping feature for a middleware

For my clustering master/worker nodes, I have put a Ping thread:

To be production code, I will protect the vector _nodes. It’s a multi-thread appz so… it needs to be done.

void MyServer::ActivatePingThread()
{
	DWORD dwThreadId = 0;
	HANDLE hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &MyServer::PingThread, NULL, 0, &dwThreadId);
}

void MyServer::PingThread(LPVOID param)
{
	while (TRUE)
	{

		::Sleep(2000);

		std::shared_ptr<NodeAttributes> pObj = nullptr;

		for (auto itr = _nodes.begin(); itr != _nodes.end(); itr++)
		{
			pObj = *itr;

			TCHAR sz[255];
			_stprintf(sz, _T("http://%s:%s/MyServer/LMDB/"), pObj->_server.c_str(), pObj->_port.c_str());

			std::wstring address = sz;

			http_client client(address);

			std::wostringstream buf;
			buf << _T("?request=") << _T("ping");

			http_response response;

			try
			{
				wcout << _T("Ping testing ip:") << pObj->_server.c_str() << _T(" on port:") << pObj->_port.c_str() << endl;
				response = client.request(methods::GET, buf.str()).get();
				wcout << response.to_string() << endl;
			}
			catch (...)
			{
				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;
			}

			json::value jdata = json::value::array();
			jdata = response.extract_json().get();

			if (jdata.is_null())
			{
				std::wcout << _T("no JSON data...") << std::endl;

				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;
				continue;
			}

			PingData data = PingData::FromJSON(jdata.as_object());

			if (data.status == _T("OK"))
			{
				// Normal behaviour
			}
			else
			{
				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;
			}

			::Sleep(1000);
		}
	}
}