Tuesday, February 28, 2023

NSQ Realtime Distributed Messaging

NSQ is a real-time distributed messaging platform written in Go and created by well known service bit.ly.

It is simple and easy to use and has a good GUI of admin. NSQ is one of the best option if you want to implement Message Queue.


Concept of Message Queue

Message Queue is an implementation of the publisher/subscriber architectural pattern which is used for communication between different parts (applications, services, etc) of your system.

 

Message Queue process flow

 

In short, when an event happens by a message published (producer) to the Queue (shown as picture above).  Any services that interested in that services will subscribe (consumer) to get the message from the Queue.


NSQ Component

NSQ components consist of nsqd, nsqlookupd, nsqadmin.

nsqd is the daemon that receives, queues, and delivers messages to clients.

nsqlookupd is the daemon that manages topology information. Clients query nsqlookupd to discover nsqd producers for a specific topic and nsqd nodes broadcasts topic and channel information

nsqadmin is a Web UI to view aggregated cluster stats in realtime and perform various administrative tasks.

 

 nsqadmin GUI

 

Download

First of all, you need to download the binary here as following your operating system and in my case, I use Windows then I download binary for Windows.

Open extracted folder and there you can see different executables:

  • nsqlookupd.exe
  • nsqd.exe
  • nsqadmin.exe
  • .. and many others 


Step 1. Run nsqlookupd

Open extracted directory in shell/command terminal you prefer and run

C:\nsq-1.2.1.windows-amd64.go1.16.6\bin>nsqlookupd.exe

You should see the following output as below

nsqlookupd
 
 
This picture says that nsqlookupd is running and has two interfaces:
one is using TCP with port 4160 and another is using HTTP with port 4161
 
 Let's check the result

Check with browser http://localhost:4161/topics

 
Check with curl localhost:4161/topics
 
 
 This is the result you should get and its fine since there is no topics registered yet
 
 

Step 2. Run nsqd

Next step, run nsqd in terminal

 C:\nsq-1.2.1.windows-amd64.go1.16.6\bin>nsqd --lookupd-tcp-address=127.0.0.1:4160
 
 
 You should get result as shown as picture below

nsqd in terminal

 
 

Step 3. Publish a Message

Let us publish our first message in Queue. Open terminal to execute curl:
 
curl -H "Content-Type: application/json" -X POST http://localhost:4151/pub?topic=test -d "{\"Hello World 1\"}"

If the request is 200 OK, our new topic will be created automatically
 
  curl in terminal
 
 

Step 4. Run nsqadmin

 Let's check the message in admin UI. Open terminal to execute nsqadmin
 
 C:\nsq-1.2.1.windows-amd64.go1.16.6\bin>nsqadmin --lookupd-http-address=127.0.0.1:4161
 
 
Result in browser http://localhost:4171
 
 

 Click in topic to show detail
 
 
 

Step 5. Alternative to check with nsq_to_file

Open in terminal to execute nsq_to_file

C:\nsq-1.2.1.windows-amd64.go1.16.6\bin>nsq_to_file --topic=test --output-dir=/tmp --lookupd-http-address=127.0.0.1:4161

 
 nsq_to_file in terminal
 
 
 nsq_to_file will create new file test.LAPTOP-91JM58QI.2023-02-28_16.log in folder C:\tmp
 
 
 
File created by nsq_to_file
 
 
Try to send message as below
 
curl -H "Content-Type: application/json" -X POST http://localhost:4151/pub?topic=test -d "{\"Hello World 1\"}" 
 
curl -H "Content-Type: application/json" -X POST http://localhost:4151/pub?topic=test -d "{\"Hello World 2\"}" 
 
curl -H "Content-Type: application/json" -X POST http://localhost:4151/pub?topic=test -d "{\"Hello World 3\"}"
 
 
 
send Hello World
 
 
 If you open the file test.LAPTOP-91JM58QI.2023-02-28_16.log in notepad then you will get message
 
{"Hello World 1"}
{"Hello World 2"}
{"Hello World 3"}
 
 
 
I think that's all. If you read something interesting from this article, please like and comment below. Thank you all ... Happy coding!
 
 
 
 
 

Thursday, February 23, 2023

Getting Started with KrakenD API Gateway on Docker

 If you want to develop an application in cloud environment and want to implement micro-services architecture pattern then sooner or later you will face with API Gateways. There are many API Gateway outside that we can use it and in terms of open source such as Kong, KrakenD, Tyk. In this session, I will use KrakenD API Gateway on Docker to implement API Gateway. As an example, I will use https://jsonplaceholder.typicode.com for accessing data through KrakenD as API Gateway.  

For KrakenD documentation, you can read it from here

For JSONPlaceholder guide, you can read it from here

 

Configuration KrakenD Gateway

To configure KrakenD json gateway can be done by using KrakenD designer. You can design and download the file configuration easily by online.


KrakenD API Gateway designer


Here is some endpoint that I have made it through KrakenD API gateway designer


 Endpoint in KrakenD designer

 

 

