├── README.md ├── micro-kit-apigateway ├── .DS_Store ├── go.mod ├── go.sum ├── library-apigateway │ ├── apigateway.yaml │ ├── main.go │ └── transport │ │ └── apigateway_transport.go ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── circuitbreakers │ │ └── hystrix.go │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-base ├── .DS_Store ├── go.mod ├── go.sum ├── library-user-service │ ├── main.go │ └── user.yaml └── pkg │ ├── .DS_Store │ ├── configs │ └── config.go │ └── databases │ └── mysql.go ├── micro-kit-book-grpc ├── .DS_Store ├── go.mod ├── go.sum ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ └── utils │ │ └── http_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-book ├── .DS_Store ├── go.mod ├── go.sum ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ └── utils │ │ └── http_util.go └── sql │ └── library.sql ├── micro-kit-consul ├── .DS_Store ├── go.mod ├── go.sum ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-docker ├── .DS_Store ├── deploy │ ├── docker │ │ ├── Dockerfile.apigateway │ │ ├── Dockerfile.book │ │ ├── Dockerfile.bookrpc │ │ └── Dockerfile.user │ └── prometheus │ │ ├── prometheus-grafana.yaml │ │ └── prometheus.yaml ├── go.mod ├── go.sum ├── library-apigateway │ ├── apigateway.yaml │ ├── main.go │ └── transport │ │ └── apigateway_transport.go ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ ├── user_service.go │ │ └── user_service_metrics.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── circuitbreakers │ │ └── hystrix.go │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── monitors │ │ └── prometheus.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ ├── tracers │ │ └── zipkin.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-hystrix ├── .DS_Store ├── go.mod ├── go.sum ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── circuitbreakers │ │ └── hystrix.go │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-k8s ├── .DS_Store ├── deploy │ ├── docker │ │ ├── Dockerfile.apigateway │ │ ├── Dockerfile.book │ │ ├── Dockerfile.bookrpc │ │ └── Dockerfile.user │ ├── k8s │ │ ├── k8s-apigateway-ingress.yaml │ │ ├── k8s-apigateway-service.yaml │ │ ├── k8s-book-deployment.yaml │ │ ├── k8s-book-rpc-deployment.yaml │ │ ├── k8s-hystrixdashboard-service.yaml │ │ ├── k8s-monitor.yaml │ │ ├── k8s-user-deployment.yaml │ │ └── k8s-zipkin-service.yaml │ └── prometheus │ │ ├── prometheus-grafana.yaml │ │ └── prometheus.yaml ├── go.mod ├── go.sum ├── library-apigateway │ ├── apigateway.yaml │ ├── main.go │ └── transport │ │ └── apigateway_transport.go ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ ├── user_service.go │ │ └── user_service_metrics.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── circuitbreakers │ │ └── hystrix.go │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── monitors │ │ └── prometheus.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ ├── tracers │ │ └── zipkin.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-prometheus ├── .DS_Store ├── deploy │ └── prometheus │ │ ├── prometheus-grafana.yaml │ │ └── prometheus.yaml ├── go.mod ├── go.sum ├── library-apigateway │ ├── apigateway.yaml │ ├── main.go │ └── transport │ │ └── apigateway_transport.go ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ ├── book_service.go │ │ └── book_service_metrics.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ ├── book_rpc_endpoint.go │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ ├── user_service.go │ │ └── user_service_metrics.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── circuitbreakers │ │ └── hystrix.go │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── monitors │ │ └── prometheus.go │ ├── ratelimits │ │ └── ratelimit.go │ ├── registers │ │ └── consul.go │ ├── tracers │ │ └── zipkin.go │ └── utils │ │ ├── http_util.go │ │ └── net_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-ratelimit ├── .DS_Store ├── go.mod ├── go.sum ├── library-book-grpc-service │ ├── book_rpc.yaml │ ├── dao │ │ └── book_dao.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-book-service │ ├── book.yaml │ ├── dao │ │ └── book_dao.go │ ├── dto │ │ └── book_dto.go │ ├── endpoint │ │ └── book_endpoint.go │ ├── main.go │ ├── models │ │ └── book.go │ ├── service │ │ └── book_service.go │ └── transport │ │ └── book_transport.go ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ ├── ratelimits │ │ └── ratelimit.go │ └── utils │ │ └── http_util.go ├── protos │ └── book │ │ ├── book.pb.go │ │ ├── book.proto │ │ └── book_grpc.pb.go └── sql │ └── library.sql ├── micro-kit-user ├── .DS_Store ├── go.mod ├── go.sum ├── library-user-service │ ├── dao │ │ └── user_dao.go │ ├── dto │ │ └── user_dto.go │ ├── endpoint │ │ └── user_endpoint.go │ ├── main.go │ ├── models │ │ └── user.go │ ├── service │ │ └── user_service.go │ ├── transport │ │ └── user_transport.go │ └── user.yaml ├── pkg │ ├── configs │ │ └── config.go │ ├── databases │ │ └── mysql.go │ └── utils │ │ └── http_util.go └── sql │ └── library.sql └── micro-kit-zipkin ├── .DS_Store ├── go.mod ├── go.sum ├── library-apigateway ├── apigateway.yaml ├── main.go └── transport │ └── apigateway_transport.go ├── library-book-grpc-service ├── book_rpc.yaml ├── dao │ └── book_dao.go ├── endpoint │ └── book_endpoint.go ├── main.go ├── models │ └── book.go ├── service │ └── book_service.go └── transport │ └── book_transport.go ├── library-book-service ├── book.yaml ├── dao │ └── book_dao.go ├── dto │ └── book_dto.go ├── endpoint │ └── book_endpoint.go ├── main.go ├── models │ └── book.go ├── service │ └── book_service.go └── transport │ └── book_transport.go ├── library-user-service ├── dao │ └── user_dao.go ├── dto │ └── user_dto.go ├── endpoint │ ├── book_rpc_endpoint.go │ └── user_endpoint.go ├── main.go ├── models │ └── user.go ├── service │ └── user_service.go ├── transport │ └── user_transport.go └── user.yaml ├── pkg ├── circuitbreakers │ └── hystrix.go ├── configs │ └── config.go ├── databases │ └── mysql.go ├── ratelimits │ └── ratelimit.go ├── registers │ └── consul.go ├── tracers │ └── zipkin.go └── utils │ ├── http_util.go │ └── net_util.go ├── protos └── book │ ├── book.pb.go │ ├── book.proto │ └── book_grpc.pb.go └── sql └── library.sql /micro-kit-apigateway/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-apigateway/.DS_Store -------------------------------------------------------------------------------- /micro-kit-apigateway/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | google.golang.org/grpc v1.38.0 15 | google.golang.org/protobuf v1.27.1 16 | gopkg.in/yaml.v2 v2.4.0 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-apigateway/apigateway.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | mode: debug 4 | name: "apigateway" 5 | 6 | consul: 7 | addr: "http://consul-server:8500" 8 | interval: "10s" 9 | timeout: "1s" 10 | client: 11 | retrymax: 3 12 | retrytimeout: 500 13 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-apigateway/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "com/justin/micro/kit/library-apigateway/transport" 5 | "com/justin/micro/kit/pkg/configs" 6 | "context" 7 | "flag" 8 | "fmt" 9 | "os" 10 | "os/signal" 11 | "strconv" 12 | "syscall" 13 | 14 | "github.com/go-kit/kit/log" 15 | ) 16 | 17 | var confFile = flag.String("f", "apigateway.yaml", "user config file") 18 | 19 | func main() { 20 | flag.Parse() 21 | 22 | var logger log.Logger 23 | { 24 | logger = log.NewLogfmtLogger(os.Stderr) 25 | logger = log.With(logger, "ts", log.DefaultTimestampUTC) 26 | logger = log.With(logger, "caller", log.DefaultCaller) 27 | } 28 | 29 | err := configs.Init(*confFile) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | ctx := context.Background() 35 | 36 | ctx = context.WithValue(ctx, "ginMod", configs.Conf.ServerConfig.Mode) 37 | r := transport.NewHttpHandler(ctx, configs.Conf, logger) 38 | 39 | errChan := make(chan error) 40 | go func() { 41 | errChan <- r.Run(fmt.Sprintf(":%s", strconv.Itoa(configs.Conf.ServerConfig.Port))) 42 | }() 43 | 44 | go func() { 45 | c := make(chan os.Signal, 1) 46 | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) 47 | errChan <- fmt.Errorf("%s", <-c) 48 | }() 49 | fmt.Println(<-errChan) 50 | } 51 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-grpc-service/transport/book_transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/endpoint" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | kitrpc "github.com/go-kit/kit/transport/grpc" 10 | ) 11 | 12 | type grpcServer struct { 13 | pbbook.UnimplementedBookServer 14 | findBooksByUserID kitrpc.Handler 15 | } 16 | 17 | func (g grpcServer) FindBooksByUserID(ctx context.Context, r *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 18 | _, res, err := g.findBooksByUserID.ServeGRPC(ctx, r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res.(*pbbook.BooksResponse), nil 23 | } 24 | 25 | func NewBookServer(ctx context.Context, endpoints endpoint.BookEndpoints) pbbook.BookServer { 26 | return &grpcServer{ 27 | findBooksByUserID: kitrpc.NewServer( 28 | endpoints.FindBooksByUserIDEndpoint, 29 | decodeFindBooksByUserIDRequest, 30 | encodeFindBooksByUserIDResponse, 31 | ), 32 | } 33 | } 34 | 35 | func decodeFindBooksByUserIDRequest(ctx context.Context, request interface{}) (interface{}, error) { 36 | req := request.(*pbbook.BooksByUserIDRequest) 37 | return &pbbook.BooksByUserIDRequest{ 38 | UserID: req.UserID, 39 | }, nil 40 | } 41 | 42 | func encodeFindBooksByUserIDResponse(ctx context.Context, response interface{}) (interface{}, error) { 43 | resp := response.(*pbbook.BooksResponse) 44 | return &pbbook.BooksResponse{ 45 | Books: resp.Books, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | "github.com/go-kit/kit/endpoint" 10 | grpctransport "github.com/go-kit/kit/transport/grpc" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | type BookRPCEndpoints struct { 15 | FindBooksEndpoint endpoint.Endpoint 16 | } 17 | 18 | func MakeFindBooksEndpoint(instance string) endpoint.Endpoint { 19 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 20 | if err != nil { 21 | fmt.Println(err) 22 | return nil 23 | } 24 | findBooksEndpoint := grpctransport.NewClient( 25 | conn, "book.Book", "FindBooksByUserID", 26 | encodeGRPCFindBooksRequest, 27 | decodeGRPCFindBooksResponse, 28 | pbbook.BooksResponse{}, 29 | ).Endpoint() 30 | return findBooksEndpoint 31 | } 32 | 33 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 34 | userID := r.(uint64) 35 | return &pbbook.BooksByUserIDRequest{ 36 | UserID: userID, 37 | }, nil 38 | } 39 | 40 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 41 | resp := r.(*pbbook.BooksResponse) 42 | return resp.Books, nil 43 | } 44 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-apigateway/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 -------------------------------------------------------------------------------- /micro-kit-apigateway/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-apigateway/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-apigateway/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-apigateway/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-apigateway/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-apigateway/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-base/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-base/.DS_Store -------------------------------------------------------------------------------- /micro-kit-base/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/go-sql-driver/mysql v1.5.0 8 | github.com/jinzhu/gorm v1.9.16 9 | gopkg.in/yaml.v2 v2.4.0 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /micro-kit-base/library-user-service/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "com/justin/micro/kit/pkg/databases" 6 | "flag" 7 | "fmt" 8 | ) 9 | 10 | var confFile = flag.String("f", "user.yaml", "user config file") 11 | 12 | func main() { 13 | flag.Parse() 14 | 15 | err := configs.Init(*confFile) 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | err = databases.InitMySql(configs.Conf.MySQLConfig) 21 | if err != nil { 22 | fmt.Println("load mysql failed") 23 | } 24 | _, ok := databases.DB.Get("library") 25 | fmt.Println(ok) 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-base/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-base/pkg/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-base/pkg/.DS_Store -------------------------------------------------------------------------------- /micro-kit-base/pkg/configs/config.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/ghodss/yaml" 8 | ) 9 | 10 | type ServerConfig struct { 11 | Port int `json:"port" yaml:"port"` 12 | Mode string `json:"mode" yaml:"mode"` 13 | Name string `json:"name" yaml:"name"` 14 | } 15 | 16 | type MySQLConfig struct { 17 | Host string `json:"host" yaml:"host"` 18 | Username string `json:"username" yaml:"username"` 19 | Password string `json:"password" yaml:"password"` 20 | Port string `json:"port" yaml:"port"` 21 | Db string `json:"db" yaml:"db"` 22 | Debug bool `json:"debug" yaml:"debug"` 23 | } 24 | 25 | type AppConfig struct { 26 | *ServerConfig `json:"server" yaml:"server"` 27 | *MySQLConfig `json:"mysql" yaml:"mysql"` 28 | } 29 | 30 | var Conf = new(AppConfig) 31 | 32 | func Init(file string) error { 33 | yamlData, err := ioutil.ReadFile(file) 34 | if err != nil { 35 | fmt.Println(err) 36 | return err 37 | } 38 | if err = yaml.Unmarshal(yamlData, Conf); err != nil { 39 | return err 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /micro-kit-base/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-book-grpc/.DS_Store -------------------------------------------------------------------------------- /micro-kit-book-grpc/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/gin-gonic/gin v1.7.4 8 | github.com/go-kit/kit v0.11.0 9 | github.com/go-sql-driver/mysql v1.5.0 10 | github.com/jinzhu/gorm v1.9.16 11 | google.golang.org/grpc v1.38.0 12 | google.golang.org/protobuf v1.27.1 13 | gopkg.in/yaml.v2 v2.4.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-grpc-service/transport/book_transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/endpoint" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | kitrpc "github.com/go-kit/kit/transport/grpc" 10 | ) 11 | 12 | type grpcServer struct { 13 | pbbook.UnimplementedBookServer 14 | findBooksByUserID kitrpc.Handler 15 | } 16 | 17 | func (g grpcServer) FindBooksByUserID(ctx context.Context, r *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 18 | _, res, err := g.findBooksByUserID.ServeGRPC(ctx, r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res.(*pbbook.BooksResponse), nil 23 | } 24 | 25 | func NewBookServer(ctx context.Context, endpoints endpoint.BookEndpoints) pbbook.BookServer { 26 | return &grpcServer{ 27 | findBooksByUserID: kitrpc.NewServer( 28 | endpoints.FindBooksByUserIDEndpoint, 29 | decodeFindBooksByUserIDRequest, 30 | encodeFindBooksByUserIDResponse, 31 | ), 32 | } 33 | } 34 | 35 | func decodeFindBooksByUserIDRequest(ctx context.Context, request interface{}) (interface{}, error) { 36 | req := request.(*pbbook.BooksByUserIDRequest) 37 | return &pbbook.BooksByUserIDRequest{ 38 | UserID: req.UserID, 39 | }, nil 40 | } 41 | 42 | func encodeFindBooksByUserIDResponse(ctx context.Context, response interface{}) (interface{}, error) { 43 | resp := response.(*pbbook.BooksResponse) 44 | return &pbbook.BooksResponse{ 45 | Books: resp.Books, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/pkg/configs/config.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/ghodss/yaml" 8 | ) 9 | 10 | type ServerConfig struct { 11 | Port int `json:"port" yaml:"port"` 12 | Mode string `json:"mode" yaml:"mode"` 13 | Name string `json:"name" yaml:"name"` 14 | } 15 | 16 | type MySQLConfig struct { 17 | Host string `json:"host" yaml:"host"` 18 | Username string `json:"username" yaml:"username"` 19 | Password string `json:"password" yaml:"password"` 20 | Port string `json:"port" yaml:"port"` 21 | Db string `json:"db" yaml:"db"` 22 | Debug bool `json:"debug" yaml:"debug"` 23 | } 24 | 25 | type AppConfig struct { 26 | *ServerConfig `json:"server" yaml:"server"` 27 | *MySQLConfig `json:"mysql" yaml:"mysql"` 28 | } 29 | 30 | var Conf = new(AppConfig) 31 | 32 | func Init(file string) error { 33 | yamlData, err := ioutil.ReadFile(file) 34 | if err != nil { 35 | fmt.Println(err) 36 | return err 37 | } 38 | if err = yaml.Unmarshal(yamlData, Conf); err != nil { 39 | return err 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-book-grpc/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-book-grpc/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-book/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-book/.DS_Store -------------------------------------------------------------------------------- /micro-kit-book/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/gin-gonic/gin v1.7.4 8 | github.com/go-kit/kit v0.11.0 9 | github.com/go-sql-driver/mysql v1.5.0 10 | github.com/jinzhu/gorm v1.9.16 11 | gopkg.in/yaml.v2 v2.4.0 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /micro-kit-book/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-book/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-book/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-book/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-book/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-book/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-book/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-book/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-book/pkg/configs/config.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/ghodss/yaml" 8 | ) 9 | 10 | type ServerConfig struct { 11 | Port int `json:"port" yaml:"port"` 12 | Mode string `json:"mode" yaml:"mode"` 13 | Name string `json:"name" yaml:"name"` 14 | } 15 | 16 | type MySQLConfig struct { 17 | Host string `json:"host" yaml:"host"` 18 | Username string `json:"username" yaml:"username"` 19 | Password string `json:"password" yaml:"password"` 20 | Port string `json:"port" yaml:"port"` 21 | Db string `json:"db" yaml:"db"` 22 | Debug bool `json:"debug" yaml:"debug"` 23 | } 24 | 25 | type AppConfig struct { 26 | *ServerConfig `json:"server" yaml:"server"` 27 | *MySQLConfig `json:"mysql" yaml:"mysql"` 28 | } 29 | 30 | var Conf = new(AppConfig) 31 | 32 | func Init(file string) error { 33 | yamlData, err := ioutil.ReadFile(file) 34 | if err != nil { 35 | fmt.Println(err) 36 | return err 37 | } 38 | if err = yaml.Unmarshal(yamlData, Conf); err != nil { 39 | return err 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /micro-kit-book/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-book/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-book/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-consul/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-consul/.DS_Store -------------------------------------------------------------------------------- /micro-kit-consul/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/gin-gonic/gin v1.7.4 8 | github.com/go-kit/kit v0.11.0 9 | github.com/go-sql-driver/mysql v1.5.0 10 | github.com/hashicorp/consul/api v1.8.1 11 | github.com/jinzhu/gorm v1.9.16 12 | github.com/juju/ratelimit v1.0.1 13 | google.golang.org/grpc v1.38.0 14 | google.golang.org/protobuf v1.27.1 15 | gopkg.in/yaml.v2 v2.4.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-grpc-service/transport/book_transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/endpoint" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | kitrpc "github.com/go-kit/kit/transport/grpc" 10 | ) 11 | 12 | type grpcServer struct { 13 | pbbook.UnimplementedBookServer 14 | findBooksByUserID kitrpc.Handler 15 | } 16 | 17 | func (g grpcServer) FindBooksByUserID(ctx context.Context, r *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 18 | _, res, err := g.findBooksByUserID.ServeGRPC(ctx, r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res.(*pbbook.BooksResponse), nil 23 | } 24 | 25 | func NewBookServer(ctx context.Context, endpoints endpoint.BookEndpoints) pbbook.BookServer { 26 | return &grpcServer{ 27 | findBooksByUserID: kitrpc.NewServer( 28 | endpoints.FindBooksByUserIDEndpoint, 29 | decodeFindBooksByUserIDRequest, 30 | encodeFindBooksByUserIDResponse, 31 | ), 32 | } 33 | } 34 | 35 | func decodeFindBooksByUserIDRequest(ctx context.Context, request interface{}) (interface{}, error) { 36 | req := request.(*pbbook.BooksByUserIDRequest) 37 | return &pbbook.BooksByUserIDRequest{ 38 | UserID: req.UserID, 39 | }, nil 40 | } 41 | 42 | func encodeFindBooksByUserIDResponse(ctx context.Context, response interface{}) (interface{}, error) { 43 | resp := response.(*pbbook.BooksResponse) 44 | return &pbbook.BooksResponse{ 45 | Books: resp.Books, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-consul/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-consul/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-consul/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-consul/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | "github.com/go-kit/kit/endpoint" 10 | grpctransport "github.com/go-kit/kit/transport/grpc" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | type BookRPCEndpoints struct { 15 | FindBooksEndpoint endpoint.Endpoint 16 | } 17 | 18 | func MakeFindBooksEndpoint(instance string) endpoint.Endpoint { 19 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 20 | if err != nil { 21 | fmt.Println(err) 22 | return nil 23 | } 24 | findBooksEndpoint := grpctransport.NewClient( 25 | conn, "book.Book", "FindBooksByUserID", 26 | encodeGRPCFindBooksRequest, 27 | decodeGRPCFindBooksResponse, 28 | pbbook.BooksResponse{}, 29 | ).Endpoint() 30 | return findBooksEndpoint 31 | } 32 | 33 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 34 | userID := r.(uint64) 35 | return &pbbook.BooksByUserIDRequest{ 36 | UserID: userID, 37 | }, nil 38 | } 39 | 40 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 41 | resp := r.(*pbbook.BooksResponse) 42 | return resp.Books, nil 43 | } 44 | -------------------------------------------------------------------------------- /micro-kit-consul/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-consul/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" -------------------------------------------------------------------------------- /micro-kit-consul/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-consul/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-consul/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-consul/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-consul/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-consul/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-docker/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-docker/.DS_Store -------------------------------------------------------------------------------- /micro-kit-docker/deploy/docker/Dockerfile.apigateway: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o apigateway -a -tags netgo -ldflags '-s -w' ./library-apigateway 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/apigateway . 12 | COPY --from=builder /app/library-apigateway/apigateway.yaml . 13 | EXPOSE 10087 14 | ENTRYPOINT ["/apigateway"] -------------------------------------------------------------------------------- /micro-kit-docker/deploy/docker/Dockerfile.book: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o book-service -a -tags netgo -ldflags '-s -w' ./library-book-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/book-service . 12 | COPY --from=builder /app/library-book-service/book.yaml . 13 | EXPOSE 10087 14 | ENTRYPOINT ["/book-service"] -------------------------------------------------------------------------------- /micro-kit-docker/deploy/docker/Dockerfile.bookrpc: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o book-rpc-service -a -tags netgo -ldflags '-s -w' ./library-book-rpc-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/book-rpc-service . 12 | COPY --from=builder /app/library-book-rpc-service/book_rpc.yaml . 13 | EXPOSE 10088 14 | ENTRYPOINT ["/book-rpc-service"] -------------------------------------------------------------------------------- /micro-kit-docker/deploy/docker/Dockerfile.user: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o user-service -a -tags netgo -ldflags '-s -w' ./library-user-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/user-service . 12 | COPY --from=builder /app/library-user-service/user.yaml . 13 | EXPOSE 10086 14 | ENTRYPOINT ["/user-service"] -------------------------------------------------------------------------------- /micro-kit-docker/deploy/prometheus/prometheus-grafana.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | prometheus: 5 | image: prom/prometheus 6 | ports: 7 | - 9090:9090 8 | volumes: 9 | - /Users/Justin/workspace_go_execise/go-kit-exercise/micro-kit/micro-kit-prometheus/deploy/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml 10 | grafana: 11 | image: grafana/grafana 12 | ports: 13 | - 3000:3000 14 | environment: 15 | - GF_SECURITY_ADMIN_PASSWORD=123456 16 | volumes: 17 | - /Users/Justin/grafana_db:/var/lib/grafana grafana/grafana 18 | 19 | -------------------------------------------------------------------------------- /micro-kit-docker/deploy/prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | external_labels: 4 | monitor: 'library-monitor' 5 | 6 | scrape_configs: 7 | - job_name: 'prometheus' 8 | scrape_interval: 5s 9 | static_configs: 10 | - targets: ['192.168.1.11:9090'] 11 | labels: 12 | group: 'local' 13 | 14 | - job_name: 'library' 15 | scrape_interval: 5s 16 | static_configs: 17 | - targets: ['192.168.1.11:10086', '192.168.1.11:10087', '192.168.1.11:10089'] 18 | labels: 19 | group: 'library' 20 | 21 | -------------------------------------------------------------------------------- /micro-kit-docker/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | github.com/openzipkin/zipkin-go v0.2.5 15 | github.com/prometheus/client_golang v1.11.0 16 | google.golang.org/grpc v1.38.0 17 | google.golang.org/protobuf v1.27.1 18 | gopkg.in/yaml.v2 v2.4.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /micro-kit-docker/library-apigateway/apigateway.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | mode: debug 4 | name: "apigateway" 5 | 6 | consul: 7 | addr: "http://consul-server:8500" 8 | interval: "10s" 9 | timeout: "1s" 10 | client: 11 | retrymax: 3 12 | retrytimeout: 500 13 | 14 | zipkin: 15 | url: "http://zipkin-server:9411/api/v2/spans" 16 | service_name: "apigateway" 17 | reporter: 18 | timeout: 5 19 | batch_size: 1000 20 | batch_interval: 3 21 | max_backlog: 10000 22 | -------------------------------------------------------------------------------- /micro-kit-docker/library-apigateway/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "com/justin/micro/kit/library-apigateway/transport" 5 | "com/justin/micro/kit/pkg/configs" 6 | "com/justin/micro/kit/pkg/tracers" 7 | "context" 8 | "flag" 9 | "fmt" 10 | "os" 11 | "os/signal" 12 | "strconv" 13 | "syscall" 14 | 15 | "github.com/go-kit/kit/log" 16 | ) 17 | 18 | var confFile = flag.String("f", "apigateway.yaml", "user config file") 19 | 20 | func main() { 21 | flag.Parse() 22 | 23 | var logger log.Logger 24 | { 25 | logger = log.NewLogfmtLogger(os.Stderr) 26 | logger = log.With(logger, "ts", log.DefaultTimestampUTC) 27 | logger = log.With(logger, "caller", log.DefaultCaller) 28 | } 29 | 30 | err := configs.Init(*confFile) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | ctx := context.Background() 36 | 37 | reporter := tracers.NewZipkinReporter(configs.Conf.ZipkinConfig) 38 | defer reporter.Close() 39 | tracer := tracers.NewZipkinTracer(configs.Conf.ZipkinConfig.ServiceName, reporter) 40 | 41 | ctx = context.WithValue(ctx, "ginMod", configs.Conf.ServerConfig.Mode) 42 | r := transport.NewHttpHandler(ctx, configs.Conf, tracer, logger) 43 | 44 | errChan := make(chan error) 45 | go func() { 46 | errChan <- r.Run(fmt.Sprintf(":%s", strconv.Itoa(configs.Conf.ServerConfig.Port))) 47 | }() 48 | 49 | go func() { 50 | c := make(chan os.Signal, 1) 51 | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) 52 | errChan <- fmt.Errorf("%s", <-c) 53 | }() 54 | fmt.Println(<-errChan) 55 | } 56 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-rpc-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_rpc_service" 35 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | 42 | type ServiceMiddleware func(BookService) BookService 43 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-grpc-service/service/book_service_metrics.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/monitors" 5 | pbbook "com/justin/micro/kit/protos/book" 6 | "context" 7 | "time" 8 | 9 | "github.com/go-kit/kit/metrics" 10 | ) 11 | 12 | func MetricsMiddleware(prometheusParams *monitors.PrometheusParams) ServiceMiddleware { 13 | return func(next BookService) BookService { 14 | return metricsMiddleware{next, prometheusParams.Counter, prometheusParams.Summary} 15 | } 16 | } 17 | 18 | type metricsMiddleware struct { 19 | BookService 20 | requestCount metrics.Counter 21 | requestLatency metrics.Histogram 22 | } 23 | 24 | func (mw metricsMiddleware) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | defer func(begin time.Time) { 26 | lvs := []string{"method", "FindBooksByUserID"} 27 | mw.requestCount.With(lvs...).Add(1) 28 | mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) 29 | }(time.Now()) 30 | return mw.BookService.FindBooksByUserID(ctx, req) 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_service" -------------------------------------------------------------------------------- /micro-kit-docker/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-docker/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-docker/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-docker/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-docker/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "com/justin/micro/kit/pkg/tracers" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | 10 | "github.com/go-kit/kit/endpoint" 11 | grpctransport "github.com/go-kit/kit/transport/grpc" 12 | gozipkin "github.com/openzipkin/zipkin-go" 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | type BookRPCEndpoints struct { 17 | FindBooksEndpoint endpoint.Endpoint 18 | } 19 | 20 | func MakeFindBooksEndpoint(instance string, tracer *gozipkin.Tracer) endpoint.Endpoint { 21 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 22 | if err != nil { 23 | fmt.Println(err) 24 | return nil 25 | } 26 | findBooksEndpoint := grpctransport.NewClient( 27 | conn, "book.Book", "FindBooksByUserID", 28 | encodeGRPCFindBooksRequest, 29 | decodeGRPCFindBooksResponse, 30 | pbbook.BooksResponse{}, 31 | tracers.MakeGrpcClientOptions(tracer, "grpc-transport-findBooks")..., 32 | ).Endpoint() 33 | return findBooksEndpoint 34 | } 35 | 36 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 37 | userID := r.(uint64) 38 | return &pbbook.BooksByUserIDRequest{ 39 | UserID: userID, 40 | }, nil 41 | } 42 | 43 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 44 | resp := r.(*pbbook.BooksResponse) 45 | return resp.Books, nil 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-docker/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-docker/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 30 | 31 | zipkin: 32 | url: "http://zipkin-server:9411/api/v2/spans" 33 | service_name: "user-service" 34 | reporter: 35 | timeout: 5 36 | batch_size: 1000 37 | batch_interval: 3 38 | max_backlog: 10000 39 | 40 | prometheus: 41 | namespace: "library" 42 | subsystem: "user_service" -------------------------------------------------------------------------------- /micro-kit-docker/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-docker/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-docker/pkg/monitors/prometheus.go: -------------------------------------------------------------------------------- 1 | package monitors 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | 6 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" 7 | stdprometheus "github.com/prometheus/client_golang/prometheus" 8 | ) 9 | 10 | type PrometheusParams struct { 11 | Counter *kitprometheus.Counter 12 | Summary *kitprometheus.Summary 13 | Gauge *kitprometheus.Gauge 14 | Histogram *kitprometheus.Histogram 15 | } 16 | 17 | func MakePrometheusParams(conf *configs.PrometheusConfig) *PrometheusParams { 18 | fieldKeys := []string{"method"} 19 | requestCounter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ 20 | Namespace: conf.Namespace, 21 | Subsystem: conf.Subsystem, 22 | Name: "request_count", 23 | Help: "Number of requests received.", 24 | }, fieldKeys) 25 | requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ 26 | Namespace: conf.Namespace, 27 | Subsystem: conf.Subsystem, 28 | Name: "request_latency_microseconds", 29 | Help: "Total duration of requests in microseconds.", 30 | }, fieldKeys) 31 | 32 | return &PrometheusParams{requestCounter, requestLatency, nil, nil} 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-docker/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-docker/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-docker/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-docker/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-hystrix/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-hystrix/.DS_Store -------------------------------------------------------------------------------- /micro-kit-hystrix/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | google.golang.org/grpc v1.38.0 15 | google.golang.org/protobuf v1.27.1 16 | gopkg.in/yaml.v2 v2.4.0 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-grpc-service/transport/book_transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/endpoint" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | kitrpc "github.com/go-kit/kit/transport/grpc" 10 | ) 11 | 12 | type grpcServer struct { 13 | pbbook.UnimplementedBookServer 14 | findBooksByUserID kitrpc.Handler 15 | } 16 | 17 | func (g grpcServer) FindBooksByUserID(ctx context.Context, r *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 18 | _, res, err := g.findBooksByUserID.ServeGRPC(ctx, r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res.(*pbbook.BooksResponse), nil 23 | } 24 | 25 | func NewBookServer(ctx context.Context, endpoints endpoint.BookEndpoints) pbbook.BookServer { 26 | return &grpcServer{ 27 | findBooksByUserID: kitrpc.NewServer( 28 | endpoints.FindBooksByUserIDEndpoint, 29 | decodeFindBooksByUserIDRequest, 30 | encodeFindBooksByUserIDResponse, 31 | ), 32 | } 33 | } 34 | 35 | func decodeFindBooksByUserIDRequest(ctx context.Context, request interface{}) (interface{}, error) { 36 | req := request.(*pbbook.BooksByUserIDRequest) 37 | return &pbbook.BooksByUserIDRequest{ 38 | UserID: req.UserID, 39 | }, nil 40 | } 41 | 42 | func encodeFindBooksByUserIDResponse(ctx context.Context, response interface{}) (interface{}, error) { 43 | resp := response.(*pbbook.BooksResponse) 44 | return &pbbook.BooksResponse{ 45 | Books: resp.Books, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | "github.com/go-kit/kit/endpoint" 10 | grpctransport "github.com/go-kit/kit/transport/grpc" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | type BookRPCEndpoints struct { 15 | FindBooksEndpoint endpoint.Endpoint 16 | } 17 | 18 | func MakeFindBooksEndpoint(instance string) endpoint.Endpoint { 19 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 20 | if err != nil { 21 | fmt.Println(err) 22 | return nil 23 | } 24 | findBooksEndpoint := grpctransport.NewClient( 25 | conn, "book.Book", "FindBooksByUserID", 26 | encodeGRPCFindBooksRequest, 27 | decodeGRPCFindBooksResponse, 28 | pbbook.BooksResponse{}, 29 | ).Endpoint() 30 | return findBooksEndpoint 31 | } 32 | 33 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 34 | userID := r.(uint64) 35 | return &pbbook.BooksByUserIDRequest{ 36 | UserID: userID, 37 | }, nil 38 | } 39 | 40 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 41 | resp := r.(*pbbook.BooksResponse) 42 | return resp.Books, nil 43 | } 44 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-hystrix/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 -------------------------------------------------------------------------------- /micro-kit-hystrix/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-hystrix/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-hystrix/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-hystrix/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-hystrix/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-hystrix/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-hystrix/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-k8s/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-k8s/.DS_Store -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/docker/Dockerfile.apigateway: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o apigateway -a -tags netgo -ldflags '-s -w' ./library-apigateway 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/apigateway . 12 | COPY --from=builder /app/library-apigateway/apigateway.yaml . 13 | EXPOSE 10087 14 | ENTRYPOINT ["/apigateway"] -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/docker/Dockerfile.book: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o book-service -a -tags netgo -ldflags '-s -w' ./library-book-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/book-service . 12 | COPY --from=builder /app/library-book-service/book.yaml . 13 | EXPOSE 10087 14 | ENTRYPOINT ["/book-service"] -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/docker/Dockerfile.bookrpc: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o book-rpc-service -a -tags netgo -ldflags '-s -w' ./library-book-rpc-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/book-rpc-service . 12 | COPY --from=builder /app/library-book-rpc-service/book_rpc.yaml . 13 | EXPOSE 10088 14 | ENTRYPOINT ["/book-rpc-service"] -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/docker/Dockerfile.user: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS builder 2 | RUN go env -w GO111MODULE=on 3 | RUN go env -w GOPROXY=https://goproxy.cn,direct 4 | RUN mkdir /app 5 | COPY . /app 6 | WORKDIR /app 7 | RUN CGO_ENABLED=0 GOOS=linux go build -o user-service -a -tags netgo -ldflags '-s -w' ./library-user-service 8 | 9 | FROM scratch 10 | LABEL justin justin@ 11 | COPY --from=builder /app/user-service . 12 | COPY --from=builder /app/library-user-service/user.yaml . 13 | EXPOSE 10086 14 | ENTRYPOINT ["/user-service"] -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-apigateway-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: apigateway-ingress 5 | spec: 6 | rules: 7 | - host: api.library.com 8 | http: 9 | paths: 10 | - path: / 11 | pathType: Prefix 12 | backend: 13 | service: 14 | name: library-apigateway 15 | port: 16 | number: 80 17 | - host: consul.library.com 18 | http: 19 | paths: 20 | - path: / 21 | pathType: Prefix 22 | backend: 23 | service: 24 | name: consul-ui 25 | port: 26 | number: 80 27 | - host: zipkin.library.com 28 | http: 29 | paths: 30 | - path: / 31 | pathType: Prefix 32 | backend: 33 | service: 34 | name: zipkin-server 35 | port: 36 | number: 9411 37 | - host: hystrix.library.com 38 | http: 39 | paths: 40 | - path: / 41 | pathType: Prefix 42 | backend: 43 | service: 44 | name: hystrix-dashboard 45 | port: 46 | number: 9002 47 | -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-apigateway-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: library-apigateway 5 | labels: 6 | svc: library 7 | app: apigateway 8 | spec: 9 | replicas: 2 10 | selector: 11 | matchLabels: 12 | svc: library 13 | app: apigateway 14 | template: 15 | metadata: 16 | labels: 17 | svc: library 18 | app: apigateway 19 | spec: 20 | containers: 21 | - name: library-apigateway 22 | image: harbor.justin.com/micro-kit/apigateway:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 80 26 | resources: 27 | requests: 28 | memory: 64Mi 29 | cpu: 250m 30 | limits: 31 | memory: 64Mi 32 | cpu: 250m 33 | initContainers: 34 | - command: 35 | - sh 36 | - -c 37 | - until curl -m5 -s consul-ui:80/ui; do echo waiting for config; sleep 5; done; 38 | image: hashicorp/consul:1.10.0 39 | name: consul-ui 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: library-apigateway 45 | spec: 46 | ports: 47 | - port: 80 48 | selector: 49 | svc: library 50 | app: apigateway 51 | -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-book-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: book-service 5 | labels: 6 | svc: book 7 | app: service 8 | spec: 9 | replicas: 2 10 | selector: 11 | matchLabels: 12 | svc: book 13 | app: service 14 | template: 15 | metadata: 16 | labels: 17 | svc: book 18 | app: service 19 | spec: 20 | containers: 21 | - name: book-service 22 | image: harbor.justin.com/micro-kit/book-service:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 10087 26 | resources: 27 | requests: 28 | memory: 64Mi 29 | cpu: 250m 30 | limits: 31 | memory: 64Mi 32 | cpu: 250m 33 | initContainers: 34 | - command: 35 | - sh 36 | - -c 37 | - until curl -m5 -s consul-ui:80/ui; do echo waiting for config; sleep 5; done; 38 | image: hashicorp/consul:1.10.0 39 | name: consul-ui -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-book-rpc-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: book-rpc-service 5 | labels: 6 | svc: book-rpc 7 | app: service 8 | spec: 9 | replicas: 2 10 | selector: 11 | matchLabels: 12 | svc: book-rpc 13 | app: service 14 | template: 15 | metadata: 16 | labels: 17 | svc: book-rpc 18 | app: service 19 | spec: 20 | containers: 21 | - name: book-rpc-service 22 | image: harbor.justin.com/micro-kit/book-rpc-service:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 10088 26 | resources: 27 | requests: 28 | memory: 64Mi 29 | cpu: 250m 30 | limits: 31 | memory: 64Mi 32 | cpu: 250m 33 | initContainers: 34 | - command: 35 | - sh 36 | - -c 37 | - until curl -m5 -s consul-ui:80/ui; do echo waiting for config; sleep 5; done; 38 | image: hashicorp/consul:1.10.0 39 | name: consul-ui -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-hystrixdashboard-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: hystrix-dashboard 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: hystrix-dashboard 10 | template: 11 | metadata: 12 | labels: 13 | app: hystrix-dashboard 14 | spec: 15 | containers: 16 | - name: hystrix-dashboard 17 | image: mlabouardy/hystrix-dashboard 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 9002 21 | 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: hystrix-dashboard 27 | spec: 28 | ports: 29 | - port: 9002 30 | selector: 31 | app: hystrix-dashboard -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-monitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: book-service 5 | labels: 6 | svc: book 7 | app: service 8 | spec: 9 | ports: 10 | - name: web 11 | port: 10087 12 | selector: 13 | svc: book 14 | app: service 15 | 16 | --- 17 | apiVersion: monitoring.coreos.com/v1 18 | kind: ServiceMonitor 19 | metadata: 20 | name: book-service 21 | labels: 22 | team: backend 23 | spec: 24 | endpoints: 25 | - port: web 26 | # namespaceSelector: 27 | # matchNames: 28 | # - default 29 | selector: 30 | matchLabels: 31 | svc: book 32 | app: service 33 | -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-user-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: user-service 5 | labels: 6 | svc: user 7 | app: service 8 | spec: 9 | replicas: 2 10 | selector: 11 | matchLabels: 12 | svc: user 13 | app: service 14 | template: 15 | metadata: 16 | labels: 17 | svc: user 18 | app: service 19 | spec: 20 | containers: 21 | - name: user-service 22 | image: harbor.justin.com/micro-kit/user-service:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 10086 26 | resources: 27 | requests: 28 | memory: 64Mi 29 | cpu: 250m 30 | limits: 31 | memory: 64Mi 32 | cpu: 250m 33 | initContainers: 34 | - command: 35 | - sh 36 | - -c 37 | - until curl -m5 -s consul-ui:80/ui; do echo waiting for config; sleep 5; done; 38 | image: hashicorp/consul:1.10.0 39 | name: consul-ui -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/k8s/k8s-zipkin-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: zipkin-server 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: zipkin-server 10 | template: 11 | metadata: 12 | labels: 13 | app: zipkin-server 14 | spec: 15 | containers: 16 | - name: zipkin-server 17 | image: openzipkin/zipkin 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 9411 21 | 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: zipkin-server 27 | spec: 28 | ports: 29 | - port: 9411 30 | selector: 31 | app: zipkin-server -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/prometheus/prometheus-grafana.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | prometheus: 5 | image: prom/prometheus 6 | ports: 7 | - 9090:9090 8 | volumes: 9 | - /Users/Justin/workspace_go_execise/go-kit-exercise/micro-kit/micro-kit-prometheus/deploy/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml 10 | grafana: 11 | image: grafana/grafana 12 | ports: 13 | - 3000:3000 14 | environment: 15 | - GF_SECURITY_ADMIN_PASSWORD=123456 16 | volumes: 17 | - /Users/Justin/grafana_db:/var/lib/grafana grafana/grafana 18 | 19 | -------------------------------------------------------------------------------- /micro-kit-k8s/deploy/prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | external_labels: 4 | monitor: 'library-monitor' 5 | 6 | scrape_configs: 7 | - job_name: 'prometheus' 8 | scrape_interval: 5s 9 | static_configs: 10 | - targets: ['192.168.1.11:9090'] 11 | labels: 12 | group: 'local' 13 | 14 | - job_name: 'library' 15 | scrape_interval: 5s 16 | static_configs: 17 | - targets: ['192.168.1.11:10086', '192.168.1.11:10087', '192.168.1.11:10089'] 18 | labels: 19 | group: 'library' 20 | 21 | -------------------------------------------------------------------------------- /micro-kit-k8s/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | github.com/openzipkin/zipkin-go v0.2.5 15 | github.com/prometheus/client_golang v1.11.0 16 | google.golang.org/grpc v1.38.0 17 | google.golang.org/protobuf v1.27.1 18 | gopkg.in/yaml.v2 v2.4.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-apigateway/apigateway.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | mode: debug 4 | name: "apigateway" 5 | 6 | consul: 7 | addr: "http://consul-server:8500" 8 | interval: "10s" 9 | timeout: "1s" 10 | client: 11 | retrymax: 3 12 | retrytimeout: 500 13 | 14 | zipkin: 15 | url: "http://zipkin-server:9411/api/v2/spans" 16 | service_name: "apigateway" 17 | reporter: 18 | timeout: 5 19 | batch_size: 1000 20 | batch_interval: 3 21 | max_backlog: 10000 22 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-apigateway/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "com/justin/micro/kit/library-apigateway/transport" 5 | "com/justin/micro/kit/pkg/configs" 6 | "com/justin/micro/kit/pkg/tracers" 7 | "context" 8 | "flag" 9 | "fmt" 10 | "os" 11 | "os/signal" 12 | "strconv" 13 | "syscall" 14 | 15 | "github.com/go-kit/kit/log" 16 | ) 17 | 18 | var confFile = flag.String("f", "apigateway.yaml", "user config file") 19 | 20 | func main() { 21 | flag.Parse() 22 | 23 | var logger log.Logger 24 | { 25 | logger = log.NewLogfmtLogger(os.Stderr) 26 | logger = log.With(logger, "ts", log.DefaultTimestampUTC) 27 | logger = log.With(logger, "caller", log.DefaultCaller) 28 | } 29 | 30 | err := configs.Init(*confFile) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | ctx := context.Background() 36 | 37 | reporter := tracers.NewZipkinReporter(configs.Conf.ZipkinConfig) 38 | defer reporter.Close() 39 | tracer := tracers.NewZipkinTracer(configs.Conf.ZipkinConfig.ServiceName, reporter) 40 | 41 | ctx = context.WithValue(ctx, "ginMod", configs.Conf.ServerConfig.Mode) 42 | r := transport.NewHttpHandler(ctx, configs.Conf, tracer, logger) 43 | 44 | errChan := make(chan error) 45 | go func() { 46 | errChan <- r.Run(fmt.Sprintf(":%s", strconv.Itoa(configs.Conf.ServerConfig.Port))) 47 | }() 48 | 49 | go func() { 50 | c := make(chan os.Signal, 1) 51 | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) 52 | errChan <- fmt.Errorf("%s", <-c) 53 | }() 54 | fmt.Println(<-errChan) 55 | } 56 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-rpc-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_rpc_service" 35 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | 42 | type ServiceMiddleware func(BookService) BookService 43 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-grpc-service/service/book_service_metrics.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/monitors" 5 | pbbook "com/justin/micro/kit/protos/book" 6 | "context" 7 | "time" 8 | 9 | "github.com/go-kit/kit/metrics" 10 | ) 11 | 12 | func MetricsMiddleware(prometheusParams *monitors.PrometheusParams) ServiceMiddleware { 13 | return func(next BookService) BookService { 14 | return metricsMiddleware{next, prometheusParams.Counter, prometheusParams.Summary} 15 | } 16 | } 17 | 18 | type metricsMiddleware struct { 19 | BookService 20 | requestCount metrics.Counter 21 | requestLatency metrics.Histogram 22 | } 23 | 24 | func (mw metricsMiddleware) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | defer func(begin time.Time) { 26 | lvs := []string{"method", "FindBooksByUserID"} 27 | mw.requestCount.With(lvs...).Add(1) 28 | mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) 29 | }(time.Now()) 30 | return mw.BookService.FindBooksByUserID(ctx, req) 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_service" -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "com/justin/micro/kit/pkg/tracers" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | 10 | "github.com/go-kit/kit/endpoint" 11 | grpctransport "github.com/go-kit/kit/transport/grpc" 12 | gozipkin "github.com/openzipkin/zipkin-go" 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | type BookRPCEndpoints struct { 17 | FindBooksEndpoint endpoint.Endpoint 18 | } 19 | 20 | func MakeFindBooksEndpoint(instance string, tracer *gozipkin.Tracer) endpoint.Endpoint { 21 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 22 | if err != nil { 23 | fmt.Println(err) 24 | return nil 25 | } 26 | findBooksEndpoint := grpctransport.NewClient( 27 | conn, "book.Book", "FindBooksByUserID", 28 | encodeGRPCFindBooksRequest, 29 | decodeGRPCFindBooksResponse, 30 | pbbook.BooksResponse{}, 31 | tracers.MakeGrpcClientOptions(tracer, "grpc-transport-findBooks")..., 32 | ).Endpoint() 33 | return findBooksEndpoint 34 | } 35 | 36 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 37 | userID := r.(uint64) 38 | return &pbbook.BooksByUserIDRequest{ 39 | UserID: userID, 40 | }, nil 41 | } 42 | 43 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 44 | resp := r.(*pbbook.BooksResponse) 45 | return resp.Books, nil 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-k8s/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 30 | 31 | zipkin: 32 | url: "http://zipkin-server:9411/api/v2/spans" 33 | service_name: "user-service" 34 | reporter: 35 | timeout: 5 36 | batch_size: 1000 37 | batch_interval: 3 38 | max_backlog: 10000 39 | 40 | prometheus: 41 | namespace: "library" 42 | subsystem: "user_service" -------------------------------------------------------------------------------- /micro-kit-k8s/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-k8s/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-k8s/pkg/monitors/prometheus.go: -------------------------------------------------------------------------------- 1 | package monitors 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | 6 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" 7 | stdprometheus "github.com/prometheus/client_golang/prometheus" 8 | ) 9 | 10 | type PrometheusParams struct { 11 | Counter *kitprometheus.Counter 12 | Summary *kitprometheus.Summary 13 | Gauge *kitprometheus.Gauge 14 | Histogram *kitprometheus.Histogram 15 | } 16 | 17 | func MakePrometheusParams(conf *configs.PrometheusConfig) *PrometheusParams { 18 | fieldKeys := []string{"method"} 19 | requestCounter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ 20 | Namespace: conf.Namespace, 21 | Subsystem: conf.Subsystem, 22 | Name: "request_count", 23 | Help: "Number of requests received.", 24 | }, fieldKeys) 25 | requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ 26 | Namespace: conf.Namespace, 27 | Subsystem: conf.Subsystem, 28 | Name: "request_latency_microseconds", 29 | Help: "Total duration of requests in microseconds.", 30 | }, fieldKeys) 31 | 32 | return &PrometheusParams{requestCounter, requestLatency, nil, nil} 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-k8s/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-k8s/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-k8s/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-k8s/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-prometheus/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-prometheus/.DS_Store -------------------------------------------------------------------------------- /micro-kit-prometheus/deploy/prometheus/prometheus-grafana.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | prometheus: 5 | image: prom/prometheus 6 | ports: 7 | - 9090:9090 8 | volumes: 9 | - /Users/Justin/workspace_go_execise/go-kit-exercise/micro-kit/micro-kit-prometheus/deploy/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml 10 | grafana: 11 | image: grafana/grafana 12 | ports: 13 | - 3000:3000 14 | environment: 15 | - GF_SECURITY_ADMIN_PASSWORD=123456 16 | volumes: 17 | - /Users/Justin/grafana_db:/var/lib/grafana grafana/grafana 18 | 19 | -------------------------------------------------------------------------------- /micro-kit-prometheus/deploy/prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | external_labels: 4 | monitor: 'library-monitor' 5 | 6 | scrape_configs: 7 | - job_name: 'prometheus' 8 | scrape_interval: 5s 9 | static_configs: 10 | - targets: ['192.168.1.11:9090'] 11 | labels: 12 | group: 'local' 13 | 14 | - job_name: 'library' 15 | scrape_interval: 5s 16 | static_configs: 17 | - targets: ['192.168.1.11:10086', '192.168.1.11:10087', '192.168.1.11:10089'] 18 | labels: 19 | group: 'library' 20 | 21 | -------------------------------------------------------------------------------- /micro-kit-prometheus/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | github.com/openzipkin/zipkin-go v0.2.5 15 | github.com/prometheus/client_golang v1.11.0 16 | google.golang.org/grpc v1.38.0 17 | google.golang.org/protobuf v1.27.1 18 | gopkg.in/yaml.v2 v2.4.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-apigateway/apigateway.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | mode: debug 4 | name: "apigateway" 5 | 6 | consul: 7 | addr: "http://consul-server:8500" 8 | interval: "10s" 9 | timeout: "1s" 10 | client: 11 | retrymax: 3 12 | retrytimeout: 500 13 | 14 | zipkin: 15 | url: "http://zipkin-server:9411/api/v2/spans" 16 | service_name: "apigateway" 17 | reporter: 18 | timeout: 5 19 | batch_size: 1000 20 | batch_interval: 3 21 | max_backlog: 10000 22 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-rpc-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_rpc_service" 35 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | 42 | type ServiceMiddleware func(BookService) BookService 43 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-grpc-service/service/book_service_metrics.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/monitors" 5 | pbbook "com/justin/micro/kit/protos/book" 6 | "context" 7 | "time" 8 | 9 | "github.com/go-kit/kit/metrics" 10 | ) 11 | 12 | func MetricsMiddleware(prometheusParams *monitors.PrometheusParams) ServiceMiddleware { 13 | return func(next BookService) BookService { 14 | return metricsMiddleware{next, prometheusParams.Counter, prometheusParams.Summary} 15 | } 16 | } 17 | 18 | type metricsMiddleware struct { 19 | BookService 20 | requestCount metrics.Counter 21 | requestLatency metrics.Histogram 22 | } 23 | 24 | func (mw metricsMiddleware) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | defer func(begin time.Time) { 26 | lvs := []string{"method", "FindBooksByUserID"} 27 | mw.requestCount.With(lvs...).Add(1) 28 | mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) 29 | }(time.Now()) 30 | return mw.BookService.FindBooksByUserID(ctx, req) 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | prometheus: 33 | namespace: "library" 34 | subsystem: "book_service" -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "com/justin/micro/kit/pkg/tracers" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | 10 | "github.com/go-kit/kit/endpoint" 11 | grpctransport "github.com/go-kit/kit/transport/grpc" 12 | gozipkin "github.com/openzipkin/zipkin-go" 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | type BookRPCEndpoints struct { 17 | FindBooksEndpoint endpoint.Endpoint 18 | } 19 | 20 | func MakeFindBooksEndpoint(instance string, tracer *gozipkin.Tracer) endpoint.Endpoint { 21 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 22 | if err != nil { 23 | fmt.Println(err) 24 | return nil 25 | } 26 | findBooksEndpoint := grpctransport.NewClient( 27 | conn, "book.Book", "FindBooksByUserID", 28 | encodeGRPCFindBooksRequest, 29 | decodeGRPCFindBooksResponse, 30 | pbbook.BooksResponse{}, 31 | tracers.MakeGrpcClientOptions(tracer, "grpc-transport-findBooks")..., 32 | ).Endpoint() 33 | return findBooksEndpoint 34 | } 35 | 36 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 37 | userID := r.(uint64) 38 | return &pbbook.BooksByUserIDRequest{ 39 | UserID: userID, 40 | }, nil 41 | } 42 | 43 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 44 | resp := r.(*pbbook.BooksResponse) 45 | return resp.Books, nil 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-prometheus/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 30 | 31 | zipkin: 32 | url: "http://zipkin-server:9411/api/v2/spans" 33 | service_name: "user-service" 34 | reporter: 35 | timeout: 5 36 | batch_size: 1000 37 | batch_interval: 3 38 | max_backlog: 10000 39 | 40 | prometheus: 41 | namespace: "library" 42 | subsystem: "user_service" -------------------------------------------------------------------------------- /micro-kit-prometheus/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-prometheus/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-prometheus/pkg/monitors/prometheus.go: -------------------------------------------------------------------------------- 1 | package monitors 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | 6 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" 7 | stdprometheus "github.com/prometheus/client_golang/prometheus" 8 | ) 9 | 10 | type PrometheusParams struct { 11 | Counter *kitprometheus.Counter 12 | Summary *kitprometheus.Summary 13 | Gauge *kitprometheus.Gauge 14 | Histogram *kitprometheus.Histogram 15 | } 16 | 17 | func MakePrometheusParams(conf *configs.PrometheusConfig) *PrometheusParams { 18 | fieldKeys := []string{"method"} 19 | requestCounter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ 20 | Namespace: conf.Namespace, 21 | Subsystem: conf.Subsystem, 22 | Name: "request_count", 23 | Help: "Number of requests received.", 24 | }, fieldKeys) 25 | requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ 26 | Namespace: conf.Namespace, 27 | Subsystem: conf.Subsystem, 28 | Name: "request_latency_microseconds", 29 | Help: "Total duration of requests in microseconds.", 30 | }, fieldKeys) 31 | 32 | return &PrometheusParams{requestCounter, requestLatency, nil, nil} 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-prometheus/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-prometheus/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-prometheus/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-prometheus/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-ratelimit/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-ratelimit/.DS_Store -------------------------------------------------------------------------------- /micro-kit-ratelimit/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/gin-gonic/gin v1.7.4 8 | github.com/go-kit/kit v0.11.0 9 | github.com/go-sql-driver/mysql v1.5.0 10 | github.com/jinzhu/gorm v1.9.16 11 | github.com/juju/ratelimit v1.0.1 12 | google.golang.org/grpc v1.38.0 13 | google.golang.org/protobuf v1.27.1 14 | gopkg.in/yaml.v2 v2.4.0 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-grpc-service/transport/book_transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/endpoint" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | 9 | kitrpc "github.com/go-kit/kit/transport/grpc" 10 | ) 11 | 12 | type grpcServer struct { 13 | pbbook.UnimplementedBookServer 14 | findBooksByUserID kitrpc.Handler 15 | } 16 | 17 | func (g grpcServer) FindBooksByUserID(ctx context.Context, r *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 18 | _, res, err := g.findBooksByUserID.ServeGRPC(ctx, r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res.(*pbbook.BooksResponse), nil 23 | } 24 | 25 | func NewBookServer(ctx context.Context, endpoints endpoint.BookEndpoints) pbbook.BookServer { 26 | return &grpcServer{ 27 | findBooksByUserID: kitrpc.NewServer( 28 | endpoints.FindBooksByUserIDEndpoint, 29 | decodeFindBooksByUserIDRequest, 30 | encodeFindBooksByUserIDResponse, 31 | ), 32 | } 33 | } 34 | 35 | func decodeFindBooksByUserIDRequest(ctx context.Context, request interface{}) (interface{}, error) { 36 | req := request.(*pbbook.BooksByUserIDRequest) 37 | return &pbbook.BooksByUserIDRequest{ 38 | UserID: req.UserID, 39 | }, nil 40 | } 41 | 42 | func encodeFindBooksByUserIDResponse(ctx context.Context, response interface{}) (interface{}, error) { 43 | resp := response.(*pbbook.BooksResponse) 44 | return &pbbook.BooksResponse{ 45 | Books: resp.Books, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/pkg/configs/config.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/ghodss/yaml" 8 | ) 9 | 10 | type ServerConfig struct { 11 | Port int `json:"port" yaml:"port"` 12 | Mode string `json:"mode" yaml:"mode"` 13 | Name string `json:"name" yaml:"name"` 14 | } 15 | 16 | type MySQLConfig struct { 17 | Host string `json:"host" yaml:"host"` 18 | Username string `json:"username" yaml:"username"` 19 | Password string `json:"password" yaml:"password"` 20 | Port string `json:"port" yaml:"port"` 21 | Db string `json:"db" yaml:"db"` 22 | Debug bool `json:"debug" yaml:"debug"` 23 | } 24 | 25 | type RatelimitConfig struct { 26 | FillInterval int `json:"fillInterval" yaml:"fillInterval"` 27 | Capacity int `json:"capacity" yaml:"capacity"` 28 | } 29 | 30 | type AppConfig struct { 31 | *ServerConfig `json:"server" yaml:"server"` 32 | *MySQLConfig `json:"mysql" yaml:"mysql"` 33 | *RatelimitConfig `json:"ratelimit" yaml:"ratelimit"` 34 | } 35 | 36 | var Conf = new(AppConfig) 37 | 38 | func Init(file string) error { 39 | yamlData, err := ioutil.ReadFile(file) 40 | if err != nil { 41 | fmt.Println(err) 42 | return err 43 | } 44 | if err = yaml.Unmarshal(yamlData, Conf); err != nil { 45 | return err 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-ratelimit/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-ratelimit/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-user/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-user/.DS_Store -------------------------------------------------------------------------------- /micro-kit-user/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ghodss/yaml v1.0.0 7 | github.com/gin-gonic/gin v1.7.4 8 | github.com/go-kit/kit v0.11.0 9 | github.com/go-sql-driver/mysql v1.5.0 10 | github.com/jinzhu/gorm v1.9.16 11 | gopkg.in/yaml.v2 v2.4.0 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /micro-kit-user/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-user/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-user/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-user/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | -------------------------------------------------------------------------------- /micro-kit-user/pkg/configs/config.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/ghodss/yaml" 8 | ) 9 | 10 | type ServerConfig struct { 11 | Port int `json:"port" yaml:"port"` 12 | Mode string `json:"mode" yaml:"mode"` 13 | Name string `json:"name" yaml:"name"` 14 | } 15 | 16 | type MySQLConfig struct { 17 | Host string `json:"host" yaml:"host"` 18 | Username string `json:"username" yaml:"username"` 19 | Password string `json:"password" yaml:"password"` 20 | Port string `json:"port" yaml:"port"` 21 | Db string `json:"db" yaml:"db"` 22 | Debug bool `json:"debug" yaml:"debug"` 23 | } 24 | 25 | type AppConfig struct { 26 | *ServerConfig `json:"server" yaml:"server"` 27 | *MySQLConfig `json:"mysql" yaml:"mysql"` 28 | } 29 | 30 | var Conf = new(AppConfig) 31 | 32 | func Init(file string) error { 33 | yamlData, err := ioutil.ReadFile(file) 34 | if err != nil { 35 | fmt.Println(err) 36 | return err 37 | } 38 | if err = yaml.Unmarshal(yamlData, Conf); err != nil { 39 | return err 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /micro-kit-user/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-user/pkg/utils/http_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewRouter(mode string) *gin.Engine { 12 | gin.SetMode(mode) 13 | r := gin.New() 14 | r.Use(gin.Recovery()) 15 | return r 16 | } 17 | 18 | func EncodeJsonResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { 19 | w.Header().Set("Content-Type", "application/json;charset=utf-8") 20 | return json.NewEncoder(w).Encode(response) 21 | } 22 | -------------------------------------------------------------------------------- /micro-kit-user/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /micro-kit-zipkin/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin02180218/micro-kit/cf483107fb57e34b0b8dda729642feff89e39e30/micro-kit-zipkin/.DS_Store -------------------------------------------------------------------------------- /micro-kit-zipkin/go.mod: -------------------------------------------------------------------------------- 1 | module com/justin/micro/kit 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/ghodss/yaml v1.0.0 8 | github.com/gin-gonic/gin v1.7.4 9 | github.com/go-kit/kit v0.11.0 10 | github.com/go-sql-driver/mysql v1.5.0 11 | github.com/hashicorp/consul/api v1.8.1 12 | github.com/jinzhu/gorm v1.9.16 13 | github.com/juju/ratelimit v1.0.1 14 | github.com/openzipkin/zipkin-go v0.2.5 15 | google.golang.org/grpc v1.38.0 16 | google.golang.org/protobuf v1.27.1 17 | gopkg.in/yaml.v2 v2.4.0 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-apigateway/apigateway.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | mode: debug 4 | name: "apigateway" 5 | 6 | consul: 7 | addr: "http://consul-server:8500" 8 | interval: "10s" 9 | timeout: "1s" 10 | client: 11 | retrymax: 3 12 | retrytimeout: 500 13 | 14 | zipkin: 15 | url: "http://zipkin-server:9411/api/v2/spans" 16 | service_name: "apigateway" 17 | reporter: 18 | timeout: 5 19 | batch_size: 1000 20 | batch_interval: 3 21 | max_backlog: 10000 22 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-grpc-service/book_rpc.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10088 3 | mode: debug 4 | name: "book-rpc-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-rpc-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | 32 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-grpc-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | FindBooksByUserID(userID uint64) ([]models.Book, error) 10 | } 11 | 12 | type BookDaoImpl struct{} 13 | 14 | func NewBookDaoImpl() BookDao { 15 | return &BookDaoImpl{} 16 | } 17 | 18 | func (b *BookDaoImpl) FindBooksByUserID(userID uint64) ([]models.Book, error) { 19 | books := new([]models.Book) 20 | sql := "select b.* from book b, user_book ub where b.id = ub.book_id and ub.user_id = ?" 21 | err := databases.DB.Raw(sql, userID).Scan(books).Error 22 | if err != nil { 23 | return nil, err 24 | } 25 | return *books, nil 26 | } 27 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-grpc-service/endpoint/book_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/service" 5 | "context" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | ) 10 | 11 | type BookEndpoints struct { 12 | FindBooksByUserIDEndpoint endpoint.Endpoint 13 | } 14 | 15 | func NewFindBooksByUserIDEndpoint(bookService service.BookService) endpoint.Endpoint { 16 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 17 | req := request.(*pbbook.BooksByUserIDRequest) 18 | res, err := bookService.FindBooksByUserID(ctx, req) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return res, nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-grpc-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-grpc-service/service/book_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-grpc-service/dao" 5 | "context" 6 | 7 | pbbook "com/justin/micro/kit/protos/book" 8 | ) 9 | 10 | type BookService interface { 11 | FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) 12 | } 13 | 14 | type BookServiceImpl struct { 15 | bookDao dao.BookDao 16 | } 17 | 18 | func NewBookServiceImpl(bookDao dao.BookDao) BookService { 19 | return &BookServiceImpl{ 20 | bookDao: bookDao, 21 | } 22 | } 23 | 24 | func (b *BookServiceImpl) FindBooksByUserID(ctx context.Context, req *pbbook.BooksByUserIDRequest) (*pbbook.BooksResponse, error) { 25 | books, err := b.bookDao.FindBooksByUserID(req.UserID) 26 | if err != nil { 27 | return &pbbook.BooksResponse{}, err 28 | } 29 | 30 | pbbooks := new([]*pbbook.BookInfo) 31 | for _, book := range books { 32 | *pbbooks = append(*pbbooks, &pbbook.BookInfo{ 33 | Id: book.ID, 34 | Bookname: book.Bookname, 35 | }) 36 | } 37 | return &pbbook.BooksResponse{ 38 | Books: *pbbooks, 39 | }, nil 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-service/book.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10087 3 | mode: debug 4 | name: "book-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: 10s 21 | timeout: 1s 22 | 23 | zipkin: 24 | url: "http://zipkin-server:9411/api/v2/spans" 25 | service_name: "book-service" 26 | reporter: 27 | timeout: 5 28 | batch_size: 1000 29 | batch_interval: 3 30 | max_backlog: 10000 31 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-service/dao/book_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-book-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type BookDao interface { 9 | Save(book *models.Book) error 10 | FindAll() ([]models.Book, error) 11 | FindByName(name string) (*models.Book, error) 12 | BorrowBook(userID, bookID uint64) error 13 | } 14 | 15 | type BookDaoImpl struct{} 16 | 17 | func NewBookDaoImpl() BookDao { 18 | return &BookDaoImpl{} 19 | } 20 | 21 | func (b *BookDaoImpl) Save(book *models.Book) error { 22 | return databases.DB.Create(book).Error 23 | } 24 | 25 | func (b *BookDaoImpl) FindAll() ([]models.Book, error) { 26 | books := new([]models.Book) 27 | err := databases.DB.Find(books).Error 28 | if err != nil { 29 | return nil, err 30 | } 31 | return *books, nil 32 | } 33 | 34 | func (b *BookDaoImpl) FindByName(name string) (*models.Book, error) { 35 | book := &models.Book{} 36 | err := databases.DB.Where("bookname = ?", name).First(book).Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | return book, nil 41 | } 42 | 43 | func (b *BookDaoImpl) BorrowBook(userID, bookID uint64) error { 44 | sql := "INSERT INTO user_book (user_id, book_id) VALUES(?, ?)" 45 | return databases.DB.Exec(sql, userID, bookID).Error 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-service/dto/book_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type BookInfo struct { 4 | ID uint64 `json:"id"` 5 | Bookname string `json:"bookname"` 6 | } 7 | 8 | type BookRequest struct { 9 | Bookname string `form:"bookname" json:"bookname" validate:"required"` 10 | } 11 | 12 | type BorrowBook struct { 13 | UserID uint64 14 | BookID uint64 15 | } 16 | 17 | type BorrowBookRequest struct { 18 | UserID string `form:"userid" json:"userid" validate:"required"` 19 | BookID string `form:"bookid" json:"bookid" validate:"required"` 20 | } 21 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-book-service/models/book.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Book struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Bookname string 10 | } 11 | 12 | func (Book) TableName() string { 13 | return "book" 14 | } 15 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-user-service/dao/user_dao.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "com/justin/micro/kit/library-user-service/models" 5 | "com/justin/micro/kit/pkg/databases" 6 | ) 7 | 8 | type UserDao interface { 9 | SelectByID(id uint64) (*models.User, error) 10 | SelectByEmail(email string) (*models.User, error) 11 | Save(user *models.User) error 12 | } 13 | 14 | type UserDaoImpl struct{} 15 | 16 | func NewUserDaoImpl() UserDao { 17 | return &UserDaoImpl{} 18 | } 19 | 20 | func (u *UserDaoImpl) SelectByID(id uint64) (*models.User, error) { 21 | user := &models.User{} 22 | err := databases.DB.Where("id = ?", id).First(user).Error 23 | if err != nil { 24 | return nil, err 25 | } 26 | return user, nil 27 | } 28 | 29 | func (u *UserDaoImpl) SelectByEmail(email string) (*models.User, error) { 30 | user := &models.User{} 31 | err := databases.DB.Where("email = ?", email).First(user).Error 32 | if err != nil { 33 | return nil, err 34 | } 35 | return user, nil 36 | } 37 | 38 | func (u *UserDaoImpl) Save(user *models.User) error { 39 | return databases.DB.Create(user).Error 40 | } 41 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-user-service/dto/user_dto.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type UserInfo struct { 4 | ID uint64 `json:"id"` 5 | Username string `json:"username"` 6 | Email string `json:"email"` 7 | } 8 | 9 | type RegisterUser struct { 10 | Username string 11 | Password string 12 | Email string 13 | } 14 | 15 | type RegisterRequest struct { 16 | Username string `form:"username" json:"username" validate:"required"` 17 | Password string `form:"password" json:"password" validate:"required"` 18 | Email string `form:"email" json:"email" validate:"required,email"` 19 | } 20 | 21 | type FindByIDRequest struct { 22 | ID string `form:"id" json:"id" validate:"required"` 23 | } 24 | 25 | type FindByEmailRequest struct { 26 | Email string `form:"email" json:"email" validate:"required"` 27 | } 28 | 29 | type FindBooksByUserIDRequest struct { 30 | UserID string `form:"userid" json:"userid" validate:"required"` 31 | } 32 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-user-service/endpoint/book_rpc_endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "com/justin/micro/kit/pkg/tracers" 8 | pbbook "com/justin/micro/kit/protos/book" 9 | 10 | "github.com/go-kit/kit/endpoint" 11 | grpctransport "github.com/go-kit/kit/transport/grpc" 12 | gozipkin "github.com/openzipkin/zipkin-go" 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | type BookRPCEndpoints struct { 17 | FindBooksEndpoint endpoint.Endpoint 18 | } 19 | 20 | func MakeFindBooksEndpoint(instance string, tracer *gozipkin.Tracer) endpoint.Endpoint { 21 | conn, err := grpc.Dial(instance, grpc.WithInsecure()) 22 | if err != nil { 23 | fmt.Println(err) 24 | return nil 25 | } 26 | findBooksEndpoint := grpctransport.NewClient( 27 | conn, "book.Book", "FindBooksByUserID", 28 | encodeGRPCFindBooksRequest, 29 | decodeGRPCFindBooksResponse, 30 | pbbook.BooksResponse{}, 31 | tracers.MakeGrpcClientOptions(tracer, "grpc-transport-findBooks")..., 32 | ).Endpoint() 33 | return findBooksEndpoint 34 | } 35 | 36 | func encodeGRPCFindBooksRequest(_ context.Context, r interface{}) (interface{}, error) { 37 | userID := r.(uint64) 38 | return &pbbook.BooksByUserIDRequest{ 39 | UserID: userID, 40 | }, nil 41 | } 42 | 43 | func decodeGRPCFindBooksResponse(_ context.Context, r interface{}) (interface{}, error) { 44 | resp := r.(*pbbook.BooksResponse) 45 | return resp.Books, nil 46 | } 47 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-user-service/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type User struct { 6 | ID uint64 `gorm:"primary_key" json:"id" form:"id"` 7 | CreatedAt time.Time `form:"created_at" json:"created_at"` 8 | UpdatedAt time.Time `form:"updated_at" json:"updated_at"` 9 | Username string 10 | Password string 11 | Email string 12 | } 13 | 14 | func (User) TableName() string { 15 | return "user" 16 | } 17 | -------------------------------------------------------------------------------- /micro-kit-zipkin/library-user-service/user.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10086 3 | mode: debug 4 | name: "user-service" 5 | 6 | mysql: 7 | host: "localhost" 8 | port: 3306 9 | db: "library" 10 | username: "root" 11 | password: "123456" 12 | debug: true 13 | 14 | ratelimit: 15 | fillInterval: 1 16 | capacity: 3 17 | 18 | consul: 19 | addr: "http://consul-server:8500" 20 | interval: "10s" 21 | timeout: "1s" 22 | 23 | grpc: 24 | retrymax: 3 25 | retrytimeout: 500 26 | name: "book-rpc-service" 27 | 28 | hystrix: 29 | stream_port: 9000 30 | 31 | zipkin: 32 | url: "http://zipkin-server:9411/api/v2/spans" 33 | service_name: "user-service" 34 | reporter: 35 | timeout: 5 36 | batch_size: 1000 37 | batch_interval: 3 38 | max_backlog: 10000 -------------------------------------------------------------------------------- /micro-kit-zipkin/pkg/circuitbreakers/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreakers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/afex/hystrix-go/hystrix" 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | func Hystrix(commandName, fallbackMsg string) endpoint.Middleware { 12 | return func(next endpoint.Endpoint) endpoint.Endpoint { 13 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 14 | err = hystrix.Do( 15 | commandName, 16 | func() error { 17 | response, err = next(ctx, request) 18 | return err 19 | }, 20 | func(err error) error { 21 | fmt.Println("fallbackErrorDesc", err.Error()) 22 | response = struct { 23 | Fallback string `json:"fallback"` 24 | }{fallbackMsg} 25 | return nil 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-kit-zipkin/pkg/databases/mysql.go: -------------------------------------------------------------------------------- 1 | package databases 2 | 3 | import ( 4 | "com/justin/micro/kit/pkg/configs" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | "github.com/jinzhu/gorm" 11 | ) 12 | 13 | var DB *gorm.DB 14 | 15 | func InitMySql(cfg *configs.MySQLConfig) (err error) { 16 | connUrl := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", 17 | cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.Db) 18 | DB, err = gorm.Open("mysql", connUrl) 19 | if err != nil { 20 | log.Println(err) 21 | return 22 | } 23 | 24 | err = DB.DB().Ping() 25 | if err != nil { 26 | log.Println(err) 27 | return 28 | } 29 | 30 | if cfg.Debug { 31 | DB = DB.Debug() 32 | } 33 | DB.DB().SetConnMaxLifetime(time.Minute * 10) 34 | DB.SingularTable(true) 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /micro-kit-zipkin/pkg/ratelimits/ratelimit.go: -------------------------------------------------------------------------------- 1 | package ratelimits 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/go-kit/kit/endpoint" 8 | "github.com/juju/ratelimit" 9 | ) 10 | 11 | var ErrLimitExceed = errors.New(" Rate Limit Exceed ") 12 | 13 | func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware { 14 | return func(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 16 | if tb.TakeAvailable(1) == 0 { 17 | return nil, ErrLimitExceed 18 | } 19 | return next(ctx, request) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /micro-kit-zipkin/pkg/utils/net_util.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func LocalIP() string { 9 | netInterfaces, err := net.Interfaces() 10 | if err != nil { 11 | fmt.Println("net.Interfaces failed, err:", err.Error()) 12 | return "" 13 | } 14 | 15 | for i := 0; i < len(netInterfaces); i++ { 16 | if (netInterfaces[i].Flags & net.FlagUp) != 0 { 17 | addrs, _ := netInterfaces[i].Addrs() 18 | 19 | for _, address := range addrs { 20 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 21 | if ipnet.IP.To4() != nil { 22 | return ipnet.IP.String() 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /micro-kit-zipkin/protos/book/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package book; 4 | 5 | option go_package = "/book"; 6 | 7 | message BookInfo { 8 | uint64 id = 1; 9 | string bookname = 2; 10 | } 11 | 12 | message BooksByUserIDRequest { 13 | uint64 userID = 1; 14 | } 15 | 16 | message BooksResponse { 17 | repeated BookInfo books = 1; 18 | } 19 | 20 | service Book { 21 | rpc FindBooksByUserID (BooksByUserIDRequest) returns (BooksResponse) {} 22 | } -------------------------------------------------------------------------------- /micro-kit-zipkin/sql/library.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 | `username` varchar(255) DEFAULT '', 4 | `password` varchar(255) DEFAULT '', 5 | `email` varchar(255) DEFAULT '', 6 | `created_at` datetime DEFAULT NULL, 7 | `updated_at` datetime DEFAULT NULL, 8 | PRIMARY KEY (`id`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 | 11 | 12 | CREATE TABLE `book` ( 13 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 14 | `bookname` varchar(255) DEFAULT '', 15 | `created_at` datetime DEFAULT NULL, 16 | `updated_at` datetime DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 19 | 20 | 21 | CREATE TABLE `user_book` ( 22 | `user_id` bigint(20) NOT NULL, 23 | `book_id` bigint(20) NOT NULL, 24 | PRIMARY KEY (`user_id`,`book_id`) 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --------------------------------------------------------------------------------