-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
=charlie
committed
Nov 16, 2021
1 parent
b34008c
commit 3b56f42
Showing
5 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
|
||
} | ||
} | ||
} | ||
} |