首页 > 其他分享 >【go】【rpc】【同一端口,提供多种服务】

【go】【rpc】【同一端口,提供多种服务】

时间:2024-06-06 22:23:22浏览次数:23  
标签:http err grpc 端口 golang rpc go port

@

目录


写在前面

  • 相关博文
  • 个人博客首页
  • 免责声明:仅供学习交流使用!开源框架可能存在的风险和相关后果将完全由用户自行承担,本人不承担任何法律责任。

1. 需求

当 rpc 的服务启用时,为了更好对外提供服务(测试、监控、心跳等);我们需要多协议支持

    1. 起另外一个端口服务
    1. 同一个端口监听
    1. 同一个端口相同方法监听

1. 起另外的服务端口

package main

import (
	"context"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/reflection"
	"log"
	"net/http"
	"strings"
)

func main() {
	port := "8080"
	go handleHttp("8088")
	handleRpc("8080")

}

func handleHttp(port string) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	m.Handle("/", mux)
    m.Serve()
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
func handleRpc()  {
	//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
	//list, err := a.TagList()
	//fmt.Printf("%#v,%s", list, err)
	tag := server.NewTag("http://localhost", "string", "string")
	svc := grpc.NewServer()
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
    svc.Serve()
}

2. 一个端口监听

package main

import (
	"context"
    "github.com/soheilhy/cmux"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/reflection"
	"log"
	"net/http"
	"strings"
)

func main() {
	port := "8080"
	//go handleHttp("8088")
	//handleRpc("8080")
	//l, err := net.Listen("tcp", "localhost:"+port)
	//if err != nil {
	//	log.Fatalf("Run TCP Server err: %v", err)
	//}

	m := cmux.New(l)
	grpcL := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldPrefixSendSettings("content-type", "application/grpc"))
	httpL := m.Match(cmux.HTTP1Fast())

	grpcS := handleRpc()
	httpS := handleHttp(port)

	go grpcS.Serve(grpcL)
	go httpS.Serve(httpL)
	//
	err = m.Serve()
	if err != nil {
		log.Fatalf("Run Serve err: %v", err)
	}
}



func handleHttp(port string) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
func handleRpc() *grpc.Server {
	//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
	//list, err := a.TagList()
	//fmt.Printf("%#v,%s", list, err)
	tag := server.NewTag("http://localhost", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	svc := grpc.NewServer()
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
	return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
	endpoint := "0.0.0.0:" + port
	g := runtime.NewServeMux()
	dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
	_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)

	return g
}


3. 同一个端口相同方法监听

# 1. 下载 Google API Proto 文件
git clone https://github.com/googleapis/googleapis.git   

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest

