前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Go-Micro客户端请求报500错误的解决方法

Go-Micro客户端请求报500错误的解决方法

作者头像
Java架构师必看
发布2021-09-14 15:37:46
发布2021-09-14 15:37:46
1.7K00
代码可运行
举报
文章被收录于专栏:Java架构师必看Java架构师必看
运行总次数:0
代码可运行

Go-Micro客户端请求报500错误的解决方法

强烈推介IDEA2020.2破解激活,IntelliJ IDEA 注册码,2020.2 IDEA 激活码

文章目录

1.服务端代码

代码语言:javascript
代码运行次数:0
复制
package main

import (
	"github.com/gin-gonic/gin"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/web"
	"github.com/micro/go-plugins/registry/consul"
	"net/http"
)

func main() {
   
	consulReg := consul.NewRegistry(registry.Addrs(":8500"))
	engine := gin.Default()
	engine.POST("/hello", func(c *gin.Context) {
   
		c.JSON(http.StatusOK, gin.H{
   
			"msg": "hello,world",
		})
	})
	service := web.NewService(
		web.Name("cas"),
		web.Address(":8001"),
		web.Registry(consulReg),
		web.Handler(engine),
	)
	service.Init()
	service.Run()
}

2.客户端代码

代码语言:javascript
代码运行次数:0
复制
package main

import (
	"context"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/client/selector"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-plugins/client/http"
	"github.com/micro/go-plugins/registry/consul"
	"log"
)

func main() {
   
	consulReg := consul.NewRegistry(registry.Addrs(":8500"))
	selector := selector.NewSelector(
		selector.Registry(consulReg),
		selector.SetStrategy(selector.RoundRobin),
	)
	httpClient := http.NewClient(
		// 选择器
		client.Selector(selector),
		// 响应格式默认格式protobuf,设置为json
		client.ContentType("application/json"),
		)
	req := map[string]string{
   }
	request := httpClient.NewRequest("cas", "/hello", req)
	rsp := map[string]interface{
   }{
   }
	err := httpClient.Call(context.Background(), request, &rsp)
	if err != nil {
   
		log.Fatalf("request err: %+v", err)
	}
	log.Printf("%+v",rsp)
}

3.发起请求报错

客户端请求报错如下:

代码语言:javascript
代码运行次数:0
复制
{"id":"go.micro.client","code":500,"detail":"none available","status":"Internal Server Error"}

4.问题分析

1.顺着客户端调用的Call()方法,进入源码github.com\micro\go-plugins\client\http\http.go,找到获取服务节点的方法:

代码语言:javascript
代码运行次数:0
复制
	// get next nodes from the selector
	next, err := h.next(req, callOpts)

2.再继续查看next()方法,找到第63行,这里为Selector节点选择器添加了过滤器,传递了两个参数"protocol", "http",可以发现是个键值对:

代码语言:javascript
代码运行次数:0
复制
	// only get the things that are of mucp protocol
	selectOptions := append(opts.SelectOptions, selector.WithFilter(
		selector.FilterLabel("protocol", "http"),
	))

3.进一步进入FilterLabel()方法,在第41行可以发现,上一步传的两个参数在这里做了校验,分别作为的Metadata(元数据)的map的键和值,相当于验证协议需要为http:

代码语言:javascript
代码运行次数:0
复制
				if node.Metadata[key] == val {
   
					nodes = append(nodes, node)
				}

4.回到http.go的69行,如果不满足http协议,则获取服务节点失败,返回我们所遇到的这个err:

代码语言:javascript
代码运行次数:0
复制
	// get next nodes from the selector
	next, err := h.opts.Selector.Select(service, selectOptions...)
	if err != nil && err == selector.ErrNotFound {
   
		return nil, errors.NotFound("go.micro.client", err.Error())
	} else if err != nil {
   
		return nil, errors.InternalServerError("go.micro.client", err.Error())
	}

到这里其实已经可以基本确定我们遇到的问题了:在使用go-plugins插件进行服务调用时,在服务发现时为选择器添加了过滤,限定了请求协议,要求Metadata的键值必须为"protocol":"http",否则返回的服务节点切片长度将为0。

5.解决方法

因此解决方法则是在服务端进行服务注册的时候,为注册的服务添加上Metadata配置,指定请求协议为http:

代码语言:javascript
代码运行次数:0
复制
	service := web.NewService(
		web.Name("cas"),
		web.Address(":8001"),
		web.Registry(consulReg),
		web.Handler(engine),
		// 为注册的服务添加Metadata,指定请求协议为http
		web.Metadata(map[string]string{
   "protocol" : "http"}),
	)

在指定了服务的请求协议后,成功解决该问题~😄

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1.服务端代码
  • 2.客户端代码
  • 3.发起请求报错
  • 4.问题分析
  • 5.解决方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档