Route Mapping

 I download it the file and rename it with krakend.json shown as below


{
  "$schema": "https://www.krakend.io/schema/v3.json",
  "name": "KrakenD-API Gateway",
  "version": 3,
  "timeout": "3000ms",
  "cache_ttl": "300s",
  "port": 8080,
  "endpoints": [
    {
      "endpoint": "/v1/api/posts",
      "output_encoding": "no-op",
      "backend": [
        {
          "host": [
              "https://jsonplaceholder.typicode.com"
          ],
          "url_pattern": "/posts",
          "is_collection": "true",
          "encoding": "no-op"
        }
      ]
    },
    {
      "endpoint": "/v1/api/posts/{userId}",
      "output_encoding": "no-op",
      "backend": [
        {
          "host": [
              "https://jsonplaceholder.typicode.com"
          ],
          "url_pattern": "/posts/{userId}",
          "encoding": "no-op"
        }
      ]
    }
  ],
  "extra_config": {
    "github_com/devopsfaith/krakend-cors": {
      "allow_methods": [
        "GET",
        "HEAD",
        "POST",
        "PUT",
        "DELETE",
        "CONNECT",
        "OPTIONS",
        "TRACE",
        "PATCH"
      ]
    }
  },
  "output_encoding": "no-op"
}


Installing Docker

Installing docker on Windows is easy, you just downloaded the binary and install it by following the instruction. I have installed Docker Desktop on my windows and it is including docker compose. 

My Docker version shown as below:

C:\>docker --version
Docker version 20.10.22, build 3a2c30b

C:\>docker-compose version
Docker Compose version v2.15.1

 

Dockerfile as below


FROM devopsfaith/krakend:2.0.5
COPY krakend.json /etc/krakend/krakend.json



Implementing

Create a new folder with name krakend then copy Dockerfile and krakend.json into that folder. 

From folder krakend, run this command:

 

docker build . -t api-gateway-v1


Result docker build

 

Make sure your port setting is the same as krakend.json

 docker run -it -p "8080:8080" api-gateway-v1


Result docker run


Docker desktop will create the container and images as shown as below

 

 




Testing

To check KrakenD is running well, it can be done by inputting 

http://localhost:8080/__health 

to your browser, shown as below

 


KrakenD is running well


To check the endpoint KrakenD, it can be done in browser by inputting 

http://localhost:8080/v1/api/posts

 



 To check another endpoint by inputting 

http://localhost:8080/v1/api/posts/1

 

 

Summary

I think KrakenD has bright future. All features that you need in API Gateway is covered by KrakenD. If you have any problem in implementing KrakenD, they have very good community to support you. I hope this article will help you in implementing KrakenD. Thank you

 

 

Tuesday, February 14, 2023

Programming a Guess Game in Rust

 

Setting Up a New Project

Create new project with cargo

    cargo new --bin guessing-game
    cd guessing-game

 

Processing The Code

 Setting dependencies in Cargo.toml

[package]
name = "guessing-game"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8.5"


 

 Replace the code in src/main.rs

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    //Generating random number from 1 to 100
    let secret_number = rand::thread_rng().gen_range(1..=100);

    println!("Please input your guess.");

    let mut guess = String::new();

    //Receiving input
    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    //Converting String to Int
    let input: u32 = guess
        .trim()
        .parse()
        .expect("Wanted a number");    
   
    if secret_number == input {
        println!("You are the Best");
    } else {
        println!("You are wrong");
    }

    println!("You guessed: {guess}");

 }

 

 