protoc -I . -I  $GOPATH\github.com\googleapis     --grpc-gateway_out=logtostderr=true:.  --go_out=.   --go-grpc_out .  rpc/proto/*.proto
service TagSvc {
  // protoc -I . -I  $GOPATH\github.com\googleapis     --grpc-gateway_out=logtostderr=true:.  --go_out=.   --go-grpc_out .  rpc/proto/*.proto
  rpc TagList(TagRequest) returns (MessageResponse){
    option (google.api.http) = {
      get: "/api/v1/tag"
    };
  }
}
package main

import (
	"context"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/reflection"
	"log"
	"net/http"
	"strings"
)

func main() {
	port := "8080"

	grpcS := handleRpc()
	grpcG := handleGrpcGateway(port)
	httpS := handleHttp(port, grpcG)

	err := http.ListenAndServe(":"+port, grpcHandlerFunc(grpcS, httpS))
	if err != nil {
		log.Fatalf("Run Serve err: %v", err)
	}
}

func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
	return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
			grpcServer.ServeHTTP(w, r)
		} else {
			otherHandler.ServeHTTP(w, r)
		}
	}), &http2.Server{})
}

func handleHttp(port string, mux *runtime.ServeMux) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	m.Handle("/", mux)
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
func handleRpc() *grpc.Server {
	//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
	//list, err := a.TagList()
	//fmt.Printf("%#v,%s", list, err)
	tag := server.NewTag("http://localhost", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	svc := grpc.NewServer()
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
	return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
	endpoint := "0.0.0.0:" + port
	g := runtime.NewServeMux()
	dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
	_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)

	return g
}


参考资料

基础/标准库/第三方库


golang 导航


编程规范


算法|面试


项目


标签:http,err,grpc,端口,golang,rpc,go,port
From: https://www.cnblogs.com/nones/p/18236107

相关文章

  • golang select 的 case 执行顺序
    问题:golangselect结构,假如底下有三个case,分别从chan1,chan2,chan3读取内容,chan1,chan2,chan3都是非阻塞的,那么是会先进入第一个case,其它case还会再进入吗?在Go语言中,select语句用于监控多个通道的操作,并在其中一个操作准备好时执行相应的case。如果多个case同......
  • 查看Linux端口占用和开启端口命令
    查看端口的使用的情况lsof命令比如查看80端口的使用的情况lsof-itcp:80列出所有的端口netstat-ntlp查看端口的状态/etc/init.d/iptablesstatus开启端口以开启端口80为例。1用命令开启端口iptables-IINPUT-ptcp--dport80-jaccpet --写入要开放的端......
  • 个人向 godot 源码阅读 - 3 - MainLoop 以及 2D 视口
    3-MainLoop以及2D视口godot默认的主循环类型为SceneTree,在之上则承载了godot中的重要概念之一节点树.SceneTree的源文件位于scene/main/scene_tree.cpp,SceneTree默认将会在Main::start()函数中被创建,然后被设置到OS的mainloop上,现在让我们来看看Scen......
  • 个人向 godot 源码阅读 - 2 - 入口点
    2-入口点由于godot是一个跨平台的引擎,所以就需要不可避免的对不同平台的入口点进行封装,在windows上godot的WinMain入口点的定义位于platform/windows/godot_windows.cpp中.它所做的仅仅是调用到传统的C入口点:在C入口点中则环绕了SEH异常造成的崩溃处理......
  • 个人向 godot 源码阅读 - 1 - 获取 / 编译源码
    1-获取/编译源码获取最常见的方法便是从GitHub上拉取,不过鉴于国内访问GitHub速度之慢,可以采取个折中的方案:先从Gitee上拉取:gitclonehttps://gitee.com/mirrors/godot然后更改remote地址:gitremoteset-urloriginhttps://github.com/godotengine/god......
  • MDZ UPnP和端口映射 区别
    DMZ(demilitarizedzone):可以简单理解成把网关的全端口转发到指定内网主机上,只能指定一台主机。这是一种静态全端口映射。这个协议只要早网关开启就行了。UPnP(UniversalPlugandPlay):这个协议的目的是动态的映射网关的指定端口到指定主机上,可以一把网关的不同端口映射到不同......
  • LOGO!的S7通信应用
    建立连接都以网络视图为平台,当然电路图模式也可以配置通讯,各人使用喜好而已。1.两台LOGO之间的S7添加两个新设备如果想要默认连接的话,直接把两个PLC拖拽连线,左侧CPU是客户机,右侧CPU是服务器,如果需要调整服务器和客户端选项的话拖拽更换CPU位置即可。双击蓝色连接线,设置详......
  • 通过端口复用直接进行正向tcp代理--win会被识别为病毒
    学习项目,win会被识别为病毒,关闭病毒和威胁防护,参考https://blog.csdn.net/u_say2what/article/details/134669122main.gopackagemainimport( "context" "fmt" _"golang.org/x/sys/unix" "golang.org/x/sys/windows" "io" "......
  • golang接口请求结构体验证器Validator实现
    一、前提:认识reflect.TypeOf及reflect.ValueOfTypeOf:动态的获取从函数接口中传进去的变量的类型,如果为空则返回值为nil(获取类型对象)可以从该方法获取的对象中拿到字段的所属类型,字段名,以及该字段是否是匿名字段等信息。还可以获取到与该字段进行绑定的tag。ValueO......
  • mongo数据库集合基本操作
    --查看user_info这个集合中name等于张三的数据db.user_info.find({name:"张三"})--查看user_info这个集合中telNum等于123456789的数据db.user_info.find({telNum:123456789})--查看user_info这个集合中name等于张三并且telNum等于123456789的数据db.user_info.f......