自学内容网 自学内容网

GoLang 微服务学习笔记

https://www.bilibili.com/video/BV1Gg4y1u77D/?spm_id_from=333.337.search-card.all.click&vd_source=707ec8983cc32e6e065d5496a7f79ee6

目录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第1讲:为什么说云原生重构了互联网产品开发模式?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第2讲:云原生基础架构的组成以及云原生应用的特征

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=3

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述


第3讲:微服务架构是如何演进的?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=4

  • 通过垂直分层结构,可以让逻辑请求,也可以为不同层提供不同性能的硬件支持,比如用户界面层需要分发带宽,而业务逻辑层需要算力
    在这里插入图片描述
  • SOA有服务提供者与服务使用者
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

第4讲:DDD 领域场景分析的战略模式

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=5

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第5讲:为什么说 Service Meh 是下一代微服务架构?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.player.switch&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=6

在这里插入图片描述

  • 微服务拆分是复杂的,如下图拆分的微服务
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

第6讲: Go 语言开发快速回顾:语法、数据结构和流程控制

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=7

在这里插入图片描述
在这里插入图片描述

  • go 命令
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • go的指针应用
    在这里插入图片描述
    在这里插入图片描述
  • go的struct类型,也是go的类写法
    在这里插入图片描述
  • 在struct定义的变量,大写是包外可以访问,小写是包外部能访问
    在这里插入图片描述
  • go数组使用,声明时,需要固定数组大小
    在这里插入图片描述
  • go的切片slice,即动态数组
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • appand切片
    在这里插入图片描述
  • 也可以通过不指定数组大小,来声明切片
    在这里插入图片描述
  • go的map类型

在这里插入图片描述
在这里插入图片描述

  • map的获取
    在这里插入图片描述
  • 判断某键是否存在map中
    在这里插入图片描述
  • go 的for循环语句
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • go 中的switch不需要写case
  • go defer延迟执行函数,defer是先进后出(解析是历届解析)

在这里插入图片描述
在这里插入图片描述


第7讲: 如何使用 Go 更好地开发并发程序?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=8
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 以上总共生成了5个一组,共3组,15个(0-14)的生产;再收到queue的消息后,消费也会是15个,顺序是不确定的
    在这里插入图片描述
package main

import (
"fmt"
"time"
)

func send(ch chan int, begin int) {
for i := begin; i < begin+10; i++ {
ch <- i
}
}

func receive(ch <-chan int) {
val := <-ch
fmt.Println("receive:", val)
}

func main() {
ch1 := make(chan int)
ch2 := make(chan int)

go send(ch1, 0)
go receive(ch2)

time.Sleep(time.Second)

for {
select {
case val := <-ch1:
fmt.Println("get value from ch1:", val)
case ch2 <- 2:
fmt.Println("send value by ch2")
case <-time.After(time.Second):
fmt.Println("timeout")
return
}
}
}

在这里插入图片描述
在这里插入图片描述

package main

import (
"context"
"fmt"
"time"
)

const DB_ADDRESS = "db_address"
const CALCULATE_VALUE = "calculate_value"

