demo-1
This commit is contained in:
parent
560a026e02
commit
39b2ef4c89
|
|
@ -15,3 +15,11 @@
|
|||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
demo1
|
||||
*.exe
|
||||
logs/
|
||||
go.sum
|
||||
.DS_Store
|
||||
.vscode/
|
||||
resource/
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
var (
|
||||
_client *consulapi.Client
|
||||
conf *Config
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
// Init 初始化consul连接
|
||||
func Init(config *Config) error {
|
||||
if config == nil {
|
||||
config = &Config{
|
||||
Address: "127.0.0.1:8500",
|
||||
}
|
||||
}
|
||||
conf = config
|
||||
if conf.Address == "" {
|
||||
conf.Address = "127.0.0.1:8500"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func New() (*consulapi.Client, error) {
|
||||
if _client != nil {
|
||||
return _client, nil
|
||||
}
|
||||
|
||||
// 创建连接consul服务配置
|
||||
config := consulapi.DefaultConfig()
|
||||
config.Address = conf.Address
|
||||
client, err := consulapi.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_client = client
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// RegisterAPI 注册api服务到consul
|
||||
func RegisterAPI(name string, addr string, port int, tags ...string) error {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if client == nil {
|
||||
return errors.New("consul 实例空")
|
||||
}
|
||||
|
||||
// 创建注册到consul的服务到
|
||||
registration := new(consulapi.AgentServiceRegistration)
|
||||
registration.ID = fmt.Sprintf("%s-%s:%d", name, addr, port)
|
||||
registration.Name = name
|
||||
registration.Port = port
|
||||
registration.Tags = tags
|
||||
registration.Address = addr
|
||||
|
||||
// 增加consul健康检查回调函数
|
||||
check := new(consulapi.AgentServiceCheck)
|
||||
check.HTTP = fmt.Sprintf("http://%s:%d/health/check", registration.Address, registration.Port)
|
||||
check.Timeout = "5s"
|
||||
check.Interval = "5s"
|
||||
check.DeregisterCriticalServiceAfter = "30s" // 故障检查失败30s后 consul自动将注册服务删除
|
||||
registration.Check = check
|
||||
|
||||
// 注册服务到consul
|
||||
if err := client.Agent().ServiceRegister(registration); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeRegister 取消consul注册的服务
|
||||
func DeRegister(name string, addr string, port int) error {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if client == nil {
|
||||
return errors.New("consul 实例空")
|
||||
}
|
||||
client.Agent().ServiceDeregister(fmt.Sprintf("%s-%s:%d", name, addr, port))
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindNode 查找节点
|
||||
func FindNode(servicename, tag string) (*consulapi.AgentService, error) {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if client == nil {
|
||||
return nil, errors.New("consul 实例空")
|
||||
}
|
||||
services, _, err := client.Health().Service(servicename, tag, true, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := len(services)
|
||||
if l == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if l == 1 {
|
||||
return services[0].Service, nil
|
||||
}
|
||||
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return services[r.Intn(l)%l].Service, nil
|
||||
}
|
||||
|
||||
// CheckHeath 健康检查
|
||||
func CheckHeath(serviceid string) error {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if client == nil {
|
||||
return errors.New("consul 实例空")
|
||||
}
|
||||
// 健康检查
|
||||
// a, b, _ := client.Agent().AgentHealthServiceByID(serviceid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// KVPut test
|
||||
func KVPut(key string, values *[]byte, flags uint64) (*consulapi.WriteMeta, error) {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if client == nil {
|
||||
return nil, errors.New("consul 实例空")
|
||||
}
|
||||
|
||||
return client.KV().Put(&consulapi.KVPair{Key: key, Flags: flags, Value: *values}, nil)
|
||||
}
|
||||
|
||||
// KVGet 获取值
|
||||
func KVGet(key string, flags uint64) (*[]byte, error) {
|
||||
client, err := New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if client == nil {
|
||||
return nil, errors.New("consul 实例空")
|
||||
}
|
||||
|
||||
// KV get值
|
||||
data, _, _ := client.KV().Get(key, nil)
|
||||
if data != nil {
|
||||
return &data.Value, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package gin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"myschools.me/suguo/snippet/redis"
|
||||
)
|
||||
|
||||
//从redis中认证用户
|
||||
func AuthUser() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := c.GetHeader("Authorization")
|
||||
claims := cacheGet(&token)
|
||||
if claims == nil {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Set("user", claims)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
//从redis中获取用户信息,最佳实践经验建议把此代码放service层
|
||||
func cacheGet(token *string) interface{} {
|
||||
var user interface{}
|
||||
b, err := redis.GetBytes(token)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := json.Unmarshal(*b, &user); err != nil {
|
||||
return nil
|
||||
}
|
||||
return &user
|
||||
}
|
||||
|
||||
// gin拦截,基于微服务的拦截
|
||||
// func AuthUserBS() gin.HandlerFunc {
|
||||
// return func(c *gin.Context) {
|
||||
// token := c.GetHeader("Authorization")
|
||||
// claims := userAuthWithGrpc(&token)
|
||||
// if claims == nil {
|
||||
// yy.RespUnauth(c, "token无效或过期,请重新登录", nil, nil)
|
||||
// c.Abort()
|
||||
// }
|
||||
// c.Set("user", claims)
|
||||
// c.Next()
|
||||
// }
|
||||
// }
|
||||
|
||||
// func userAuthWithGrpc(token *string) *yy.UserClaims {
|
||||
// srv, err := consul.FindService("oauth", "v1")
|
||||
// if err != nil {
|
||||
// logrus.WithFields(logrus.Fields{
|
||||
// "func": "userAuthWithGrpc",
|
||||
// }).Errorf("consul.FindServer: %s", err.Error())
|
||||
// return nil
|
||||
// }
|
||||
// defer srv.Close()
|
||||
// client := pb.NewCertificationClient(srv)
|
||||
// resp, err := client.Auth(context.Background(), &pb.CertificationAuthRequest{
|
||||
// Token: *token,
|
||||
// })
|
||||
// if err != nil {
|
||||
// logrus.WithFields(logrus.Fields{
|
||||
// "func": "userAuthWithGrpc",
|
||||
// }).Errorf("client.Auth: %s", err.Error())
|
||||
// return nil
|
||||
// }
|
||||
// if resp.Result == "ok" {
|
||||
// r := &yy.UserClaims{}
|
||||
// if err := json.Unmarshal(resp.Data.Value, r); err != nil {
|
||||
// logrus.WithFields(logrus.Fields{
|
||||
// "func": "userAuthWithGrpc",
|
||||
// }).Errorf("json.Unmarshal: %s", err.Error())
|
||||
// return nil
|
||||
// }
|
||||
// return r
|
||||
// }
|
||||
// logrus.WithFields(logrus.Fields{
|
||||
// "func": "userAuthWithGrpc",
|
||||
// }).Warnln("nil")
|
||||
// return nil
|
||||
// }
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package gin
|
||||
|
||||
// GIN 配置
|
||||
type Config struct {
|
||||
RootPath string
|
||||
Addr string
|
||||
Port int
|
||||
Ssl bool
|
||||
SslPem string
|
||||
SslKey string
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package gin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/unrolled/secure"
|
||||
)
|
||||
|
||||
func Service(conf *Config) *Config {
|
||||
if conf == nil {
|
||||
conf = &Config{
|
||||
RootPath: "/",
|
||||
Addr: "0.0.0.0",
|
||||
Port: 8080,
|
||||
Ssl: false,
|
||||
SslPem: "server.pem",
|
||||
SslKey: "server.key",
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
router := gin.New()
|
||||
routerSetup(router, &conf.RootPath)
|
||||
|
||||
if conf.Ssl {
|
||||
router.Use(tlsHandler(conf))
|
||||
}
|
||||
|
||||
s := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", conf.Addr, conf.Port),
|
||||
Handler: router,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
log.Printf("start service on %s", fmt.Sprintf("%s:%d", conf.Addr, conf.Port))
|
||||
|
||||
if conf.Ssl {
|
||||
log.Fatal(s.ListenAndServeTLS(conf.SslPem, conf.SslKey))
|
||||
} else {
|
||||
log.Fatal(s.ListenAndServe())
|
||||
}
|
||||
}()
|
||||
return conf
|
||||
}
|
||||
|
||||
func tlsHandler(conf *Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
secureMiddleware := secure.New(secure.Options{
|
||||
SSLRedirect: true,
|
||||
SSLHost: ":" + strconv.Itoa(conf.Port),
|
||||
})
|
||||
err := secureMiddleware.Process(c.Writer, c.Request)
|
||||
|
||||
// If there was an error, do not continue.
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package gin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"myschools.me/campus/demo-1/handler"
|
||||
)
|
||||
|
||||
// 路由配置
|
||||
func routerSetup(router *gin.Engine, rootpath *string) {
|
||||
router.Use(gin.Recovery())
|
||||
router.GET(`/health/check`, handler.HealthCheck)
|
||||
|
||||
r := router.Group(fmt.Sprintf("/%s", *rootpath))
|
||||
{
|
||||
r.POST(`/register`)
|
||||
r.GET(`/accountcheck/:accname`)
|
||||
r.POST(`/login`)
|
||||
r.POST(`/forgot`)
|
||||
}
|
||||
|
||||
ug := router.Group(`/user`)
|
||||
{
|
||||
ug.GET(`/choose/:orgid`)
|
||||
ug.GET(`/detail`)
|
||||
ug.POST(`/update`)
|
||||
}
|
||||
hell := router.Group("token")
|
||||
{
|
||||
hell.GET("verify", handler.TokenVerify)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
module myschools.me/campus/demo-1
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.9.0
|
||||
github.com/hashicorp/consul/api v1.20.0
|
||||
github.com/unrolled/secure v1.13.0
|
||||
myschools.me/campus/campus-core v0.1.68
|
||||
myschools.me/suguo/snippet v1.0.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
|
||||
github.com/bytedance/sonic v1.8.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/fatih/color v1.9.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/gomodule/redigo v1.8.9 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
|
||||
github.com/hashicorp/go-hclog v0.12.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/serf v0.10.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/gorm v1.24.3 // indirect
|
||||
)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"myschools.me/campus/campus-core/campus"
|
||||
)
|
||||
|
||||
func HealthCheck(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
||||
func TokenVerify(c *gin.Context) {
|
||||
|
||||
reqid := campus.NewRequestID(nil)
|
||||
token := c.GetHeader("Authorization")
|
||||
if token != "112233" {
|
||||
campus.RespBadRequest(c, "token err", errors.New("token err"), &reqid)
|
||||
} else {
|
||||
campus.RespSuccess(c, "helo_word", token+"helo_word", &reqid)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"myschools.me/campus/campus-core/exceptionless"
|
||||
"myschools.me/campus/demo-1/consul"
|
||||
"myschools.me/campus/demo-1/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 日志初始化
|
||||
// exceptionless.Init(&exceptionless.Config{
|
||||
// ApiKey: os.Getenv("EXCEPTIONLESS_KEY"),
|
||||
// ServerURL: os.Getenv("EXCEPTIONLESS_URL"),
|
||||
// UpdateSettingsWhenIdleInterval: 0,
|
||||
// })
|
||||
|
||||
//gin初始化,基于docker部署,不再需要调整默认值(80)
|
||||
|
||||
consul.Init(&consul.Config{
|
||||
Address: "192.168.0.214:8500",
|
||||
})
|
||||
|
||||
gin.Service(nil)
|
||||
|
||||
if err := consul.RegisterAPI("demo1", "192.168.0.214", 8080, ""); err != nil {
|
||||
fmt.Println("注册失败", err.Error())
|
||||
}
|
||||
|
||||
// exceptionless.SubmitLog(fmt.Sprintf("campus-srv[%s:%d%s] service is running...", conf.Addr, conf.Port, conf.RootPath), "info")
|
||||
// 服务停止相应
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
<-c
|
||||
_, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
exceptionless.SubmitLog("campus-srv service shutting down", "info")
|
||||
os.Exit(0)
|
||||
}
|
||||
Loading…
Reference in New Issue