九,自写网关(library-apigateway)
网关 library-apigateway,接口访问的统一入口。通过 consul 获取注册的微服务的某一个实例,发起访问请求。如图:

完整代码:
https://github.com/Justin02180218/micro-kit
包结构

目前网关的功能只是做接口转发,所以只有一个 transport 层。
代码实现
配置文件
server:port: 80mode: debugname: "apigateway"consul:addr: "http://consul-server:8500"interval: "10s"timeout: "1s"client: retrymax: 3retrytimeout: 500
修改 consul.go
func HttpClient(cfg *configs.AppConfig, name, method, path string, logger log.Logger) endpoint.Endpoint {consulAddr := cfg.ConsulConfig.AddrretryMax := cfg.ConsulConfig.Client.RetryMaxretryTimeout := cfg.ConsulConfig.Client.RetryTimeoutclient := connectConsul(consulAddr)instance := consul.NewInstancer(client, logger, name, []string{name}, true)factory := factoryForHttp(method, path)endpointer := sd.NewEndpointer(instance, factory, logger)balancer := lb.NewRoundRobin(endpointer)retry := lb.Retry(retryMax, time.Millisecond*time.Duration(retryTimeout), balancer)return retry
}func factoryForHttp(method, path string) sd.Factory {return func(instance string) (endpoint.Endpoint, io.Closer, error) {if !strings.HasPrefix(instance, "http") {instance = "http://" + instance}tgt, err := url.Parse(instance)if err != nil {return nil, nil, err}tgt.Path = pathreturn httptransport.NewClient(method,tgt,utils.EncodeJSONRequest,utils.DecodeJSONResponse,).Endpoint(), nil, nil}
}
transport层
在 transport 层定义 NewHttpHandler 函数,返回 *gin.Engine,目前采用硬编码的方式添加api接口,后续可以改成页面配置的方式。
func NewHttpHandler(ctx context.Context, cfg *configs.AppConfig, logger log.Logger) *gin.Engine {r := utils.NewRouter(ctx.Value("ginMod").(string))e := r.Group("/api/user"){e.POST("register", func(c *gin.Context) {register := registers.HttpClient(cfg, "user-service", "POST", "/api/v1/register", logger)kithttp.NewServer(register,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.GET("findByID", func(c *gin.Context) {findByID := registers.HttpClient(cfg, "user-service", "GET", "/api/v1/findByID", logger)kithttp.NewServer(findByID,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.GET("findByEmail", func(c *gin.Context) {findByEmail := registers.HttpClient(cfg, "user-service", "GET", "/api/v1/findByEmail", logger)kithttp.NewServer(findByEmail,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.GET("findBooksByUserID", func(c *gin.Context) {findBooksByUserID := registers.HttpClient(cfg, "user-service", "GET", "/api/v1/findBooksByUserID", logger)kithttp.NewServer(findBooksByUserID,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})}e = r.Group("/api/book"){e.POST("save", func(c *gin.Context) {save := registers.HttpClient(cfg, "book-service", "POST", "/api/v1/save", logger)kithttp.NewServer(save,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.GET("books", func(c *gin.Context) {books := registers.HttpClient(cfg, "book-service", "GET", "/api/v1/books", logger)kithttp.NewServer(books,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.GET("selectBookByName", func(c *gin.Context) {selectBookByName := registers.HttpClient(cfg, "book-service", "GET", "/api/v1/selectBookByName", logger)kithttp.NewServer(selectBookByName,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})e.POST("borrowBook", func(c *gin.Context) {borrowBook := registers.HttpClient(cfg, "book-service", "POST", "/api/v1/borrowBook", logger)kithttp.NewServer(borrowBook,utils.DecodeJSONRequest,utils.EncodeJsonResponse,).ServeHTTP(c.Writer, c.Request)})}return r
}
启动服务
main.go
var confFile = flag.String("f", "apigateway.yaml", "user config file")
func main() {flag.Parse()var logger log.Logger{logger = log.NewLogfmtLogger(os.Stderr)logger = log.With(logger, "ts", log.DefaultTimestampUTC)logger = log.With(logger, "caller", log.DefaultCaller)}err := configs.Init(*confFile)if err != nil {panic(err)}ctx := context.Background()ctx = context.WithValue(ctx, "ginMod", configs.Conf.ServerConfig.Mode)r := transport.NewHttpHandler(ctx, configs.Conf, logger)errChan := make(chan error)go func() {errChan <- r.Run(fmt.Sprintf(":%s", strconv.Itoa(configs.Conf.ServerConfig.Port)))}()go func() {c := make(chan os.Signal, 1)signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)errChan <- fmt.Errorf("%s", <-c)}()fmt.Println(<-errChan)
}
启动
进入 library-apigateway 目录,执行 go run main.go 如图:

服务成功启动,监听80端口
接口测试
在 /etc/hosts 中配置 api.library.com 域名
使用postman进行接口测试,在这里进行了 findBooksByUserID 的接口测试,结果如图:

下一篇文章,我们在各个服务中加入分布式链路追踪功能。
完整代码:
https://github.com/Justin02180218/micro-kit
更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
