Skip to content

Commit

Permalink
整合服务降级用户
Browse files Browse the repository at this point in the history
  • Loading branch information
=charlie committed Nov 16, 2021
1 parent b34008c commit 3b56f42
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module service.gomicro.test
go 1.16

require (
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
github.com/go-kit/kit v0.12.0
github.com/google/uuid v1.1.2
github.com/gorilla/mux v1.8.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
Expand Down
86 changes: 86 additions & 0 deletions hystrixtest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"fmt"
"github.com/afex/hystrix-go/hystrix"
"math/rand"
"sync"
"time"
)

type Product struct {
ID int
Title string
Price int
}

func getProduct() (Product, error) {
r := rand.Intn(10)
if r < 6 { //模拟api卡顿和超时效果
time.Sleep(time.Second * 4)
}
return Product{
ID: 101,
Title: "Golang从入门到精通",
Price: 12,
}, nil
}

func RecProduct() (Product, error) {
return Product{
ID: 999,
Title: "推荐商品",
Price: 120,
}, nil

}

func main() {

rand.Seed(time.Now().UnixNano())
configA := hystrix.CommandConfig{ //创建一个hystrix的config
Timeout: 3000, //command运行超过3秒就会报超时错误
MaxConcurrentRequests: 5, //控制最大并发数为5,如果超过5会调用我们传入的回调函数降级
RequestVolumeThreshold: 5, // 在一个统计窗口没处理的请求量达到阈值,才会进行熔断与否的判断
ErrorPercentThreshold: 20, // 在一个 %20的处理失败 处理熔断服务
SleepWindow: int(time.Second * 10), // 熔断后多久尝试是否恢复
}
hystrix.ConfigureCommand("get_prod", configA) //hystrix绑定command
c,_,_:=hystrix.GetCircuit("get_prod") // 熔断指针 ,bool表示是否能取到 error
resultChan := make(chan Product, 1)

wg := sync.WaitGroup{}

for i := 0; i < 20; i++ {
go (func() {
wg.Add(1)
defer wg.Done()
// Go为异步
errs := hystrix.Do("get_prod", func() error { //使用hystrix来讲我们的操作封装成command,hystrix返回值是一个chan error
p, _ := getProduct() //这里会随机延迟0-4秒
resultChan <- p
return nil //这里返回的error在回调中可以获取到,也就是下面的e变量
}, func(e error) error {
fmt.Println(e)
rcp, err := RecProduct() //推荐商品,如果这里的err不是nil,那么就会忘errs中写入这个err,下面的select就可以监控到
resultChan <- rcp
return err
})
if errs!=nil {
fmt.Println(errs)
}else {
select {
case getProd := <-resultChan:
fmt.Println(getProd)
}
}

fmt.Println(c.IsOpen())
fmt.Println(c.AllowRequest())
})()

}
wg.Wait()

time.Sleep(time.Second * 1)
}
34 changes: 34 additions & 0 deletions product2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"fmt"
"github.com/afex/hystrix-go/hystrix"
"log"
"service.gomicro.test/util"
"time"
)



func main() {
configA := hystrix.CommandConfig{
Timeout: 2000,
MaxConcurrentRequests: 5,
RequestVolumeThreshold: 3,
SleepWindow: int(time.Second * 10),
ErrorPercentThreshold: 20,
}

hystrix.ConfigureCommand("getuser", configA)
err := hystrix.Do("getuser", func() error {
res, err := util.GetUser() //调用方法
fmt.Println(res)
return err
}, func(e error) error {
fmt.Println("降级用户")
return e
})
if err != nil {
log.Fatal(err)
}
}
67 changes: 67 additions & 0 deletions util/UserUtil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package util

import (
"context"
"fmt"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/consul"
"github.com/go-kit/kit/sd/lb"
httptransport "github.com/go-kit/kit/transport/http"
consulapi "github.com/hashicorp/consul/api"
"io"
"net/url"
"os"
"service.gomicro.test/DirectServices"
"time"
)

func GetUser() (string, error) {
//第一步创建client
{
config := consulapi.DefaultConfig() //初始化consul的配置
config.Address = "localhost:8500" //consul的地址
api_client, err := consulapi.NewClient(config) //根据consul的配置初始化client
if err != nil {
return "", err
}
client := consul.NewClient(api_client) //根据client创建实例

var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stdout)
var Tag = []string{"primary"}
instancer := consul.NewInstancer(client, logger, "userservice", Tag, true) //最后的true表示只有通过健康检查的服务才能被得到
{
factory := func(service_url string) (endpoint.Endpoint, io.Closer, error) { //factory定义了如何获得服务端的endpoint,这里的service_url是从consul中读取到的service的address我这里是192.168.3.14:8000
tart, _ := url.Parse("http://" + service_url) //server ip +8080真实服务的地址
return httptransport.NewClient("GET", tart, DirectServices.GetUserInfoRequest, DirectServices.GetUserInfoResponse).Endpoint(), nil, nil //我再GetUserInfo_Request里面定义了访问哪一个api把url拼接成了http://192.168.3.14:8000/v1/user/{uid}的形式
}
endpointer := sd.NewEndpointer(instancer, factory, logger)
endpoints, err := endpointer.Endpoints() //获取所有的服务端当前server的所有endpoint函数
if err != nil {
return "", err
}
fmt.Println("服务有", len(endpoints), "条")

mylb := lb.NewRandom(endpointer, time.Now().UnixNano()) //使用go-kit自带的轮询

for {
getUserInfo, err := mylb.Endpoint() //写死获取第一个
ctx := context.Background() //第三步:创建一个context上下文对象

//第四步:执行
res, err := getUserInfo(ctx, DirectServices.UserRequest{Uid: 101})
if err != nil {
return "", err
}
//第五步:断言,得到响应值
userinfo := res.(DirectServices.UserResponse)
return userinfo.Result, nil
}

}
}
}
}

0 comments on commit 3b56f42

Please sign in to comment.