Skip to main content

2 posts tagged with "go"

View All Tags

· 4 min read

Introduction

In the realm of software development, there is often a need for implementing features dynamically, toggling functionalities, and rolling out changes seamlessly without disrupting user experience. Imagine this scenario: you're working on a high-stakes project, and you need to introduce a new feature. However, releasing it to all users at once might be risky. What if there are bugs? What if users don't like it? This is where feature flags come to the rescue.

The Tale of Dynamic Feature Rollouts

Let's delve into a hypothetical scenario. Meet Adam, a software engineer working on a cutting-edge e-commerce platform. Their team is gearing up to introduce a new payment gateway, which promises to enhance user experience and reduces failure rates. However, they're wary of unforeseen bugs that might surface during the rollout. Plus, they're unsure if the new checkout flow will resonate well with all users.

Here's where feature flags come into play. By leveraging feature flags, Adam and their team can deploy the new payment gateway to a small subset of users initially. They can monitor its performance, gather feedback, and make necessary tweaks without affecting the entire user base. Once they're confident in the feature's stability and user acceptance, they can gradually roll it out to all users, mitigating risks and ensuring a smooth transition.

Understanding Feature Flags

Feature flags, also known as feature toggles or feature switches, are a powerful technique used in software development to enable or disable certain features at runtime. They provide developers with fine-grained control over feature rollout, allowing them to manage feature releases, perform A/B testing, and mitigate risks associated with deploying new functionalities.

Hands-on

In this blog, we'll explore how to implement feature flags using the Flagsmith in a Go application built on the Go-Micro framework.

Generate prototype from WeDAA

Use below Architecture as reference and generate code from WeDAA

A Go Micro Service

Setup Flagsmith

Flagsmith is a feature flag tool that lets you manage features across web, mobile and server side applications.

It provides free account as well for SaaS offering. Signup, Create Organisation and add a feature flag.

Flagsmith setup

Flagsmith SDK

Include flagsmith SDK in go.mod

github.com/Flagsmith/flagsmith-go-client/v3 v3.4.0

Payment Handler

In this snippet, we initialize the Flagsmith client with our API key, retrieve the status of a feature flag, and conditionally execute feature-specific functionality based on the flag's status.

// src/handlers/payments.go
package handler

import (
"context"
"net/http"
flagsmith "github.com/Flagsmith/flagsmith-go-client/v3"
)

type PaymentsHandler struct{}

func (handler *PaymentsHandler) ProcessPayment(response http.ResponseWriter, request *http.Request) {
client := flagsmith.NewClient("<YOUR_FLAGSMITH_API_KEY>")
flags, _ := client.GetEnvironmentFlags(context.TODO())
isEnabled, _ := flags.IsFeatureEnabled("payment_gateway")

if isEnabled {
response.Write([]byte(`{ "message": "New Payment Gateway" }`))
} else {
response.Write([]byte(`{ "message": "Old Payment Gateway" }`))
}
}

Payment Controller

A sample controller with API to simulate payments.

// src/controllers/payments.go
package controllers

import (
"github.com/gorilla/mux"
"net/http"
"payments/handlers"
)

var paymentsHandler *handler.PaymentsHandler

type PaymentsController struct {}

func (paymentsController PaymentsController) RegisterRoutes(r *mux.Router) {
r.Handle("/api/payments",http.HandlerFunc(paymentsHandler.ProcessPayment)).Methods(http.MethodGet,http.MethodOptions)
}

Register Payments Controller

Add the following code in registerRoutes function of main.go in src

func registerRoutes(router *mux.Router) {
registerControllerRoutes(controllers.ManagementController{}, router)
registerControllerRoutes(controllers.PaymentsController{}, router) // Register Payments Controller
}

Execution

  1. Run the Go Micro Service using following commands

    go mod tidy
    go run .
  2. Check health of the service

    curl -i -H "Accept: application/json" http://localhost:6060/management/health/readiness

    Response should be as follows

    HTTP/1.1 200 OK
    Access-Control-Allow-Headers: Origin, Content-Type, Accept,Authorization
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
    Access-Control-Allow-Origin: *
    Content-Type: application/json
    Date: Wed, 17 Apr 2024 19:30:53 GMT
    Content-Length: 64

    {"components":{"readinessState":{"status":"UP"}},"status":"UP"}
  3. Test the new Payment API

    curl -i -H "Accept: application/json" http://localhost:6060/api/payments

    Response will be based on feature flag, whether new or old payment gateway is used.

    HTTP/1.1 200 OK
    Access-Control-Allow-Headers: Origin, Content-Type, Accept,Authorization
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
    Access-Control-Allow-Origin: *
    Content-Type: application/json
    Date: Wed, 17 Apr 2024 19:33:33 GMT
    Content-Length: 36

    { "message": "New Payment Gateway" }

Conclusion

Feature flags revolutionize the way software is developed and released. They empower developers to iterate quickly, gather feedback, and deliver value to users with confidence. By adopting feature flags in your development workflow, you can mitigate risks, improve deployment agility, and ultimately, delight your users with timely and impactful features.

· 5 min read

In today's scenario, we are seeing a shift from the monolithic landscape to microservice landscape. In simple words it can be termed as breaking a complex problem into smaller parts and making it easier to manage and develop. In Go to make this easier there is a framework GO MICRO - a helpful framework for building microservice applications with the Go programming language.

