package main import ( "context" "fmt" "github.com/afex/hystrix-go/hystrix" consul "github.com/asim/go-micro/plugins/registry/consul/v4" "github.com/dtm-labs/dtm/client/dtmcli" "github.com/go-micro/plugins/v4/wrapper/select/roundrobin" opentracing2 "github.com/go-micro/plugins/v4/wrapper/trace/opentracing" "github.com/lithammer/shortuuid/v3" "github.com/opentracing/opentracing-go" "go-micro.dev/v4/client" "go-micro.dev/v4/web" "strconv" "strings" //"goproduct/common" common "git.mashibing.com/msb_47094/shopping-comm" "log" "net" "net/http" "trade-order/proto" "github.com/gin-gonic/gin" "go-micro.dev/v4" "go-micro.dev/v4/registry" ) // 获取远程服务的客户端 func main() { const ( //DTM 服务地址 DtmServer = "http://192.168.100.131:36789/api/dtmsvr" QSBusi = "http://192.168.1.135:6669" //注意 ) //var CartId int32 = 1 //var Number int32 = 1 resp := &proto.AddTradeOrderResp{} router := gin.Default() //注册到consul consulReg := consul.NewRegistry(func(options *registry.Options) { options.Addrs = []string{"192.168.100.131:8500"} }) //初始化链路追踪的jaeper t, io, err := common.NewTracer("shop-cart-client", "192.168.100.131:6831") if err != nil { log.Println(err) } defer io.Close() opentracing.SetGlobalTracer(t) //熔断器 hystrixStreamHandler := hystrix.NewStreamHandler() hystrixStreamHandler.Start() go func() { err := http.ListenAndServe(net.JoinHostPort("192.168.100.1", "9097"), hystrixStreamHandler) if err != nil { log.Panic(err) } }() rpcServer := micro.NewService( //micro.Name("shop-product-client"), micro.Registry(consulReg), //服务发现 micro.WrapClient(opentracing2.NewClientWrapper(opentracing.GlobalTracer())), //加入熔断器 micro.WrapClient(NewClientHystrixWrapper()), //负载均衡 micro.WrapClient(roundrobin.NewClientWrapper()), ) //AddCartClient := proto.NewAddCartService("shop-cart", rpcServer.Client()) UpdateCartClient := proto.NewUpdateCartService("shop-cart", rpcServer.Client()) //ShowProductDetailClient := proto.NewShowProductDetailService("shop-product", rpcServer.Client()) //ShowDetailSkuClient := proto.NewShowDetailSkuService("shop-product", rpcServer.Client()) GetUserTokenClient := proto.NewGetUserTokenService("shop-user", rpcServer.Client()) //UpdateSkuClient := proto.NewUpdateSkuService("shop-product", rpcServer.Client()) AddTraderClient := proto.NewAddTradeOrderService("trade-order", rpcServer.Client()) UpdateTraderClient := proto.NewUpdateTradeOrderService("trade-order", rpcServer.Client()) //开始拆分 DTM服务 router.POST("/updateCart", func(c *gin.Context) { req := &proto.UpdateCartReq{} if err := c.BindJSON(req); err != nil { log.Fatalln(err) } req.IsDeleted = true _, err := UpdateCartClient.UpdateCart(context.TODO(), req) if err != nil { log.Println("/updateCart err ", err) c.JSON(http.StatusOK, gin.H{"dtm_reslut": "FAILURE", "Message": "删除购物车失败!"}) return } c.JSON(http.StatusOK, gin.H{"updateCart": "SUCCESS", "Message": "删除购物车成功!"}) }) router.POST("/updateCart-compensate", func(c *gin.Context) { req := &proto.UpdateCartReq{} if err := c.BindJSON(req); err != nil { log.Fatalln(err) } req.IsDeleted = false _, err := UpdateCartClient.UpdateCart(context.TODO(), req) if err != nil { log.Println("/updateCart err ", err) c.JSON(http.StatusOK, gin.H{"dtm_reslut": "FAILURE", "Message": "回滚购物车失败!"}) return } c.JSON(http.StatusOK, gin.H{"updateCart-compensate": "SUCCESS", "Message": "回滚购物车成功!"}) }) router.POST("/addTrade", func(c *gin.Context) { req := &proto.AddTradeOrderReq{} if err := c.BindJSON(req); err != nil { log.Fatalln(err) } _, err := AddTraderClient.AddTradeOrder(context.TODO(), req) if err != nil { log.Println("/addTrade err ", err) c.JSON(http.StatusOK, gin.H{"dtm_reslut": "FAILURE", "Message": "新增订单失败!"}) return } c.JSON(http.StatusOK, gin.H{"addTrade": "SUCCESS", "Message": "新增订单成功!"}) }) router.POST("/addTrade-compensate", func(c *gin.Context) { req := &proto.AddTradeOrderReq{} if err := c.BindJSON(req); err != nil { log.Fatalln(err) } req.TradeOrder.IsDeleted = true _, err := UpdateTraderClient.UpdateTradeOrder(context.TODO(), req) if err != nil { log.Println("/addTrade err ", err) c.JSON(http.StatusOK, gin.H{"dtm_reslut": "FAILURE", "Message": "回滚订单失败!"}) return } c.JSON(http.StatusOK, gin.H{"addTrade-compensate": "SUCCESS", "Message": "回滚订单成功!"}) }) //新增订单API router.GET("/cartAdvanceOrder", func(c *gin.Context) { //开始检验登录 uuid := c.Request.Header["Uuid"][0] cc := common.GetInput(uuid) out := common.SQ(cc) sum := 0 for o := range out { sum += o } //Token校验 //拼接请求信息 tokenReq := &proto.TokenReq{ Uuid: uuid, } //响应 tokenResp, err := GetUserTokenClient.GetUserToken(context.TODO(), tokenReq) if err != nil || tokenResp.IsLogin == false { log.Println("GetUserToken err : ", err) common.RespFail(c.Writer, tokenResp, "未登录!") return } //拼接请求信息 log.Println("GetUserToken success : ", tokenResp) //结束检验登录 //开始订单插入 tempStr := c.Request.FormValue("cartIds") // 12,355,666 cartIds := SplitToInt32List(tempStr, ",") isVirtual, _ := strconv.ParseBool(c.Request.FormValue("isVirtual")) recipientAddressId, _ := strconv.Atoi(c.Request.FormValue("recipientAddressId")) //构建tradeOrder tradeOrder := &proto.TradeOrder{} tradeOrder.UserId = int32(sum) tradeOrder.CreateUser = int32(sum) tradeOrder.OrderStatus = 1 req := &proto.AddTradeOrderReq{ CartIds: cartIds, IsVirtual: isVirtual, RecipientAddressId: int32(recipientAddressId), TradeOrder: tradeOrder, } updateCartReq := &proto.UpdateCartReq{ Id: cartIds[0], } //全局事务 gid := shortuuid.New() saga := dtmcli.NewSaga(DtmServer, gid). Add(QSBusi+"/updateCart", QSBusi+"/updateCart-compensate", updateCartReq). Add(QSBusi+"/addTrade", QSBusi+"/addTrade-compensate", req) err = saga.Submit() if err != nil { log.Println("saga submit err :", err) common.RespFail(c.Writer, resp, "添加失败") } log.Println(" /saga submit submit :", gid) ////writer data message row total field common.RespOK(c.Writer, resp, "请求成功") }) //router.POST("/addCart-compensate", func(c *gin.Context) { // req := &proto.AddCartReq{} // if err := c.BindJSON(req); err != nil { // log.Fatalln(err) // } // req.Id = CartId // resp, err = UpdateCartClient.UpdateCart(context.TODO(), req) // CartId = resp.ID // if err != nil { // log.Println("/addCart-compensate err ", err) // c.JSON(http.StatusOK, gin.H{"dtm_reslut": "FAILURE", "Message": "删除购物车失败!"}) // return // } // c.JSON(http.StatusOK, gin.H{"addCart-compensate": "SUCCESS", "Message": "删除购物车成功!"}) //}) // //router.GET("/addShoppingCart", func(c *gin.Context) { // number, _ := strconv.Atoi(c.Request.FormValue("number")) // productId, _ := strconv.Atoi(c.Request.FormValue("productId")) // productSkuId, _ := strconv.Atoi(c.Request.FormValue("productSkuId")) // uuid := c.Request.Header["Uuid"][0] // cc := common.GetInput(uuid) // out := common.SQ(cc) // sum := 0 // for o := range out { // sum += o // } // //Token校验 // //拼接请求信息 // tokenReq := &proto.TokenReq{ // Uuid: uuid, // } // //响应 // tokenResp, err := GetUserTokenClient.GetUserToken(context.TODO(), tokenReq) // //拼接请求信息 // respErr := &proto.AddCartResp{} // if err != nil || tokenResp.IsLogin == false { // log.Println("GetUserToken err : ", err) // common.RespFail(c.Writer, respErr, "未登录!") // return // } // log.Println("GetUserToken success : ", tokenResp) // // //拼接请求信息 // req := &proto.AddCartReq{ // Number: int32(number), // ProductId: int32(productId), // ProductSkuId: int32(productSkuId), // UserId: int32(sum), // } // resp := &proto.AddCartResp{} // //商品详情 // reqDetail := &proto.ProductDetailReq{ // Id: int32(productId), // } // respDetail, err := ShowProductDetailClient.ShowProductDetail(context.TODO(), reqDetail) // if err != nil { // log.Println("ShowProductDetail err : ", err) // common.RespFail(c.Writer, respErr, "查询商品详情失败!") // return // } // if respDetail != nil { // req.ProductName = respDetail.ProductDetail[0].Name // req.ProductMainPicture = respDetail.ProductDetail[0].MainPicture // } // // //log.Println(" /ShowProductDetail resp :", respDetail) // //SKU详情 // reqDetail.Id = req.ProductSkuId // respSkuDetail, err := ShowDetailSkuClient.ShowDetailSku(context.TODO(), reqDetail) // //log.Println(" /ShowDetailSku resp :", respSkuDetail) // //添加购物车 远程调用服务 // //log.Println(" /AddCart req :", req) // // if respSkuDetail.ProductSku[0].Stock < req.Number { // common.RespFail(c.Writer, &proto.AddCartResp{}, "库存不足,添加失败") // return // } // sku := respSkuDetail.ProductSku[0] // sku.Stock -= req.Number // Number = req.Number // // updateSkuReq := &proto.UpdateSkuReq{ // ProductSku: sku, // } // resp.ProductSkuSimple = respSkuDetail.ProductSku[0] // resp.ProductSimple = respDetail.ProductDetail[0] // // //全局事务 // gid := shortuuid.New() // saga := dtmcli.NewSaga(DtmServer, gid). // Add(QSBusi+"/updateSku", QSBusi+"/updateSku-compensate", updateSkuReq). // Add(QSBusi+"/addCart", QSBusi+"/addCart-compensate", req) // err = saga.Submit() // if err != nil { // log.Println("saga submit err :", err) // common.RespFail(c.Writer, resp, "添加失败") // } // log.Println(" /saga submit submit :", gid) // ////writer data message row total field // common.RespOK(c.Writer, resp, "请求成功") //}) service := web.NewService( web.Address(":6669"), web.Name("trade-order-client"), web.Registry(consulReg), web.Handler(router), ) //启动服务 service.Run() } type clientWrapper struct { client.Client } func (c clientWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { return hystrix.Do(req.Service()+"."+req.Endpoint(), func() error { //正常执行 fmt.Println("call success ", req.Service()+"."+req.Endpoint()) return c.Client.Call(ctx, req, resp, opts...) }, func(err error) error { fmt.Println("call err :", err) return err }) } // 格式化页面传入的cartIds func SplitToInt32List(str string, sep string) (int32List []int32) { tempStr := strings.Split(str, sep) if len(tempStr) > 0 { for _, item := range tempStr { if item == "" { continue } val, err := strconv.ParseInt(item, 10, 32) if err != nil { continue } int32List = append(int32List, int32(val)) } } return int32List } func NewClientHystrixWrapper() client.Wrapper { return func(i client.Client) client.Client { return &clientWrapper{i} } }