Go-Micro服务熔断初步使用
简介Go-Micro服务熔断初步使用
1、服务熔断库安装
go get github.com/afex/hystrix-go/hystrix
2、客户端熔断添加
package main
import (
"context"
"github.com/afex/hystrix-go/hystrix"
"github.com/gin-gonic/gin"
"github.com/micro/go-micro"
"github.com/micro/go-micro/client"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/web"
"github.com/micro/go-plugins/registry/consul"
"log"
services "micro-home/service/model"
"strconv"
)
func InitMiddleware(service services.StudentListService) gin.HandlerFunc {
return func(context *gin.Context) {
context.Keys = make(map[string]interface{})
context.Keys["student_service"] = service
context.Next()
}
}
//装饰器
type logWrapper struct {
client.Client
}
//每次调用都会执行这个方法
func (c *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
log.Print("请求")
return c.Client.Call(ctx, req, rsp)
}
func NewLogWrapper(c client.Client) client.Client {
return &logWrapper{c}
}
func main() {
register := consul.NewRegistry(func(options *registry.Options) {
options.Addrs = []string{
"192.168.1.171:8500",
"192.168.1.177:8500",
"192.168.1.178:8500",
}
})
//微服务需要注册
homeService := micro.NewService(
micro.Name("micro-home-client"),
micro.Registry(register),
micro.WrapClient(NewLogWrapper), //在注册时只需要传入方法名即可,底层会自动给这个方法传入client
)
//实例化服务
studentListService := services.NewStudentListService("student-service", homeService.Client())
routers := gin.Default()
routers.Use(InitMiddleware(studentListService)) //使用中间件,将服务传递到context中
routers.GET("/", func(context *gin.Context) {
service := context.Keys["student_service"].(services.StudentListService)
number := context.DefaultQuery("number", "0")
num, err := strconv.Atoi(number)
if err != nil {
num = 1
}
if num <= 0 {
num = 1
}
//熔断配置
hystrix.ConfigureCommand("student-service", hystrix.CommandConfig{
Timeout: 1000,
})
var studentListResponse *services.StudentListResponse
//熔断处理
err = hystrix.Do("student-service", func() error {
studentListResponse, err = service.GetStudentListService(context, &services.StudentListRequest{
Num: int32(num),
})
return err
}, nil)//fallback这里为nil,可以自己定义需要返回的处理,如果这里调用服务出现问题会直接抛出异常,如果不想抛出异常,可以实现对应的方法,下面我们会处理
if err != nil {
context.JSON(400, gin.H{
"status": "",
"data": err.Error(),
})
} else {
context.JSON(200, gin.H{
"status": studentListResponse.Status,
"data": studentListResponse.Data,
})
}
})
service := web.NewService(
web.Name("home-service-api"),
web.Address(":8081"),
web.Handler(routers),
web.Registry(register),
)
service.Run()
}
3、将服务接口处理时间延迟,可以睡眠几秒钟
4、熔断返回处理
package main
import (
"context"
"github.com/afex/hystrix-go/hystrix"
"github.com/gin-gonic/gin"
"github.com/micro/go-micro"
"github.com/micro/go-micro/client"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/web"
"github.com/micro/go-plugins/registry/consul"
"log"
services "micro-home/service/model"
"strconv"
)
func InitMiddleware(service services.StudentListService) gin.HandlerFunc {
return func(context *gin.Context) {
context.Keys = make(map[string]interface{})
context.Keys["student_service"] = service
context.Next()
}
}
//装饰器
type logWrapper struct {
client.Client
}
//每次调用都会执行这个方法
func (c *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
log.Print("请求")
return c.Client.Call(ctx, req, rsp)
}
func NewLogWrapper(c client.Client) client.Client {
return &logWrapper{c}
}
func main() {
register := consul.NewRegistry(func(options *registry.Options) {
options.Addrs = []string{
"192.168.1.171:8500",
"192.168.1.177:8500",
"192.168.1.178:8500",
}
})
//微服务需要注册
homeService := micro.NewService(
micro.Name("micro-home-client"),
micro.Registry(register),
micro.WrapClient(NewLogWrapper), //在注册时只需要传入方法名即可,底层会自动给这个方法传入client
)
//实例化服务
studentListService := services.NewStudentListService("student-service", homeService.Client())
routers := gin.Default()
routers.Use(InitMiddleware(studentListService)) //使用中间件,将服务传递到context中
routers.GET("/", func(context *gin.Context) {
service := context.Keys["student_service"].(services.StudentListService)
number := context.DefaultQuery("number", "0")
num, err := strconv.Atoi(number)
if err != nil {
num = 1
}
if num <= 0 {
num = 1
}
hystrix.ConfigureCommand("student-service", hystrix.CommandConfig{
Timeout: 1000,
})
var studentListResponse *services.StudentListResponse
err = hystrix.Do("student-service", func() error {
studentListResponse, err = service.GetStudentListService(context, &services.StudentListRequest{
Num: int32(num),
})
return err
}, func(e error) error {//熔断处理,当发生熔断后,就返回如下数据
var studentModel []*services.StudentModel
studentModel = append(studentModel, &services.StudentModel{
Id: 0,
Name: "熔断返回",
Sex: "女",
})
studentListResponse = &services.StudentListResponse{
Status: 200,
Data: studentModel,
}
return nil
})
if err != nil {
context.JSON(400, gin.H{
"status": "",
"data": err.Error(),
})
} else {
context.JSON(200, gin.H{
"status": studentListResponse.Status,
"data": studentListResponse.Data,
})
}
})
service := web.NewService(
web.Name("home-service-api"),
web.Address(":8081"),
web.Handler(routers),
web.Registry(register),
)
service.Run()
}
5、可以使用go-micro的wrapper来对熔断进行封装
快速生成表格
《康熙王朝》是一部非常优秀的电视连续剧,陈道明演的康熙是我觉得最有帝王气魄,让人意犹未尽,本文主要记录一小段非常经典的对白。
top命令用于实时显示系统中进程占用资源的情况。该命令还可以按照CPU的使用、内存使用和执行时间对系统进程进行排序显示。同时top命令还可以通过交互命令进行设定显示
默认情况下 pip 使用的是国外的镜像,在下载的时候速度非常慢,本文我们介绍使用国内源对pip进行加速。
Electron页面跳转、浏览器打开链接和打开新窗口
Docker编译镜像出现:fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.12/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.2c4ac24e.tar.gz: No such file or directory问题
在Mac电脑中,如何对Git的用户名和密码进行修改呢?起初不懂Mac,所以整了很久,本文将记录如何对这个进行操作,以便后期使用。
在使用Git的过程中,不想每次都输入用户名和密码去拉取代码,所以就需要保存这些信息,那么既然有保存了,就必须有清除功能。