Why Microservice Architecture

Imagine a library where all the books used to be stacked in one massive room. It would be chaotic trying to find the book you needed among the towering shelves. But now, picture this library transformed into a series of smaller rooms, each dedicated to a specific genre—mystery, romance, science fiction, and so on. Each room is organized neatly, making it easier for readers to find the books they're looking for without getting lost in the sea of literature. This is similar to how microservices work in software—they break down complex applications into smaller, specialized components, making it simpler for developers to manage and maintain the software.

Now how do we build them??

Meet GOMICRO - A framework for distributed systems development

In the world of microservices, Go Micro is like your trusty sidekick. It helps developers build and manage microservices without all the headaches of doing it from scratch. Think of it as a toolbox full of handy tools to make building microservices easier and faster.

How Go Micro helps us??

  • Authentication and Authorization - Security is paramount in any architecture.Gomicro provide authorization.It seamlessly integrates with authentication providers like Keycloak, serving as a middleware to authenticate incoming requests.

  • Service Discovery - Effective communication among microservices necessitates a reliable service discovery mechanism. Go Micro simplifies this with built-in support for mdns (Multicast DNS) and offers integrable libraries (plugins) for popular options such as Eureka, Etcd, Consul, and NATS, among others.

  • Messaging - Messaging is an important aspect in the microservice architecture and event driven architectures. Go Micro eases the implementation of pub-sub models and other messaging paradigms with its plugin-based approach. Whether it's HTTP event message brokering or support for NATS, RabbitMQ, or Kafka, Go Micro has you covered.

  • Protocols - Go Micro supports communication via HTTP and RPC (Remote Procedure Call), providing abstractions for synchronous communication. This flexibility enables developers to choose the most suitable communication protocol for their specific use cases.

Tutorial

  1. Visit WeDAA: Go to WeDAA.

  2. Choose GoMicro Application: Navigate to the service tab in the sidebar and select Go. Drag and drop it onto the canvas.

  3. Connect a Database and Add Authentication: Connect a database to the application. Additionally, add authentication to secure the application. WeDAA supports Keycloak as an authentication IDP.

Sample GOMICRO WeDAA Architecture

  1. Fill in Required Details: Provide necessary details for the service and database connection.

Sample GOMICRO WeDAA Architecture

  1. Validate and Review: Click on validate to review the setup. Ensure everything is configured correctly.

Sample GOMICRO WeDAA Architecture

  1. Cloud Service Setup (Optional): Weeda has support for Azure, AWS and minikube.We can opt for one and fill in the necessary details to deploy applications in the specific cloud provider.we can skip this step for now by selecting none.

Sample GOMICRO WeDAA Architecture

  1. Generate Project Zip: After submission, a zip file containing the project will be generated.

Application Quickstart Guide

  1. Prerequisites: Ensure Docker is set up in advance if Keycloak is not configured as standalone or if PostgreSQL is not set up separately. Keycloak and PostgreSQL provided are Dockerized containers.

  2. Start Keycloak and PostgreSQL:

   docker compose -f docker/keycloak.yml up -d
docker compose -f docker/postgresql.yml up -d
  1. Start the Go Service: Once Keycloak and PostgreSQL services are up, start the Go service.

  2. Install Dependencies and Run the Service:

   go mod tidy
go run .

This command will install any required dependencies and then run the Go service.

Understanding the code

package main

func main() {
app.Setconfig()
migrate.MigrateAndCreateDatabase()
auth.SetClient()
config.InitializeDb()
port :=app.GetVal("GO_MICRO_SERVICE_PORT")
srv := micro.NewService(
micro.Server(mhttp.NewServer()),
)
opts1 := []micro.Option{
micro.Name("backendone"),
micro.Version("latest"),
micro.Address(":"+port),
}
srv.Init(opts1...)
r := mux.NewRouter().StrictSlash(true)
r.Use(corsMiddleware)
registerRoutes(r)
var handlers http.Handler = r

if err := micro.RegisterHandler(srv.Server(), handlers); err != nil {
logger.Fatal(err)
}

if err := srv.Run(); err != nil {
logger.Fatal(err)
}
}
  • Config Initialization - The application begins by loading configuration values from externalized YAML files into the environment. This ensures that the application has access to the necessary configuration parameters.

  • Database Migration - WeDAA supports migration for PostgreSQL databases. Using the go-migrate package library, a new database is created and data initialization is performed. This ensures that the database is properly set up and populated with initial data.

  • Authentication Setup - The code proceeds by setting up the authentication client,here Keycloak is being used as the identity provider (IDP) for authentication. This involves establishing a connection to Keycloak.

  • Microservice Setup - The micro.NewService function is a notation used by GoMicro to set up the microservice. Here, configurations are provided to the microservice via options. This step initializes the microservice and prepares it to handle incoming requests.

  • Router Setup - The code utilizes the mux router to create a routing setup. This involves defining endpoints and their corresponding handlers. The router is then registered with GoMicro, indicating that the microservice should use this router to handle incoming requests.

  • Application Execution - Finally, the application is run. This step starts the microservice, allowing it to listen for incoming requests and handle them according to the defined routing setup.

Conclusion

Go Micro leverages Go interfaces for each distributed system abstraction, rendering them pluggable and runtime-agnostic. This inherent flexibility allows developers to seamlessly integrate various underlying technologies, optimizing microservice development in a clean and efficient manner.