- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章go-kit组件使用hystrix中间件的操作由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
使用go-kit中间件时,一般在endpoint中进行中间件的开发.
在endpoint层插入hystrix中间件的插入.
。
1
2
3
4
5
6
7
|
func MakeEndpoint (svc services.StringService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(*StringService.Request)
rep , err := svc.Diff(ctx , req)
return rep , err
}
}
|
go-kit使我们更注重对服务逻辑的开发,对中间过程的省略会减少很多的错误发生.
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package main
import (
"balencegrpc/services"
"balencegrpc/router"
"balencegrpc/proto"
"balencegrpc/discover"
"balencegrpc/endpoints"
"github.com/go-kit/kit/circuitbreaker"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
"log"
"net"
)
func main() {
//svc := new()
svc := services.ServiceI{}
endpoint := circuitbreaker.Hystrix("testname")(endpoints.MakeEndpoint(svc))
lis , err := net.Listen("tcp" , ":8081")
if err != nil {
log.Println(err)
return
}
router := router.NewRouter(svc , endpoint)
grpcserver := grpc.NewServer()
c := discover.Service{}
grpc_health_v1.RegisterHealthServer(grpcserver , &c)
StringService.RegisterStringServiceServer(grpcserver , router)
rs := discover.NewService()
rs.Register("127.0.0.1" , 8081)
grpcserver.Serve(lis)
}
|
我们在main.go中进行添加hystrix对endpoint进行封装,,使用hystrix进行服务熔断的处理。其实使用go-kit封装的。也可以自行封装一个中间件,在创建endpoint时进行封装 。
补充:go-kit微服务熔断机制的实现 。
在微服务架构中,每一个微服务都是一个独立的业务功能单元,而一个应用一般由多个微服务组成,微服务之间的交互是通过RPC(远程过程调用)完成.
比如,我们的应用是微服务A调用微服务B和微服务C来完成的,而微服务B又需要调用微服务D,微服务D又需要调用微服务E。如果在调用的链路上对微服务E的调用,响应时间过长或者服务不可用,那么对微服务D的调用就会占用越来越多的系统资源,进而引起微服务D的系统崩溃,微服务D的不可用,又会连锁反应的引起微服务B崩溃,进而微服务A崩溃,最终导致整个应用不可用。这也就是所谓的“雪崩效应”.
。
go-kit 提供了三种熔断 。
1、 gobreaker 。
2、 handy 。
3、 hystrix-go 。
hystrix用的比较多,我们来介绍下go-kit中hystrix的使用方法 。
go-kit的hystrix 。
Middleware的实现 。
1、 Hystrix返回Middleware 此中间件会在原来的endPoint包一层Hystrix的endPoint 。
2、 hystrix通过传入的commanName获取对应的Hystrix的设置,并设置run失败时运行的fallback函数为nil 。
3、 我们也可以自己实现middleware包装endPoint 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func Hystrix(commandName string) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var resp interface{}
if err := hystrix.Do(commandName, func() (err error) {
resp, err = next(ctx, request)
return err
}, nil); err != nil {
return nil, err
}
return resp, nil
}
}
}
|
客户端hystrix配置 。
1、Timeout 【请求超时的时间】 。
2、ErrorPercentThreshold【允许出现的错误比例】 。
3、SleepWindow【熔断开启多久尝试发起一次请求】 。
4、MaxConcurrentRequests【允许的最大并发请求数】 。
5、RequestVolumeThreshold 【波动期内的最小请求数,默认波动期10S】 。
1
2
3
4
5
6
7
8
|
commandName := "my-endpoint"
hystrix.ConfigureCommand(commandName, hystrix.CommandConfig{
Timeout: 1000 * 30,
ErrorPercentThreshold: 1,
SleepWindow: 10000,
MaxConcurrentRequests: 1000,
RequestVolumeThreshold: 5,
})
|
增加熔断中间件的包装 。
1
2
3
|
breakerMw := circuitbreaker.Hystrix(commandName)
//增加熔断中间件
reqEndPoint = breakerMw(reqEndPoint)
|
。
1、protobuf文件及生成对应的go文件 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
syntax = "proto3";
// 请求书详情的参数结构 book_id 32位整形
message BookInfoParams {
int32 book_id = 1;
}
// 书详情信息的结构 book_name字符串类型
message BookInfo {
int32 book_id = 1;
string book_name = 2;
}
// 请求书列表的参数结构 page、limit 32位整形
message BookListParams {
int32 page = 1;
int32 limit = 2;
}
// 书列表的结构 BookInfo结构数组
message BookList {
repeated BookInfo book_list = 1;
}
// 定义 获取书详情 和 书列表服务 入参出参分别为上面所定义的结构
service BookService {
rpc GetBookInfo (BookInfoParams) returns (BookInfo) {}
rpc GetBookList (BookListParams) returns (BookList) {}
}
|
生成对应的go语言代码文件:protoc --go_out=plugins=grpc:. book.proto (其中:protobuf文件名为:book.proto) 。
注:由于演示熔断机制,也就是Server出现问题的时候进行熔断,因此本文Server端代码可以不用.
2、Client端代码 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
package main
import (
"MyKit"
"context"
"fmt"
"github.com/afex/hystrix-go/hystrix"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/etcdv3"
"github.com/go-kit/kit/sd/lb"
"google.golang.org/grpc"
"io"
"time"
)
func main() {
var (
//注册中心地址
etcdServer = "127.0.0.1:2379"
//监听的服务前缀
prefix = "/services/book/"
ctx = context.Background()
)
//对hystrix进行配置
commandName:="my_endpoint"
hystrix.ConfigureCommand(commandName,hystrix.CommandConfig{
Timeout:1000*3, //超时
MaxConcurrentRequests:100, //最大并发的请求数
RequestVolumeThreshold:5,//请求量阈值
SleepWindow:10000, //熔断开启多久尝试发起一次请求
ErrorPercentThreshold:1, //误差阈值百分比
})
breakerMw:=circuitbreaker.Hystrix(commandName) //定义熔断器中间件
options := etcdv3.ClientOptions{
DialTimeout: time.Second * 3,
DialKeepAlive: time.Second * 3,
}
//连接注册中心
client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
if err != nil {
panic(err)
}
logger := log.NewNopLogger()
//创建实例管理器, 此管理器会Watch监听etc中prefix的目录变化更新缓存的服务实例数据
instancer, err := etcdv3.NewInstancer(client, prefix, logger)
if err != nil {
panic(err)
}
//创建端点管理器, 此管理器根据Factory和监听的到实例创建endPoint并订阅instancer的变化动态更新Factory创建的endPoint
endpointer := sd.NewEndpointer(instancer, reqFactory, logger) //reqFactory自定义的函数,主要用于端点层(endpoint)接受并显示数据
//创建负载均衡器
balancer := lb.NewRoundRobin(endpointer)
/**
我们可以通过负载均衡器直接获取请求的endPoint,发起请求
reqEndPoint,_ := balancer.Endpoint()
*/
/**
也可以通过retry定义尝试次数进行请求
*/
reqEndPoint := lb.Retry(3, 100*time.Second, balancer) //请求次数为3,时间为10S(时间需要多于服务器限流时间3s)
//增加熔断中间件
reqEndPoint=breakerMw(reqEndPoint)
//现在我们可以通过 endPoint 发起请求了
req := struct{}{}
for i:=0;i<20;i++ { //发生20次请求
ctx=context.Background()
if _, err = reqEndPoint(ctx, req); err != nil {
//panic(err)
fmt.Println("当前时间: ", time.Now().Format("2006-01-02 15:04:05.99"),"\t第",i+1,"次")
fmt.Println(err)
time.Sleep(1*time.Second)
}
}
}
//通过传入的 实例地址 创建对应的请求endPoint
func reqFactory(instanceAddr string) (endpoint.Endpoint, io.Closer, error) {
return func(ctx context.Context, request interface{}) (interface{}, error) {
conn, err := grpc.Dial(instanceAddr, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
panic("connect error")
}
defer conn.Close()
bookClient := book.NewBookServiceClient(conn)
bi, _ := bookClient.GetBookInfo(context.Background(), &book.BookInfoParams{BookId: 1})
fmt.Println("获取书籍详情")
fmt.Println("bookId: 1", " => ", "bookName:", bi.BookName)
fmt.Println("请求服务成功: ", instanceAddr,"当前时间为:",time.Now().Format("2006-01-02 15:04:05.99"))
/*bl, _ := bookClient.GetBookList(context.Background(), &book.BookListParams{Page: 1, Limit: 10})
fmt.Println("获取书籍列表")
for _, b := range bl.BookList {
fmt.Println("bookId:", b.BookId, " => ", "bookName:", b.BookName)
}*/
return nil, nil
}, nil, nil
}
|
3、运行及分析 。
直接运行Client端(不用启动etcd、Server),效果如下:
通过上面的输出记录可以验证我们的配置:
1、 前5条波动期内的错误,没有触发circuit开启(RequestVolumeThreshold:5,//请求量阈值) 。
2、 circuit开启后请求熔断生效(输出内容:hystrix: circuit open) 。
3、 circuit开启10S后,SleepWindow测试发起请求设置生效(第16次输出的内容;设置:SleepWindow:10000, //熔断开启多久尝试发起一次请求) 。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我。如有错误或未考虑完全的地方,望不吝赐教.
原文链接:https://blog.csdn.net/Xiang_lhh/article/details/115495321 。
最后此篇关于go-kit组件使用hystrix中间件的操作的文章就讲到这里了,如果你想了解更多关于go-kit组件使用hystrix中间件的操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我没有使用 Sprite Kit 的经验。我想知道是否有类似 Cocos2D 的东西 调度程序在 SpriteKit 中?如果不是,应该用什么 NSTimer 是唯一的选择吗?我想如果唯一的选择是使用
在我的 Sprite Kit 应用程序中,我想要一个粘性物理体:任何与该物体接触的动态物体都不会反弹,而是与其保持连接。 是否有任何属性可以执行这种粘性行为?如果不能,如何实现? 最佳答案 SKNod
在我的 Sprite Kit 应用程序中,我想要一个粘性物理体:任何与该物体接触的动态物体都不会反弹,而是与其保持连接。 是否有任何属性可以执行这种粘性行为?如果不能,如何实现? 最佳答案 SKNod
我正在构建一个 flappy bird 游戏,其中一半关卡在水上,另一半关卡在水下。 如果您的小鸟在空中,则存在规律的重力,当您轻敲时,会施加一个直线向上的冲量。 如果你的鸟在水中,重力应该在负方向(
我正在使用 Sprite 套件制作游戏,现在我想知道让对象“跳跃”的最佳方法是什么。所以它将以几个像素垂直启动。 这是我要跳转的对象的代码: SKSpriteNode *sprite = [SKSpr
我很好奇如何为我的游戏显示像素艺术。现在我只是将 SKScene 的大小调整为 sceneWithSize:CGSizeMake(256, 192) 这是正确的方法还是有更好的方法来进行这种排序任务?
我不知道如何阻止节点旋转。 为什么允许旋转没有禁用它? 这是我描述我的节点的方式: SKSpriteNode *badguy = [SKSpriteNode spriteNodeWithTexture
我在 Xcode 中使用 Sprite Kit,我想知道如何更改重力方向。默认重力方向为“X”,您可以在轴下方的图形上想象。如果我想更改为“Y”怎么办。 我的目标是给予物体坠落效果。它就像从高处坠落并
我想知道如何在屏幕外删除我的 SKNode 以帮助我的游戏运行更流畅。 如何在 Sprite Kit 上做到这一点 非常感谢 最佳答案 https://stackoverflow.com/a/2419
我有一个关于“WEBKIT”的问题。什么是 WebKit?什么是 Android WebKit 以及它与 IOS WEbKit 有何不同?如何使用 WebKit?想要完美清晰的答案。有人有什么想法吗?
在我的 Sprite 套件游戏中,当两个 Sprite 发生碰撞时,我使用 SKAction 播放 mp3 文件。虽然游戏运行良好,但我在第一次播放声音时注意到游戏中有一个小的“hickup”。整个游
我正在创建一个游戏,对于我的角色,他的腿和躯干有单独的动画,因此它们是具有单独物理体的单独节点。我在将躯干和腿连接在一起时遇到了很多麻烦,但是,将它们连接起来不是问题,让它们保持连接才是问题。在四处走
Sprite Kit 是否具有相当于 9 切片缩放的 Sprite ? 我试过谷歌搜索,但没有找到任何东西,但是......它通常是一个在不同框架中有不同名称的功能。所以我可能会错过它。 最佳答案 S
我正在 Sprite Kit 中制作“Achtung die kurve”克隆。对于不断移动的队伍/球员,我使用 CGMutablePathRef 和 SKShapeNode。在更新方法中我正在这样做
我正在尝试开发一个building information model iPad 的查看器,我面临着当前的挑战。我应该使用 SpriteKit 还是 SceneKit?我知道 SceneKit 是用来
在 iPhone ios10 上安装后,我的 ready to ship appstore 应用程序不再播放声音!帮助!使用 ios9,一切都完美运行 SKAction.playSoundFileNa
如何将 CIPixellate 核心图像过滤器添加到 Sprite Kit 场景中? 我有一个 SpriteKit 场景,它是 SKScene 或其子类。 我想在场景中添加一个核心图像过滤器。特别是
这似乎不是一个明智的问题,但我心中有一些困惑,我想澄清。在Apple的2d游戏框架Sprite kit中,通常建议将节点相关的数据存储在Plist中,然后在代码中需要时检索。我不明白的是,在使用 .s
这似乎不是一个明智的问题,但我心中有一些困惑,我想澄清。在Apple的2d游戏框架Sprite kit中,通常建议将节点相关的数据存储在Plist中,然后在代码中需要时检索。我不明白的是,在使用 .s
我试图让用户能够将 skspritenode 拖到 UIImageView 和 UIButton 上,但每当我创建场景时,它都会出现在 UI 元素后面。我该如何解决这个问题? 最佳答案 恐怕这是不可能
我是一名优秀的程序员,十分优秀!