Testing The Code

 Run the code in terminal with command

    cd guessing-game

    cargo run
 

 
 Here is the Result 
 PS C:\guessing-game> cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target\debug\guess.exe`
    Guess the number!
    Please input your guess.
    15
    You are wrong
    You guessed: 15
 
 
 Code can be downloaded here

Tuesday, August 10, 2021

Trying Game Engine rg3d 2D/3D Written in Rust



A game engine is a software framework primarily designed for the development of a video game 2D or 3D. Typically a game engine include a game loop or rendering engine. Game engine can usually be associated with programming language such as C++ and we can find the list here

In this occasion, I found a game engine made of Rust called rg3d and have tried the sample code. rg3d stands for Rust Game engine 3D and it is a general purpose 2D/3D engine, it allows creating any kind of 2D/3D game. This engine is suitable for any kind of games and using Rapier physics engine that written in Rust too. 

Let's see the example below


2d.rs --- implementing in 2D



terrain.rs --- terrain implementation


ui.rs  --- graphic user interface


simple.rs --- load character 3D



lod.rs  --- level of detail




I think this is a great starting for Rust in game engine and I hope Rust can be used like C++ in the future game development. Thank you


 

Tuesday, July 13, 2021

Trying Piston Game Engine in Rust

Piston is a game engine written in Rust. It is a modular game engine with a minimal core abstraction and designed for optimal modularity, making it optional to even use the core modules in many cases.

This example was running in Windows OS. Just make sure you have installed Rust and Cargo.

You can download the source in here

 

Setting up the project

1.  Create new project with cargo

    cargo new --bin getting-started
    cd getting-started

 

2. Setting dependencies in Cargo.toml

    [package]
    name = "spinning-square"
    version = "0.1.0"
    authors = [
        "TyOverby <ty@pre-alpha.com>",
        "Nikita Pekin <contact@nikitapek.in>"
    ]

    [[bin]]
    name = "spinning-square"

    [dependencies]
    piston = "0.53.0"
    piston2d-graphics = "0.40.0"
    pistoncore-glutin_window = "0.69.0"
    piston2d-opengl_graphics = "0.78.0"

 

Copy the code in main.rs

 Open src/main.rs and copy the code below

    extern crate glutin_window;
    extern crate graphics;
    extern crate opengl_graphics;
    extern crate piston;

    use glutin_window::GlutinWindow as Window;
    use opengl_graphics::{GlGraphics, OpenGL};
    use piston::event_loop::{EventSettings, Events};
    use piston::input::{RenderArgs, RenderEvent, UpdateArgs, UpdateEvent};
    use piston::window::WindowSettings;

    pub struct App {
        gl: GlGraphics, // OpenGL drawing backend.
        rotation: f64,  // Rotation for the square.
    }

    impl App {
        fn render(&mut self, args: &RenderArgs) {
            use graphics::*;

            const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
            const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];

            let square = rectangle::square(0.0, 0.0, 50.0);
            let rotation = self.rotation;
            let (x, y) = (args.window_size[0] / 2.0, args.window_size[1] / 2.0);

            self.gl.draw(args.viewport(), |c, gl| {
                // Clear the screen.
                clear(GREEN, gl);

                let transform = c
                    .transform
                    .trans(x, y)
                    .rot_rad(rotation)
                    .trans(-25.0, -25.0);

                // Draw a box rotating around the middle of the screen.
                rectangle(RED, square, transform, gl);
            });
        }

        fn update(&mut self, args: &UpdateArgs) {
            // Rotate 2 radians per second.
            self.rotation += 2.0 * args.dt;
        }
    }

    fn main() {
        // Change this to OpenGL::V2_1 if not working.
        let opengl = OpenGL::V3_2;

        // Create an Glutin window.
        let mut window: Window = WindowSettings::new("spinning-square", [200, 200])
            .graphics_api(opengl)
            .exit_on_esc(true)
            .build()
            .unwrap();

        // Create a new game and run it.
        let mut app = App {
            gl: GlGraphics::new(opengl),
            rotation: 0.0,
        };

        let mut events = Events::new(EventSettings::new());
        while let Some(e) = events.next(&mut window) {
            if let Some(args) = e.render_args() {
                app.render(&args);
            }

            if let Some(args) = e.update_args() {
                app.update(&args);
            }
        }
    }


Compiling and Running

 Compiling with "cargo build" and it will download all dependencies


Finally, running the code with "cargo run"


You should have a rotating square as shown as picture above





Monday, July 12, 2021

Printing Pyramid Patterns in Rust

 This article is aimed at giving a Rust implementation in printing of pyramid patterns.


First Pattern

Output:

*
**
***
****
*****


fn pyramid(n:i32) {
    for row in 1..=n {
        for _col in 1..=row {
            print!("*");
        }
        println!("");
    }
}

fn main() {
    pyramid(5);
}


Second Pattern

  Output:

    *
   **
  ***
 ****
*****



fn pyramid(n:i32) {
    for row in (1..=n).rev() {
        for col in 1..=n {
            if col >= row {
                print!("*");
            } else {
                print!(" ");
            }            
        }
        println!("");
    }
}

fn main() {
    pyramid(5);
}


Third Pattern

Output:

*****
****
***
**
*


fn pyramid(n:i32) {
    for row in (1..=n).rev() {
        for _col in 1..=row {
            print!("*");
        }
        println!("");
    }
}

fn main() {
    pyramid(5);
}


Fourth Pattern

Output:

*****
 ****
  ***
   **
    *


fn pyramid(n:i32) {

    let mut k = 2 * n - 2;

    for row in (1..=n).rev() {
        for _col in 1..=n-row {
            print!(" ");
        }

        = k - 2;

        for _col in 1..=row {
            print!("*");
        }

        println!("");
    }
}

fn main() {
    pyramid(5);
}



Fifth Pattern

Output:

   *
  ***
 *****
*******



fn pyramid(n:i32) {
    let mut i:i32 = 0;
    let mut j:i32 = 0;
    let mut k:i32 = 0;
    while i < n {
       
        // for spacing
        while k <= (n - i - 2) {
            print!(" ");
            = k + 1;
        }
        0;
       
        // For Patter printing
        while j < (2 * i - 1) {
            print!("*");
            = j + 1;
        }
        0;
        = i + 1;
        println!(" ");
    }
}

fn main() {
    pyramid(5);
}