123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package service
- import (
- "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"
- }
|