当前位置:首页 » 《随便一记》 » 正文

九,自写网关(library-apigateway)_Coding到灯火阑珊的专栏

26 人参与  2022年03月17日 17:57  分类 : 《随便一记》  评论

点击全文阅读


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

图片

完整代码:

https://github.com/Justin02180218/micro-kit

包结构

图片

 

 

 

 

目前网关的功能只是做接口转发,所以只有一个 transport 层。

代码实现

配置文件

server:
  port: 80
  mode: debug
  name: "apigateway"
  
consul:
  addr: "http://consul-server:8500"
  interval: "10s"
  timeout: "1s"
  client: 
    retrymax: 3
    retrytimeout: 500

修改 consul.go

func HttpClient(cfg *configs.AppConfig, name, method, path string, logger log.Logger) endpoint.Endpoint {
    consulAddr := cfg.ConsulConfig.Addr
    retryMax := cfg.ConsulConfig.Client.RetryMax
    retryTimeout := cfg.ConsulConfig.Client.RetryTimeout
    client := 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 = path
        
        return 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


更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号


点击全文阅读


本文链接:http://zhangshiyu.com/post/36347.html

接口  如图  启动  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1