最新要闻
- 手机问题:努比亚z30pro续航怎么样
- 天天播报:RTX 4060今晚上市后 尴尬一幕出现:日本线下仅1人排队买首发
- 重点聚焦!女子疑坐公交不付钱:踩猫威胁司机
- 2023年上半年剧集报告发布:国产剧口碑上涨显著
- 微动态丨GDDR7显存明年就有了!RTX 50可能先吃螃蟹
- 800V高压架构+二代XNGP辅助驾驶上车!小鹏G6上市:20.99万起 滚动
- iGame人气王!七彩虹iGame RTX 4060 Ultra W OC显卡图赏
- 每日观察!《异世界》魔径—給异世界点颜色看看 楔子
- 【全球速看料】山东龙凤四胞胎同圆大学梦 网友:四倍辛苦 四倍幸福
- 当前信息:可以换电的纯电MPV来了!全新上汽大通大家MIFA 9车电分离版上市
- 旗袍发型教程_旗袍发型-天天即时看
- 阿斯巴甜将被世卫列为“可能致癌物质”:元气森林、奈雪火速回应
- 丫丫解锁新玩具竹笼:一刻也没闲着
- 无糖可乐不能喝了?或含致癌物阿斯巴甜
- 天天观焦点:Steam将AI作图游戏拒之门外!除非能证明拥有版权
- 环球热讯:红米Redmi Pad 2平板跑分曝光:配骁龙680 或近期发布
手机
光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
- 搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 视点!美国首位女总统即将诞生?拜登恐怕要提前下岗,美政坛迎来变局?
- 当前速递!用理想仪器实现更好的颗粒 德国新帕泰克亮相CPHI & PMEC China获好评
- 微粒贷怎么申请开通 开通方法如下
- 焦点简讯:心疼!这位40岁的云南缉毒警,已是满头白发
家电
kratos http原理 每日看点
概念
kratos 为了使http协议的逻辑代码和grpc的逻辑代码使用同一份,选择了基于protobuf的IDL文件使用proto插件生成辅助代码的方式。
protoc http插件的地址为:https://github.com/go-kratos/kratos/tree/main/cmd/protoc-gen-go-http
【资料图】
示例
syntax = "proto3";package helloworld;option go_package = "test/helloworld;helloworld";option java_multiple_files = true;option java_package = "helloworld";import "google/api/annotations.proto";service Greeter {rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { post: "/helloworld", // 声明路由 body: "*" };} } message HelloRequest {string name = 1;} message HelloReply {string msg = 1;}
使用kratos proto client xxx
生成的代码为:
// Code generated by protoc-gen-go-http. DO NOT EDIT.// versions:// - protoc-gen-go-http v2.4.0// - protoc v3.19.4// source: helloworld/helloworld.protopackage helloworldimport (context "context"http "github.com/go-kratos/kratos/v2/transport/http"binding "github.com/go-kratos/kratos/v2/transport/http/binding")// This is a compile-time assertion to ensure that this generated file// is compatible with the kratos package it is being compiled against.var _ = new(context.Context)var _ = binding.EncodeURLconst _ = http.SupportPackageIsVersion1const OperationGreeterSayHello = "/helloworld.Greeter/SayHello"type GreeterHTTPServer interface {SayHello(context.Context, *HelloRequest) (*HelloReply, error)}func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) {r := s.Route("/")r.POST("/helloworld", _Greeter_SayHello0_HTTP_Handler(srv))}func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error {return func(ctx http.Context) error {var in HelloRequestif err := ctx.Bind(&in); err != nil {return err}http.SetOperation(ctx, OperationGreeterSayHello)h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) {return srv.SayHello(ctx, req.(*HelloRequest))})out, err := h(ctx, &in)if err != nil {return err}reply := out.(*HelloReply)return ctx.Result(200, reply)}}type GreeterHTTPClient interface {SayHello(ctx context.Context, req *HelloRequest, opts ...http.CallOption) (rsp *HelloReply, err error)}type GreeterHTTPClientImpl struct {cc *http.Client}func NewGreeterHTTPClient(client *http.Client) GreeterHTTPClient {return &GreeterHTTPClientImpl{client}}func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http.CallOption) (*HelloReply, error) {var out HelloReplypattern := "/helloworld"path := binding.EncodeURL(pattern, in, false)opts = append(opts, http.Operation(OperationGreeterSayHello))opts = append(opts, http.PathTemplate(pattern))err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...)if err != nil {return nil, err}return &out, err}
开启一个grpc及http服务:
package mainimport ("context""fmt""log""test/helloworld""github.com/go-kratos/kratos/v2""github.com/go-kratos/kratos/v2/middleware/recovery""github.com/go-kratos/kratos/v2/transport/grpc""github.com/go-kratos/kratos/v2/transport/http")type server struct {helloworld.UnimplementedGreeterServer}func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {return &helloworld.HelloReply{Msg: fmt.Sprintf("Hello %+v", in.Name)}, nil}func main() {s := &server{}httpSrv := http.NewServer(http.Address(":8000"),http.Middleware(recovery.Recovery(),),)grpcSrv := grpc.NewServer(grpc.Address(":9000"),grpc.Middleware(recovery.Recovery(),),) helloworld.RegisterGreeterServer(grpcSrv, s)helloworld.RegisterGreeterHTTPServer(httpSrv, s)app := kratos.New(kratos.Name("test"),kratos.Server(httpSrv,grpcSrv,),)if err := app.Run(); err != nil {log.Fatal(err)}}
http client:
package mainimport ("context""log""test/helloworld""github.com/go-kratos/kratos/v2/middleware/recovery"transhttp "github.com/go-kratos/kratos/v2/transport/http")func main() {callHTTP()}func callHTTP() {conn, err := transhttp.NewClient(context.Background(),transhttp.WithMiddleware(recovery.Recovery(),),transhttp.WithEndpoint("127.0.0.1:8000"),)if err != nil {panic(err)}defer conn.Close()client := helloworld.NewGreeterHTTPClient(conn)reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "kratos"})if err != nil {log.Fatal(err)}log.Printf("[http] SayHello %s\n", reply.Msg)}
http server端实现原理
核心流程为下图 :
首先新建一个struct 并实现 http_pb.go种 GreeterHTTPServer interface 的方法,GreeterHTTPServer的命名方式为protobuf文件中的 service
+HTTPServer
,interface的方法为protobuf
中使用google.api.http
生命http路由所有的method。
然后使用RegisterGreeterHTTPServer方法把服务注册进去。大体的流程如下:
const OperationGreeterSayHello = "/helloworld.Greeter/SayHello"func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) {r := s.Route("/")r.POST("/helloworld", _Greeter_SayHello0_HTTP_Handler(srv)) // 注册路由}func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error {return func(ctx http.Context) error {var in HelloRequest // protobuf 中声明的request if err := ctx.Bind(&in); err != nil { // 把http的参数绑定到 inreturn err}http.SetOperation(ctx, OperationGreeterSayHello) // 设置Operation 和grpc一值,用于middleware select 等h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) {return srv.SayHello(ctx, req.(*HelloRequest)) // 这个方法也就是上文提到的GreeterHTTPServer接口的方法,也就是我们自己实现的struct server里的SayHello方法}) // 使用责任链模式middleware 这里没有任何中间件out, err := h(ctx, &in) // 执行if err != nil {return err}reply := out.(*HelloReply) return ctx.Result(200, reply) }}
什么事责任链模式?
https://haiyux.cc/post/designmode/behavioral/#责任链模式
上段代码中的POST方法为:
代码在https://github.com/go-kratos/kratos/blob/main/transport/http/router.go#L76
func (r *Router) POST(path string, h HandlerFunc, m ...FilterFunc) {r.Handle(http.MethodPost, path, h, m...) // MethodPost = POST net/http下的常量}// h 为上段xxx_http_pb.go代码中_Greeter_SayHello0_HTTP_Handler的返回值func (r *Router) Handle(method, relativePath string, h HandlerFunc, filters ...FilterFunc) {next := http.Handler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {ctx := r.pool.Get().(Context)ctx.Reset(res, req) // 把 net/http的http.ResponseWriter 和*http.Request 设置ctx中if err := h(ctx); err != nil { // 执行h r.srv.ene(res, req, err) // 如果出错了 执行 ene(EncodeErrorFunc)}ctx.Reset(nil, nil)r.pool.Put(ctx)}))next = FilterChain(filters...)(next)next = FilterChain(r.filters...)(next) // 添加filter 责任链模式r.srv.router.Handle(path.Join(r.prefix, relativePath), next).Methods(method) // router 为 mux的router 把方法注册到路由中}
当我们访问 path.Join(r.prefix, relativePath)
也就是/helloworld
时,会执行上段代码中的next
方法,next是一个责任链。
核心为会执行_Greeter_SayHello0_HTTP_Handler方法,
如果没发生错误,执行ctx.Result(200, reply)
type wrapper struct {router *Routerreq *http.Requestres http.ResponseWriterw responseWriter}func (c *wrapper) Result(code int, v interface{}) error {c.w.WriteHeader(code)return c.router.srv.enc(&c.w, c.req, v)}
enc也就是EncodeResponseFunc
, 为kratos预留的返回值函数
type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) error
kratos提供了默认的EncodeResponseFunc
func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {if v == nil {return nil}if rd, ok := v.(Redirector); ok { // 检查有无Redirect方法,如果实现了interface 为跳转路由 也就是http的301 302等url, code := rd.Redirect()http.Redirect(w, r, url, code) // 跳转return nil}codec, _ := CodecForRequest(r, "Accept") // 查看需要返回的参数类型 比如jsondata, err := codec.Marshal(v) // 把数据Marshal成[]byteif err != nil {return err}w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) // 设置header_, err = w.Write(data) // 写数据if err != nil {return err}return nil}
如果没发生错误,执行ene
,也就是EncodeErrorFunc
, 为kratos预留的错误返回值删除
type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error)
kratos提供了默认的EncodeErrorFunc
func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {se := errors.FromError(err) // 把error变成自定义的实现error的结构体codec, _ := CodecForRequest(r, "Accept") // 查看需要返回的参数类型 比如jsonbody, err := codec.Marshal(se)if err != nil {w.WriteHeader(http.StatusInternalServerError)return}w.Header().Set("Content-Type", httputil.ContentType(codec.Name()))w.WriteHeader(int(se.Code)) // 写入 error中的code_, _ = w.Write(body) // 返回错误信息}
http client端实现原理
在上传的代码中http client的部分为
type GreeterHTTPClient interface {SayHello(ctx context.Context, req *HelloRequest, opts ...http.CallOption) (rsp *HelloReply, err error)}type GreeterHTTPClientImpl struct { // 实现 GreeterHTTPClient 接口cc *http.Client}func NewGreeterHTTPClient(client *http.Client) GreeterHTTPClient {return &GreeterHTTPClientImpl{client}}func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http.CallOption) (*HelloReply, error) {var out HelloReply // 返回值pattern := "/helloworld" path := binding.EncodeURL(pattern, in, false) // 整理path 传入in 是由于可能有path参数或者queryopts = append(opts, http.Operation(OperationGreeterSayHello))opts = append(opts, http.PathTemplate(pattern))err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...) // 访问接口if err != nil {return nil, err}return &out, err}
上段代码中的Invoke方法为:
代码在https://github.com/go-kratos/kratos/blob/main/transport/http/client.go#L192
func (client *Client) Invoke(ctx context.Context, method, path string, args interface{}, reply interface{}, opts ...CallOption) error {var (contentType stringbody io.Reader)c := defaultCallInfo(path)for _, o := range opts {if err := o.before(&c); err != nil {return err}}if args != nil {data, err := client.opts.encoder(ctx, c.contentType, args)if err != nil {return err}contentType = c.contentTypebody = bytes.NewReader(data)}url := fmt.Sprintf("%s://%s%s", client.target.Scheme, client.target.Authority, path)req, err := http.NewRequest(method, url, body)if err != nil {return err}if contentType != "" {req.Header.Set("Content-Type", c.contentType)}if client.opts.userAgent != "" {req.Header.Set("User-Agent", client.opts.userAgent)}ctx = transport.NewClientContext(ctx, &Transport{endpoint: client.opts.endpoint,reqHeader: headerCarrier(req.Header),operation: c.operation,request: req,pathTemplate: c.pathTemplate,})return client.invoke(ctx, req, args, reply, c, opts...)}func (client *Client) invoke(ctx context.Context, req *http.Request, args interface{}, reply interface{}, c callInfo, opts ...CallOption) error {h := func(ctx context.Context, in interface{}) (interface{}, error) {res, err := client.do(req.WithContext(ctx))if res != nil {cs := csAttempt{res: res}for _, o := range opts {o.after(&c, &cs)}}if err != nil {return nil, err}defer res.Body.Close()if err := client.opts.decoder(ctx, res, reply); err != nil {return nil, err}return reply, nil}var p selector.Peerctx = selector.NewPeerContext(ctx, &p)if len(client.opts.middleware) > 0 {h = middleware.Chain(client.opts.middleware...)(h)}_, err := h(ctx, args)return err}
关键词:
kratos http原理 每日看点
手机问题:努比亚z30pro续航怎么样
天天播报:RTX 4060今晚上市后 尴尬一幕出现:日本线下仅1人排队买首发
重点聚焦!女子疑坐公交不付钱:踩猫威胁司机
算法导论-第14章-数据结构的扩张-全球新消息
货币市场日报:6月29日
2023年上半年剧集报告发布:国产剧口碑上涨显著
微动态丨GDDR7显存明年就有了!RTX 50可能先吃螃蟹
800V高压架构+二代XNGP辅助驾驶上车!小鹏G6上市:20.99万起 滚动
iGame人气王!七彩虹iGame RTX 4060 Ultra W OC显卡图赏
文心一言 VS 讯飞星火 VS chatgpt (51)-- 算法导论6.2 3题|全球时讯
每日观察!《异世界》魔径—給异世界点颜色看看 楔子
世界看点:华为宣布2024年推出面向商用的5.5G全套网络设备
【全球速看料】山东龙凤四胞胎同圆大学梦 网友:四倍辛苦 四倍幸福
当前信息:可以换电的纯电MPV来了!全新上汽大通大家MIFA 9车电分离版上市
世界热推荐:Kubernetes 对象以及部署nginx服务示例(四)
记录--写一个高德地图巡航功能的小DEMO
旗袍发型教程_旗袍发型-天天即时看
世界实时:债市日报:6月29日
阿斯巴甜将被世卫列为“可能致癌物质”:元气森林、奈雪火速回应
丫丫解锁新玩具竹笼:一刻也没闲着
无糖可乐不能喝了?或含致癌物阿斯巴甜
天天观焦点:Steam将AI作图游戏拒之门外!除非能证明拥有版权
环球热讯:红米Redmi Pad 2平板跑分曝光:配骁龙680 或近期发布
新市街道开展“健康无毒 喜迎大运”6.26禁毒宣传日活动
天天观点:内爆致5人遇难!美国泰坦号观光潜艇失事残骸打捞上岸
1200mAh锂电池+三档风力调节:佳格手持小风扇8.9元狂促_全球今日讯
世界时讯:最好的Windows掌机!ROG Ally暴力魔改8TB SSD:容量陡增8倍
当前热讯:重要提醒!暴雪国服游戏退款申请明日将截止
【当前独家】张颂文北影毕业典礼演讲:希望你们每天都在进步
【世界速看料】不吝赐教的意思(赐教的意思)
Spring Cloud 如何引入云原生网关,创新微服务架构|天天最新
拈花云科基于 Apache DolphinScheduler 在文旅业态下的实践
.NET 个人博客-添加RSS订阅功能 世界快播
如何将视频文件.h264和音频文件.mp3复用为输出文件output.mp4?
天天热资讯!商品日报(6月29日):尿素再度拉涨超5% 供应利多刺激甲醇盘中涨超3%
联发科MT6825芯片组获上海MWC 2023亚洲突破性设备创新大奖!手机卫星可双向通信_焦点资讯
支持Type-C充电:英菲克F1无线鼠标24.9元抄底
天天热消息:做错N多年!央视科普:鸡蛋别再放到冰箱门上了
要求罚金30亿美元!Chatgpt涉嫌信息盗窃被起诉 全球视讯
官方辟谣激情誓师女生考508分:女生考了600多分 考得特别好 环球焦点
全球低水足迹倡议(LWFi)联盟扩容,伊利“双足迹”开启全链减碳新篇章_世界视点
IDA的使用-1_世界新消息
clop勒索软件攻击活动频发,西门子能源中招_世界观察
精彩看点:构建数字工厂丨数据分析与图表视图模型的配置用法
券商数字化创新场景数据中台实践
热门看点:C# 序列化大小写 序列化对象为大小写 JsonConvert.SerializeObject
新款2024MGCyberster泄露 当前热讯
第十四届夏季达沃斯论坛闭幕
天天快讯:暴露年龄!时隔16年 Office“大眼夹”回归Windows 11:功能焕然一新
16.5亿打造!《封神》妲己首次亮相引热议 网友称妆造诡异在拍画皮吗
苹果之后 三星被指侵犯加州理工Wi-Fi专利:索赔可达数十亿美元-世界新消息
“快乐水”不快乐了!阿斯巴甜将被定为可能致癌物质|天天热资讯
华为发布F5.5G智简全光联接四大创新:万兆时代来了
讯息:大宗交易:蓝色光标成交6967.8万元,折价1.96%(06-29)
解读 RocketMQ 5.0 全新的高可用设计
探秘华为云盘古大模型:AI for industries的身体力行_报道
天天速读:高铁踹老头底被曝
科创板收盘播报:科创50指数跌0.67% 新股时创能源较发行价涨63.91%|全球热闻
如何使用 iOS 17 将照片变成 iMessage 贴纸
多家高校下月起停用微信支付 微信团队致歉:即刻修正
鳄鱼独居16年产子 科学家:濒临灭绝物种的生存策略
南极人纯棉抗菌袜子8双14.9元:吸湿排汗 亲肤透气
【全球报资讯】多家高校下月起停用微信支付 腾讯回应网友不买账:专家称反垄断太有意义
Intel四代至强命运多舛:突曝严重Bug 部分停止出货
精彩看点:司法部出手!这项业务,有大变化!
【后端面经-Java】公平锁和加锁流程 全球简讯
讯息:玖章算术与百度智能云达成合作,「NineData SQL 开发」成为百度智能云主推的数据库工具
【高端访谈】中非经贸博览会将助力刚中贸易提质升级——访刚果(金)外贸部长布萨_当前视讯
央企改革三年重点任务考核结果出炉:三大运营商排名一一曝光
摩托骑手被汽车撞下高架 现场惨!官方通报:系被追尾 伤者暂无生命危险
立白洗衣液大促:山茶幽香、除菌除螨 10斤到手38元_每日简讯
MWC牌面!魅族Flyme Auto上央视:车机互联打通软硬件|当前快看
露牙媚眼羞涩笑主播圈粉中老年人:当当网李国庆在线求合作
每日消息!索尼ZV-E1“打鸡血”:免费升级4K 120p拍摄
年内8家“袖珍”IPO公司登陆港交所-天天观天下
鼎通科技(688668):该股换手率大于8%(06-29)_世界速讯
性能4倍于1060!RTX 4060今天开售:2399元 英伟达诚意感受到没-当前速读
世界即时看!疑因不满项目谈判被提前泄露:特斯拉或已放弃在西班牙建厂!
今日讯!内蒙古康巴什区:让“梧桐树”更加枝繁叶茂
环球播报:装机选500W电源就是万金油?你又错了
海南环岛旅游公路主线路基段即将完工:12月底通车 串联全省景点|独家
Windows自带杀软又出问题:Defender新版CPU占用过高|环球焦点
每部手机都有的出厂标签要改了!工信部:7月1日起正式启用新型进网许可标志
90后宝妈沙漠边缘送奶茶月入7000 我能赚钱生娃:直言男人除了赚钱还能干啥? 当前速递
卢卡申科:普京曾有意杀死普里戈任,我劝他不要鲁莽行事
数字经济催生的低代码开发浪潮,JNPF带你轻松实现应用程序拓展! 天天日报
直播平台源码功能分享:直播回放功能的实现_当前看点
【天天快播报】云顶新耀-B早盘持续走高涨近9% 中金维持跑赢行业评级
能在车上点外卖了!特斯拉或将推出应用商城 可支持第三方应用与服务 热点聚焦
法庭文件出纰漏 五星大饭店运营成本曝光|实时焦点
剑指比亚迪海豚 宝骏云朵外观细节图发布:全球顶级设计师操刀 环球观察
40度高温杀回马枪!南方多地加入高温群聊蒸桑拿
传奇女歌手麦当娜进ICU:因细菌感染_每日看点
宁德时代联合长安汽车等共设动力电池公司
js的Set数据类型
Linux_Centos 增加中文字体支持|环球视点
直播系统聊天技术(九):千万级实时直播弹幕的技术实践
天天看热讯:【Oracle】使用PL/SQL实现冒泡排序
BackboneJS教程_编程入门自学教程_菜鸟教程-免费教程分享 环球关注