- 准备工做
- Go:
v1.13
- micro工具:https://github.com/micro/micro#install
- tutorials代码:git clone git@github.com:micro-in-cn/tutorials.git $GOPATH/src/github.com/micro-in-cn/tutorials
- learning-videos代码:git clone git@github.com:micro-in-cn/learning-videos.git $GOPATH/src/github.com/micro-in-cn/learning-videos
- etcd
- consul
API
前提已经安装micro工具,演示版本
1.18.0
micro api
curl http://localhost:8080
{"version": "1.18.0"}
Web
虽然定义的不是网关,但也可以作为网关使用
micro web
micro
命令行格式
micro -h
micro [global options] command [command options] [arguments...]
global options
micro -h
--registry value Registry for discovery. etcd, mdns [$MICRO_REGISTRY]
--registry_address value Comma-separated list of registry addresses [$MICRO_REGISTRY_ADDRESS]
--server_name value Name of the server. go.micro.srv.example [$MICRO_SERVER_NAME]
--transport value Transport mechanism used; http [$MICRO_TRANSPORT]
command options
micro api -h
--address value Set the api address e.g 0.0.0.0:8080 [$MICRO_API_ADDRESS]
--handler value Specify the request handler to be used for mapping HTTP requests to services; {api, event, http, rpc} [$MICRO_API_HANDLER]
--namespace value Set the namespace used by the API e.g. com.example.api [$MICRO_API_NAMESPACE]
--resolver value Set the hostname resolver used by the API {host, path, grpc} [$MICRO_API_RESOLVER]
--enable_rpc Enable call the backend directly via /rpc [$MICRO_API_ENABLE_RPC]
有关
handler
、resolver
、rpc
的介绍参考官方文档:API Gateway
micro web -h
--address value Set the web UI address e.g 0.0.0.0:8082 [$MICRO_WEB_ADDRESS]
--namespace value Set the namespace used by the Web proxy e.g. com.example.web [$MICRO_WEB_NAMESPACE]
global options --registry
micro --registry=etcd api
command options --address & --namespace
为了演示方便,这里使用中国社区教程(micro-in-cn/tutorials)的micro-api示例)
micro --registry=etcd api --address=:9080 --namespace=com.hbchen.api
错误示范,不指定server_name
# micro-in-cn/tutorials/examples/basic-practices/micro-api/meta
go run meta.go --registry=etcd
curl -XGET "http://localhost:9080/example?name=john"
{"id":"com.hbchen.api","code":500,"detail":"service not found","status":"Internal Server Error"}
正确示范
# micro-in-cn/tutorials/examples/basic-practices/micro-api/meta
go run meta.go --registry=etcd --server_name=com.hbchen.api.example
curl -XGET "http://localhost:9080/example?name=john"
{"message":"Meta已经收到你的请求,john"}
通过server_name
和namespace
可以定义不同类型的网关,负载通过server_name
筛选API网关,网关通过namespace
筛选API服务
- | 类型 | 说明 |
---|---|---|
1 | rpc | 通过RPC向go-micro应用转送请求,只接收GET和POST请求,GET转发RawQuery ,POST转发Body |
2 | api | 与rpc差不多,但是会把完整的http头封装向下传送,不限制请求方法 |
3 | http或proxy | 以反向代理的方式使用API,相当于把普通的web应用部署在API之后,让外界像调api接口一样调用web服务 |
4 | web | 与http差不多,但是支持websocket |
5 | event | 代理event事件服务类型的请求 |
6 | meta* | 默认值,元数据,通过在代码中的Endpoint 配置选择使用上述中的某一个处理器,默认RPC |
rpc
或api
模式同样可以使用Endpoint
定义路由。
api.Endpoint{
// 接口方法,一定要在proto接口中存在,不能是类的自有方法
Name: "Example.Call",
// http请求路由,支持POSIX风格
Path: []string{"/example"},
// 支持的方法类型
Method: []string{"POST", "GET"},
// 该接口使用的API转发模式
Handler: rpc.Handler,
}
- router过程
- endpoint
- 自定义路由
- resolver
- 路径规则
- endpoint
这里的Resolver类型都是
micro
中默认的go-micro/api/resolver/micro
rpc
类型需要服务名称go.micro.api.greeter
+ 方法名Greeter.Hello
请求路径 | 后台服务 | 接口方法 |
---|---|---|
/foo/bar | go.micro.api.foo | Foo.Bar |
/foo/bar/baz | go.micro.api.foo | Bar.Baz |
/foo/bar/baz/cat | go.micro.api.foo.bar | Baz.Cat |
/v1/foo/bar | go.micro.api.v1.foo | Foo.Bar |
/v1/foo/bar/baz | go.micro.api.v1.foo | Bar.Baz |
/v2/foo/bar | go.micro.api.v2.foo | Foo.Bar |
/v2/foo/bar/baz | go.micro.api.v2.foo | Bar.Baz |
proxy
类型只需要服务名称,用于服务发现,将http请求转发到对应的服务
请求路径 | 服务 | 后台服务路径 |
---|---|---|
/foo | go.micro.api.foo | /foo |
/foo/bar | go.micro.api.foo | /foo/bar |
/greeter | go.micro.api.greeter | /greeter |
/greeter/:name | go.micro.api.greeter | /greeter/:name |
默认网关
micro --registry=etcd api
# micro-in-cn/tutorials/examples/basic-practices/micro-api/meta
go run meta.go --registry=etcd
curl -XGET "http://localhost:8080/example?name=john"
--handler=api
micro --registry=etcd api --handler=api
# micro-in-cn/tutorials/examples/basic-practices/micro-api/api
go run api.go --registry=etcd
curl -XGET "http://localhost:8080/example/call?name=john"
--handler=proxy
micro --registry=etcd api --handler=proxy
# micro-in-cn/tutorials/examples/basic-practices/micro-api/proxy
go run proxy.go --registry=etcd
curl -XGET "http://localhost:8080/example/call?name=john"
- import
micro
的上下文插件,以及go-micro
的可插拔组件- 适合简单定制,如go-micro组件、增加插件,参考micro-in-cn/starter-kit/gateway
- fork
- 二次开发,需要修改网关源码
不管需求大小都建议在项目中自己编译
micro
工具,确保开发、生产等环境一致
以下示例在本文档的example目录:
main_01.go
、main_02.go
- registry
- consul
- kubernetes
- transport
- tcp
- grpc
自定义组件
package main
import (
"github.com/micro/micro/cmd"
// go-micro plugins
_ "github.com/micro/go-plugins/registry/consul"
_ "github.com/micro/go-plugins/registry/kubernetes"
_ "github.com/micro/go-plugins/transport/grpc"
_ "github.com/micro/go-plugins/transport/tcp"
)
func main() {
cmd.Init()
}
go build -o bin/micro_01 main_01.go
./bin/micro_01 --registry=consul --transport=tcp api
#https://github.com/micro-in-cn/tutorials/tree/master/examples/basic-practices/micro-api/meta
go run meta.go --registry=consul --transport=tcp
curl -XGET "http://localhost:8080/example?name=john"
plugin是使用网关的关键,类似各种web框架的中间件,通过HTTP
请求上下文的前置、后置处理实现拦截、装饰等各种场景的需求,如:
- 跨域
- 认证鉴权
- 监控
- 限流
- 链路追踪
- 日志
- 流量染色 _ ……
plugin接口
type Plugin interface {
// Global Flags
Flags() []cli.Flag
// Sub-commands
Commands() []cli.Command
// Handle is the middleware handler for HTTP requests. We pass in
// the existing handler so it can be wrapped to create a call chain.
Handler() Handler
// Init called when command line args are parsed.
// The initialised cli.Context is passed in.
Init(*cli.Context) error
// Name of the plugin
String() string
}
Wrap ResponseWriter
- StatusCode
- In/Out Bytes
- ……
type WrapWriter struct {
StatusCode int
wroteHeader bool
http.ResponseWriter
}
func (ww *WrapWriter) WriteHeader(statusCode int) {
ww.wroteHeader = true
ww.StatusCode = statusCode
ww.ResponseWriter.WriteHeader(statusCode)
}
go build -o bin/micro_02 main_02.go
bin/micro_02 api -h
# 多了自定义插件的flag
--metrics_disable disable metrics
./bin/micro_02 --registry=consul --transport=tcp api
访问服务:http://localhost:8080/metrics
做些访问数据,再看metrics
结果
curl -XGET "http://localhost:8080/example?name=john"
curl -XGET "http://localhost:8080/example?name=john"
curl -XGET "http://localhost:8080/example?name=john"
……
# 或
hey -z 5s -c 1 "http://localhost:8080/example?name=john"
./bin/micro_02 --registry=consul --transport=tcp api --metrics_disable
访问服务:http://localhost:8080/metrics
{
"id": "go.micro.api",
"code": 500,
"detail": "service not found",
"status": "Internal Server Error"
}