西维蜀黍

【Design Pattern】Microservices - Service per Team Pattern

Context

A high performance development organization consist of multiple teams. Each team is long-lived, small (typically 5-9 people), loosely coupled, autonomous, and cross-functional. Conway’s law says an architecture mirrors the communication structure of the organization that builds it. Consequently, an organization consisting of loosely coupled teams needs a loosely coupled architecture.

One such loosely coupled architecture is the microservice architecture. It’s an application style that structures an application as a loosely coupled set of services. Decompose by Subdomain and Decompose by business capability are patterns for identifying services and organizing them around business functionality. But what’s the relationship between services and teams?

One approach is a shared ownership model where multiple teams to work on each service as necessary. For example, each team might be responsible for implementing features that span multiple services. On the one hand, this approach aligns teams with the user experience. But on the other hand, it increases the amount of coordination needed between the teams. Also, the lack of code ownership increases the risk of poor code quality.

A better approach, which increases team autonomy and loose coupling, is a code/service ownership model. The team, which is responsible for a business function/capability owns a code base, which they deploy as one of more services. As a result, the team can freely develop, test, deploy and scale its services. They primarily interact with other teams in order to negotiate APIs.

A team should ideally own just one service since that’s sufficient to ensure team autonomy and loose coupling and each additional service adds complexity and overhead. A team should only deploy its code as multiple services if it solves a tangible problem, such as significantly reducing lead time or improving scalability or fault tolerance.

Since a team must be small, its cognitive capacity is limited. In order for the team to be productive, its code base should be scoped to not exceed the team’s cognitive capacity. In other words, it must ‘fit’ in the team’s heads. As a result, there is an upper bound on the size and/or complexity of a service.

  ...


【Design Pattern】Microservices - Serverless Deployment Pattern

Context

You have applied the Microservice architecture pattern and architected your system as a set of services. Each service is deployed as a set of service instances for throughput and availability.

  ...


【Design Pattern】Microservices - Multiple Service Instances per Host Pattern

Context

You have applied the Microservice architecture pattern and architected your system as a set of services. Each service is deployed as a set of service instances for throughput and availability.

  ...


【Design Pattern】Microservices - Service Instance per Host Pattern

Context

You have applied the Microservice architecture pattern and architected your system as a set of services. Each service is deployed as a set of service instances for throughput and availability.

  ...


【Design Pattern】Microservices - Service Instance per Container Pattern

Context

You have applied the Microservice architecture pattern and architected your system as a set of services. Each service is deployed as a set of service instances for throughput and availability.

  ...


【Golang】源码 - sync 包 - Once

// /usr/local/go/src/sync/once.go

// Once is an object that will perform exactly one action.
type Once struct {
	// done indicates whether the action has been performed.
	// It is first in the struct because it is used in the hot path.
	// The hot path is inlined at every call site.
	// Placing done first allows more compact instructions on some architectures (amd64/x86),
	// and fewer instructions (to calculate offset) on other architectures.
	done uint32
	m    Mutex
}
  ...


【Golang】使用 - sync.Once

package main

import (
    "fmt"
    "sync"
)

var doOnce sync.Once

func main() {
    DoSomething()
    DoSomething()
}

func DoSomething() {
    doOnce.Do(func() {
        fmt.Println("Run once - first time, loading...")
    })
    fmt.Println("Run this every time")
}
  ...


【Golang】设计模式 - Creational - Singleton

Singleton Pattern

Refer to https://swsmile.info/post/design-pattern-singleton-pattern/ for Singleton pattern.

Using init() functions

Package init() functions are guaranteed to be called only once and all called from a single thread ( they’re thread-safe unless you make them multi-threaded). But that makes you dependent on boot order. And you should not write codes in an *init ( )* that you need a guarantee of execution at any given time

type A struct {
	str string
}

var singleton *A

func init() {
	//initialize static instance on load
	singleton = &A{str: "abc"}
}

//GetInstanceA - get singleton instance pre-initialized
func GetInstanceA() *A {
	return singleton
}
  ...


【Golang】Test - Unit Test Coverage

Test Coverage

Test coverage is a term that describes how much of a package’s code is exercised by running the package’s tests. If executing the test suite causes 80% of the package’s source statements to be run, we say that the test coverage is 80%.

  ...


【Kubernetes】Kubelet 和 Pod

Kubernetes

kubernetes 是一个分布式的集群管理系统,在每个节点(node)上都要运行一个 worker 对容器进行生命周期的管理,这个 worker 程序就是 kubelet

简单地说,kubelet 的主要功能就是定时从某个地方获取节点上 Pod / Container 的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态。

集群状态下,kubelet 会从 master 上读取信息,但其实 kubelet 还可以从其他地方获取节点的 pod 信息。目前 kubelet 支持三种数据源:

  ...