func readDB(ctx context.Context, cost time.Duration) {
fmt.Println("db address is", ctx.Value(DB_ADDRESS))
select {
case <-time.After(cost):
fmt.Println("read data from db")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}

func calculate(ctx context.Context, cost time.Duration) {
fmt.Println("calculate value is", ctx.Value(CALCULATE_VALUE))
select {
case <-time.After(cost):
fmt.Println("calculate finish")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}

func main() {
ctx := context.Background()

ctx = context.WithValue(ctx, DB_ADDRESS, "localhost:10086")
ctx = context.WithValue(ctx, CALCULATE_VALUE, 1234)

ctx, cancel := context.WithTimeout(ctx, time.Second*2) //6秒则输出finish
defer cancel()

go readDB(ctx, time.Second*4)
go calculate(ctx, time.Second*4)

time.Sleep(time.Second * 5)
}


第8讲: 如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=8

  • 配置代理
    在这里插入图片描述

  • 安装插件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 项目需要引入的包
    在这里插入图片描述

redis的安装:
https://github.com/microsoftarchive/redis/releases (微软的Redis版)
https://gitee.com/qishibo/AnotherRedisDesktopManager/releases/tag/v1.7.1(Redis工具)
cmd输入,redis-server.exe --service-install redis.windows-service.conf 完成服务添加
cmd输入,redis-cli.exe ,输入keys * 查看缓存情况,也可以用redis工具查看

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package main

import (
"context"
"flag"
"fmt"
"github.com/longjoy/micro-go-course/section08/user/dao"
"github.com/longjoy/micro-go-course/section08/user/endpoint"
"github.com/longjoy/micro-go-course/section08/user/redis"
"github.com/longjoy/micro-go-course/section08/user/service"
"github.com/longjoy/micro-go-course/section08/user/transport"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
)

func main() {

//* 使用了flag定义了带有更多信息的变量
var (
// 服务地址和服务名
servicePort = flag.Int("service.port", 10086, "service port")
)

flag.Parse()

//* 空的 Context,用作 Context 树的根节点,是其他 Context 的父级,一般用于初始化 Context 链
ctx := context.Background()
errChan := make(chan error)

//* 使用dao包,用于数据库操作,打开数据库,初始化db (Gorm)
err := dao.InitMysql("127.0.0.1", "3306", "root", "***", "user")
if err != nil {
log.Fatal(err)
}

//* 打开redis
err = redis.InitRedis("127.0.0.1", "6379", "")
if err != nil {
log.Fatal(err)
}

//* 把UserDAOImpl对象(包含SelectByEmail与Save)给到service,初始化userService,见代码1
userService := service.MakeUserServiceImpl(&dao.UserDAOImpl{})

//* UserEndpoints是2个endpoint.Endpoint类型的函数,如下
//* type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
//* 并make初始化,见代码2
userEndpoints := &endpoint.UserEndpoints{
endpoint.MakeRegisterEndpoint(userService),
endpoint.MakeLoginEndpoint(userService),
}

//* 把路由封装起来,之后启动服务器,见代码3
r := transport.MakeHttpHandler(ctx, userEndpoints)

//* 首先,定义了一个 servicePort 并创建了一个错误通道 errChan。
//* 然后,使用 http.NewServeMux() 创建一个路由处理程序 r,并为根路由添加了一个简单的处理函数。
//* 启动了两个 goroutine:一个用于启动 HTTP 服务器,另一个用于监听系统信号。
//* 最后,从 errChan 接收错误信息,当按下 Ctrl+C 时,会接收到 SIGINT 信号,程序打印错误信息并退出。
go func() {
errChan <- http.ListenAndServe(":"+strconv.Itoa(*servicePort), r)
}()

go func() {
// 监控系统信号,等待 ctrl + c 系统信号通知服务关闭
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
errChan <- fmt.Errorf("%s", <-c)
}()

error := <-errChan
log.Println(error)

}

  • 代码1:MakeUserServiceImpl操作
//* 定义了UserService接口
type UserService interface {
// 登录接口
Login(ctx context.Context, email, password string) (*UserInfoDTO, error)
// 注册接口
Register(ctx context.Context, vo *RegisterUserVO) (*UserInfoDTO, error)
}

//* UserServiceImpl为接口的一个实现,并有一个userDAO的对象值
type UserServiceImpl struct {
userDAO dao.UserDAO
}

func MakeUserServiceImpl(userDAO dao.UserDAO) UserService {
return &UserServiceImpl{
userDAO: userDAO,
}
}

//* 以下函数实现了userService接口的一个具体实现UserServiceImpl
//* 通过userService取到userDAO,符合依赖倒置原则
func (userService *UserServiceImpl) Login(ctx context.Context, email, password string) (*UserInfoDTO, error){
user, err := userService.userDAO.SelectByEmail(email)
......
}

func (userService UserServiceImpl) Register(ctx context.Context, vo *RegisterUserVO) (*UserInfoDTO, error){
......
}
  • 代码2:MakeLoginEndpoint:Endpoint的初始化
type UserEndpoints struct {
RegisterEndpoint  endpoint.Endpoint
LoginEndpoint endpoint.Endpoint
}

//* 发送数据格式
type LoginRequest struct {
Email string
Password string
}

//* 接受数据格式
type LoginResponse struct {
//* 转换json时,这个字段名为user_info
UserInfo *service.UserInfoDTO `json:"user_info"`
}

//* 返回endpoint.Endpoint函数,接受LoginRequest格式,返回LoginResponse格式
func MakeLoginEndpoint(userService service.UserService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
//* 通过指针,断言了request的类型,后面的req.Email, req.Password就可以成立
req := request.(*LoginRequest)
userInfo, err := userService.Login(ctx, req.Email, req.Password)
//* 通过userService返回需要的userInfo查询数据,并返回
return &LoginResponse{UserInfo:userInfo}, err

}
}
  • 代码3
package transport

import (
"context"
"encoding/json"
"errors"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/gorilla/mux"
"github.com/longjoy/micro-go-course/section08/user/endpoint"
"net/http"
"os"
)

var (
ErrorBadRequest = errors.New("invalid request parameter")
)

// MakeHttpHandler make http handler use mux
func MakeHttpHandler(ctx context.Context, endpoints *endpoint.UserEndpoints) http.Handler {
//* mux 是一个强大的 HTTP 路由和分发库
r := mux.NewRouter()

//* 日志打印
kitLog := log.NewLogfmtLogger(os.Stderr)

kitLog = log.With(kitLog, "ts", log.DefaultTimestampUTC)
kitLog = log.With(kitLog, "caller", log.DefaultCaller)

//* 配置服务器的错误处理和错误编码
options := []kithttp.ServerOption{
kithttp.ServerErrorHandler(transport.NewLogErrorHandler(kitLog)),
kithttp.ServerErrorEncoder(encodeError),
}

//* 建立一个路由
r.Methods("POST").Path("/register").Handler(kithttp.NewServer(
endpoints.RegisterEndpoint, //绑定处理的endpoint
decodeRegisterRequest, //数据获取解析,并交给endpoint处理
encodeJSONResponse, //把结果转成Json,发送给客户端,是发送前的处理
options...,
))


r.Methods("POST").Path("/login").Handler(kithttp.NewServer(
endpoints.LoginEndpoint,
decodeLoginRequest,
encodeJSONResponse,
options...,
))

return r
}
func decodeRegisterRequest(_ context.Context, r *http.Request) (interface{}, error) {
username := r.FormValue("username")
password := r.FormValue("password")
email := r.FormValue("email")

if username == "" || password == "" || email == ""{
return nil, ErrorBadRequest
}
return &endpoint.RegisterRequest{
Username:username,
Password:password,
Email:email,
},nil
}


func decodeLoginRequest(_ context.Context, r *http.Request) (interface{}, error) {
email := r.FormValue("email")
password := r.FormValue("password")

if email == "" || password == "" {
return nil, ErrorBadRequest
}
return &endpoint.LoginRequest{
Email:email,
Password:password,
},nil
}

func encodeJSONResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json;charset=utf-8")
return json.NewEncoder(w).Encode(response)
}



func encodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
switch err {
default:
w.WriteHeader(http.StatusInternalServerError)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}



第9讲: 货运平台应用的微服务划分

https://https://www.bilibili.com/video/BV1Gg4y1u77D/?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=10

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第10讲: 微服务 Docker 容器化部署和 Kubernete 容器编排

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.player.switch&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=11

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第11讲: 如何结合 Jenkin 完成持续化集成和自动化测试?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=12

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第12讲: 服务注册与发现如何满足服务治理?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=13

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第13讲: 如何基于 Conul 给微服务添加服务注册与发现?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=14

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第14讲: 如何在 Go-kit 和 Service Meh 中进行服务注册与发现?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=15

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第15讲: 微服务间如何进行远程方法调用?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.player.switch&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=16

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第16讲: Go RPC 如何实现服务间通信?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=17

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


第17讲: Go-kit 如何集成 gRPC?

https://www.bilibili.com/video/BV1Gg4y1u77D?spm_id_from=333.788.videopod.episodes&vd_source=707ec8983cc32e6e065d5496a7f79ee6&p=19
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结束:

作为想了解下golang的微服务部分,就先看到这里,此教程给到众多惊喜;
云原生与微服务是当下开发大系统有力的解决方案,这篇教程更像是一场淋漓尽致的讲座,介绍了当下的云原生的各个构成,非常值得一学。


原文地址:https://blog.csdn.net/qq_17523181/article/details/145143537

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!