zoukankan      html  css  js  c++  java
  • go-micro 报500

    server.go

    package main
    
    import (
    	"github.com/gin-gonic/gin"
    	"github.com/micro/go-micro/registry"
    	"github.com/micro/go-micro/web"
    	"github.com/micro/go-micro/registry/consul"
    	"time"
    )
    
    func main() {
    	consulReg := consul.NewRegistry( //新建一个consul注册的地址,也就是我们consul服务启动的机器ip+端口
    		registry.Addrs("127.0.0.1:8500"),
    	)
    	ginRouter := gin.Default()
    	ginRouter.Handle("GET", "/user", func(context *gin.Context) {
    		context.String(200, "user api")
    	})
    	ginRouter.Handle("GET", "/news", func(context *gin.Context) {
    		context.String(200, "news api")
    	})
    
    	v1Group := ginRouter.Group("/v1")
    	{
    		v1Group.Handle("POST", "/prods", func(context *gin.Context) {
    			//rq := Helper.NewRequest()
    			//context.bind(rq) //使用自定义的结构体解析post表单
    			context.JSON(
    				200,
    				gin.H{
    					"data":2,
    				},
    			)
    		})
    	}
    
    
    	//其实下面这段代码的意义就是启动服务的同时把服务注册进consul中,做的是服务发现
    	server := web.NewService( //go-micro很灵性的实现了注册和反注册,我们启动后直接ctrl+c退出这个server,它会自动帮我们实现反注册
    		web.Name("httpprodservice"), //注册进consul服务中的service名字
    		web.Address(":8088"), //注册进consul服务中的端口,也是这里我们gin的server地址
    		web.Handler(ginRouter),  //web.Handler()返回一个Option,我们直接把ginRouter穿进去,就可以和gin完美的结合
    		web.Registry(consulReg), //注册到哪个服务器伤的consul中
    		
    	)
    	server.Init() //加了这句就可以使用命令行的形式去设置我们一些启动的配置
    	server.Run()
    }
    

      client.go

     

    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-micro/registry/consul"
    	myhttp "github.com/micro/go-plugins/client/http"
    	"log"
    )
    
    func callAPI(s selector.Selector) {
    	myCli := myhttp.NewClient(
    		client.Selector(s),
    		client.ContentType("application/json"), //因为我们要调用的/v1/prods这个api返回的是json,要先规定好数据格式json(很重要,如果是其他的会报错)
    	)
    	//下面这句代码封装了一个请求(未发送)
    	req := myCli.NewRequest("httpprodservice", "/v1/prods", map[string]string{})//这里最后一个参数是body,一般用于post请求的参数,因为我们这个api没有参数,所以我随便写了map[string]string{}
    	//从之前的图可以看到我们的返回值是一个json,key-val为"data":[],所以我们的response要构建一个相同结构的,方便go-micro帮我们返回响应结构体map[string]int{"Size": 4},这里的key大小写都可以,只要和request结构体该字段字母一样就行入 abcd:3 Abcd:3 ABCD:3都可以
    	var resp map[string]interface{}
    	log.Println("===req===")
    	log.Println(req)
    	log.Println("===context====")
    	log.Println(context.Background())
    	err := myCli.Call(context.Background(), req, &resp) //发起请求调用,并返回结果
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Println(resp)
    }
    
    func main() {
    	consulReg:=consul.NewRegistry(func(options *registry.Options) {
    		options.Addrs=[]string{
    			"127.0.0.1:8500",
    		}
    	})
    	mySelector := selector.NewSelector(
    		selector.Registry(consulReg),
    		selector.SetStrategy(selector.Random), //设置查询策略,这里是轮询
    	)
    	log.Println("===sel===")
    	log.Println(mySelector)
    	callAPI(mySelector)
    }
    

      go run server.go --server_address :8001

      go run client.go

      结果客户端报

    {"id":"go.micro.client","code":500,"detail":"none available","status":"Internal Server Error"}

      将consul换成etcd,发现也是报

    {"id":"go.micro.client","code":500,"detail":"none available","status":"Internal Server Error"}

      后来通过查看源码 pkgmodgithub.commicrogo-pluginsclienthttp@v0.0.0-20200119172437-4fe21aa238fdhttp.go

      大概在63行左右

    	// only get the things that are of mucp protocol
    	selectOptions := append(opts.SelectOptions, selector.WithFilter(
    		selector.FilterLabel("protocol", "http"),
    	))
    

      会添加过滤器 pkgmodgithub.commicrogo-micro@v1.8.1clientselectordefault.go 的 

    Select()  大概在56行
    	// apply the filters
    	for _, filter := range sopts.Filters {
    		services = filter(services)
    	}
    

      

    里面的进行过滤
    查看 pkgmodgithub.commicrogo-micro@v1.8.1clientselectorfilter.go
    func FilterLabel(key, val string) 方法, key是protocol val是http
    // FilterLabel is a label based Select Filter which will
    // only return services with the label specified.
    func FilterLabel(key, val string) Filter {
    	return func(old []*registry.Service) []*registry.Service {
    		var services []*registry.Service
    
    		for _, service := range old {
    			serv := new(registry.Service)
    			var nodes []*registry.Node
    
    			for _, node := range service.Nodes {
    				if node.Metadata == nil {
    					continue
    				}
    
    				if node.Metadata[key] == val {
    					nodes = append(nodes, node)
    				}
    			}
    
    			// only add service if there's some nodes
    			if len(nodes) > 0 {
    				// copy
    				*serv = *service
    				serv.Nodes = nodes
    				services = append(services, serv)
    			}
    		}
    
    		return services
    	}
    }
    

      发现是

    node.Metadata[key] == val

    解决方法在server.go 的web服务注册添加Metadata信息
    //其实下面这段代码的意义就是启动服务的同时把服务注册进consul中,做的是服务发现
    	server := web.NewService( //go-micro很灵性的实现了注册和反注册,我们启动后直接ctrl+c退出这个server,它会自动帮我们实现反注册
    		web.Name("httpprodservice"), //注册进consul服务中的service名字
    		web.Address(":8088"), //注册进consul服务中的端口,也是这里我们gin的server地址
    		web.Handler(ginRouter),  //web.Handler()返回一个Option,我们直接把ginRouter穿进去,就可以和gin完美的结合
    		web.Metadata(map[string]string{"protocol" : "http"}),
    		web.Registry(consulReg), //注册到哪个服务器伤的consul中
    		web.RegisterTTL(time.Second*30),
    		web.RegisterInterval(time.Second*15),
    	)
    

      

  • 相关阅读:
    第十六周学习进度报告
    个人课程总结
    第一阶段意见评论
    用户评价
    第二阶段10
    第二阶段9
    第二阶段8
    第十五周学习进度报告
    第二阶段7
    第二阶段6
  • 原文地址:https://www.cnblogs.com/f-rt/p/12704992.html
Copyright © 2011-2022 走看看