| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 | package serviceimport (	"context"	"encoding/json"	"errors"	"fmt"	"github.com/afex/hystrix-go/hystrix"	"github.com/longjoy/micro-go-course/section28/goods/common"	"github.com/longjoy/micro-go-course/section28/goods/pkg/discovery"	"github.com/longjoy/micro-go-course/section28/goods/pkg/loadbalancer"	"go.etcd.io/etcd/clientv3"	"io/ioutil"	"log"	"net/http"	"net/url"	"strconv"	"time")type GoodsDetailVO struct {	Id       string	Name     string	Comments common.CommentListVO}type Service interface {	GetGoodsDetail(ctx context.Context, id string) (GoodsDetailVO, error)	HealthCheck() string}func NewGoodsServiceImpl(discoveryClient *discovery.DiscoveryClient, loadbalancer loadbalancer.LoadBalancer) Service {	return &GoodsDetailServiceImpl{		discoveryClient: discoveryClient,		loadbalancer:    loadbalancer,	}}type GoodsDetailServiceImpl struct {	discoveryClient    *discovery.DiscoveryClient	loadbalancer       loadbalancer.LoadBalancer	callCommentService int}func (service *GoodsDetailServiceImpl) GetGoodsDetail(ctx context.Context, id string) (GoodsDetailVO, error) {	detail := GoodsDetailVO{Id: id, Name: "Name"}	commentResult, _ := service.GetGoodsComments(ctx, id)	detail.Comments = commentResult.Detail	return detail, nil}var ErrNotServiceInstances = errors.New("instances are not existed")var ErrLoadBalancer = errors.New("loadbalancer select instance error")func (service *GoodsDetailServiceImpl) DiscoveryService(ctx context.Context, serviceName string) ([]*discovery.InstanceInfo, error) {	instances, err := service.discoveryClient.DiscoverServices(ctx, serviceName)	if err != nil {		log.Printf("get service info err: %s", err)	}	if instances == nil || len(instances) == 0 {		return nil, ErrNotServiceInstances	}	return instances, nil}func (service *GoodsDetailServiceImpl) GetGoodsComments(ctx context.Context, id string) (common.CommentResult, error) {	var result common.CommentResult	serviceName := "comment"	instances, err := service.discoveryClient.DiscoverServices(ctx, serviceName)	if err != nil {		log.Printf("get service info err: %s", err)	}	if instances == nil || len(instances) == 0 {		log.Printf("no instance")		return result, ErrNotServiceInstances	}	selectedInstance, err2 := service.loadbalancer.SelectService(instances)	log.Print("select instance info :" + selectedInstance.Address + ":" + strconv.Itoa(selectedInstance.Port))	if err2 != nil {		log.Printf("loadbalancer get selected instance  err: %s", err2)		return result, ErrLoadBalancer	}	call_err := hystrix.Do(serviceName, func() error {		requestUrl := url.URL{			Scheme:   "http",			Host:     selectedInstance.Address + ":" + strconv.Itoa(selectedInstance.Port),			Path:     "/comments/detail",			RawQuery: "id=" + id,		}		resp, err := http.Get(requestUrl.String())		if err != nil {			return err		}		body, _ := ioutil.ReadAll(resp.Body)		jsonErr := json.Unmarshal(body, &result)		if jsonErr != nil {			return jsonErr		}		return nil	}, func(e error) error {		// 断路器打开时的处理逻辑,本示例是直接返回错误提示		return errors.New("Http errors!")	})	if call_err == nil {		return result, nil	} else {		return result, call_err	}}func (service *GoodsDetailServiceImpl) InitConfig(ctx context.Context) {	cli, _ := clientv3.New(clientv3.Config{		Endpoints:   []string{"127.0.0.1:2379"},		DialTimeout: 5 * time.Second,	})	// get	resp, _ := cli.Get(ctx, "call_service_d")	for _, ev := range resp.Kvs {		fmt.Printf("%s:%s\n", ev.Key, ev.Value)		if string(ev.Key) == "call_service_d" {			service.callCommentService, _ = strconv.Atoi(string(ev.Value))		}	}	rch := cli.Watch(context.Background(), "call_service_d") // <-chan WatchResponse	for wresp := range rch {		for _, ev := range wresp.Events {			fmt.Printf("Type: %s Key:%s Value:%s\n", ev.Type, ev.Kv.Key, ev.Kv.Value)			if string(ev.Kv.Key) == "call_service_d" {				service.callCommentService, _ = strconv.Atoi(string(ev.Kv.Value))			}		}	}}func (service *GoodsDetailServiceImpl) HealthCheck() string {	return "OK"}
 |