激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

2021-05-07 13:01神牛步行3 Java教程

這篇文章主要介紹了springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件,本篇來(lái)使用rest+ribbon消費(fèi)服務(wù),并且通過(guò)輪詢方式來(lái)自定義了個(gè)簡(jiǎn)易消費(fèi)組件,感興趣的小伙伴們可以參考一下

本次和大家分享的是怎么來(lái)消費(fèi)服務(wù),上篇文章講了使用feign來(lái)消費(fèi),本篇來(lái)使用rest+ribbon消費(fèi)服務(wù),并且通過(guò)輪詢方式來(lái)自定義了個(gè)簡(jiǎn)易消費(fèi)組件,本文分享的宗旨是:自定義消費(fèi)服務(wù)的思路;思路如果有可取之處還請(qǐng)“贊”一下:

  1. rest+ribbon實(shí)現(xiàn)消費(fèi)服務(wù)
  2.  rest+輪詢自定義簡(jiǎn)易消費(fèi)組件
  3. 使用scheduled刷新服務(wù)提供者信息

rest+ribbon實(shí)現(xiàn)消費(fèi)服務(wù)

做為服務(wù)消費(fèi)方準(zhǔn)確的來(lái)說(shuō)進(jìn)行了兩種主流程區(qū)分1)獲取可以服務(wù)2)調(diào)用服務(wù),那么又是如何獲取服務(wù)的并且又是通過(guò)什么來(lái)調(diào)用服務(wù)的,下面我們來(lái)看一副手工圖:

springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

手工圖上能夠看出消費(fèi)方先獲取了服務(wù)方的真實(shí)接口地址,然后再通過(guò)地址去調(diào)用接口;然后對(duì)于微服務(wù)架構(gòu)來(lái)說(shuō)獲取某一個(gè)類ip或端口然后去調(diào)用接口肯定是不可取的,因此微服務(wù)中產(chǎn)生了一種serviceid的概念;簡(jiǎn)單流程介紹完了,下面通過(guò)實(shí)例來(lái)分析;首先添加依賴如:

?
1
2
3
4
5
6
7
8
<dependency>
  <groupid>org.springframework.boot</groupid>
  <artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
  <groupid>org.springframework.cloud</groupid>
  <artifactid>spring-cloud-starter-eureka</artifactid>
</dependency>

再來(lái)我們通過(guò)上篇文章搭建的eureka_server(服務(wù)中心),eureka_provider(服務(wù)提供者)來(lái)做測(cè)試用例,這里我重新定義eureka_consumer_ribbon模塊做為消費(fèi)服務(wù);先創(chuàng)建service層類和代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@service
public class userservice implements userinterface {
 
  @autowired
  protected resttemplate resttemplate;
 
  @override
  public morp<list<mouser>> getusers(morq rq) {
    return null;
  }
 
  @override
  public string getmsg() {
 
    string str = resttemplate.getforobject("http://eureka-provider/msg", string.class);
    return str;
  }
}

主要用到了resttemplate的 resttemplate.getforobject 函數(shù),然后需要定義個(gè)controller來(lái)吧獲取到的數(shù)據(jù)響應(yīng)到頁(yè)面上,為了簡(jiǎn)單這里僅僅只拿getmsg服務(wù)接口測(cè)試:

?
1
2
3
4
5
6
7
8
9
10
11
12
@restcontroller
public class usercontroller {
 
  @autowired
  private userservice userservice;
 
  @getmapping("/msg")
  public string getmsg(){
 
    return userservice.getmsg();
  }
}

最后我們?cè)趩?dòng)類添加入下代碼,注意 @loadbalanced 標(biāo)記必須加,因?yàn)檎円氲膃ureka依賴?yán)锩姘藃ibbon(dalston.release版本),ribbon封裝了負(fù)載均衡的算法,如果不加這個(gè)注解,那后面rest方法的url就必須是可用的url路徑了,當(dāng)然這里加了注解就可以使用上面說(shuō)的serviceid:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@springbootapplication
@enablediscoveryclient //消費(fèi)客戶端
public class eurekaconsumerribbonapplication {
 
  @bean
  @loadbalanced //負(fù)載均衡
  resttemplate resttemplate(){
    return new resttemplate();
  }
  
  public static void main(string[] args) {
    springapplication.run(eurekaconsumerribbonapplication.class, args);
  }
}

下面來(lái)消費(fèi)方顯示的效果:

springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

rest+輪詢自定義簡(jiǎn)易消費(fèi)組件

自定義消費(fèi)組件原來(lái)和面手工圖差不多,就是先想法獲取服務(wù)提供端真實(shí)的接口地址,然后通過(guò)rest去調(diào)用這個(gè)url,得到相應(yīng)的結(jié)果輸出;這里自定義了一個(gè)shenniubanlance的組件類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
 * created by shenniu on 2018/6
 * <p>
 * rest+eureka+自定義client端
 */
@component
public class shenniubanlance {
 
  @autowired
  private resttemplate resttemplate;
 
  @autowired
  private discoveryclient discoveryclient;
 
  /**
   * 服務(wù)真實(shí)地址 concurrenthashmap<"服務(wù)應(yīng)用名稱", ("真實(shí)接口ip", 被訪問(wèn)次數(shù))>
   */
  public static concurrenthashmap<string, list<moservice>> sericesmap = new concurrenthashmap<>();
 
  /**
   * 設(shè)置服務(wù)提供者信息到map
   */
  public void setservicesmap() {
    //獲取所有服務(wù)提供者applicationname
    list<string> appnames = discoveryclient.getservices();
 
    //存儲(chǔ)真實(shí)地址到map
    for (string appname :
        appnames) {
      //獲取某個(gè)服務(wù)提供者信息
      list<serviceinstance> instanceinfos = discoveryclient.getinstances(appname);
      if (instanceinfos.isempty()) {
        continue;
      }
 
      list<moservice> services = new arraylist<>();
      instanceinfos.foreach(b -> {
        moservice service = new moservice();
        //被訪問(wèn)次數(shù)
        service.setwatch(0l);
        //真實(shí)接口地址
        service.seturl(b.geturi().tostring());
        services.add(service);
      });
 
      //如果存在就更新
      sericesmap.put(appname.tolowercase(), services);
    }
  }
 
  /**
   * 根據(jù)app獲取輪詢方式選中后的service
   *
   * @param appname
   * @return
   */
  public moservice choiceservicebyappname(string appname) throws exception {
    appname = appname.tolowercase();
    //某種app的服務(wù)service集合
    list<moservice> servicemap = sericesmap.get(appname);
    if (servicemap == null) {
      //初始化所有app服務(wù)
      setservicesmap();
      servicemap = sericesmap.get(appname);
      if (servicemap == null) {
        throw new exception("未能找到" + appname + "相關(guān)服務(wù)");
      }
    }
 
    //篩選出被訪問(wèn)量最小的service 輪詢的方式
    moservice moservice = servicemap.stream().min(
        comparator.comparing(moservice::getwatch)
    ).get();
 
    //負(fù)載記錄+1
    moservice.setwatch(moservice.getwatch() + 1);
    return moservice;
  }
 
  /**
   * 自動(dòng)刷新 服務(wù)提供者信息到map
   */
  @scheduled(fixeddelay = 1000 * 10)
  public void refreshservicesmap() {
    setservicesmap();
  }
 
  /**
   * get請(qǐng)求服務(wù)獲取返回?cái)?shù)據(jù)
   *
   * @param appname   應(yīng)用名稱 applicationname
   * @param servicename 服務(wù)名稱 servicename
   * @param map     url上請(qǐng)求參數(shù)
   * @param tclass   返回類型
   * @param <t>
   * @return
   */
  public <t> t getservicedata(
      string appname, string servicename,
      map<string, ?> map,
      class<t> tclass) {
    t result = null;
    try {
      //篩選獲取真實(shí)service
      moservice service = choiceservicebyappname(appname);
 
      //請(qǐng)求該service的url
      string apiurl = service.geturl() + "/" + servicename;
      system.out.println(apiurl);
      result = map != null ?
          resttemplate.getforobject(apiurl, tclass, map) :
          resttemplate.getforobject(apiurl, tclass);
    } catch (exception ex) {
      ex.printstacktrace();
    }
    return result;
  }
 
  /**
   * service信息
   */
  public class moservice {
    /**
     * 負(fù)載次數(shù)記錄數(shù)
     */
    private long watch;
    /**
     * 真實(shí)接口地址: http://xxx.com/api/add
     */
    private string url;
 
    public long getwatch() {
      return watch;
    }
 
    public void setwatch(long watch) {
      this.watch = watch;
    }
 
    public string geturl() {
      return url;
    }
 
    public void seturl(string url) {
      this.url = url;
    }
  }
}

以上就是主要的實(shí)現(xiàn)代碼,代碼邏輯:設(shè)置服務(wù)提供者信息到map-》根據(jù)app獲取輪詢方式選中后的service-》請(qǐng)求服務(wù)獲取返回?cái)?shù)據(jù);輪詢實(shí)現(xiàn)的原理是使用了一個(gè)負(fù)載記錄數(shù),每次被請(qǐng)求后自動(dòng)+1,當(dāng)要獲取某個(gè)服務(wù)提供者時(shí),通過(guò)記錄數(shù)篩選出最小值的一個(gè)實(shí)例,里面存儲(chǔ)有真實(shí)接口地址url;調(diào)用只需要這樣(當(dāng)然可以弄成注解來(lái)調(diào)用):

?
1
2
3
4
5
6
7
8
9
10
@override
  public string getmsg() {
 
    string str = banlance.getservicedata(
        "eureka-provider", "msg",
        null,
        string.class
    );
    return str;
  }

這里需要注意由于我們?cè)谇懊鎟esttemplate使用加入了注解 @loadbalanced ,這樣使得rest請(qǐng)求時(shí)必須用非ip的訪問(wèn)方式(也就是必須serviceid)才能正常響應(yīng),不然會(huì)提示錯(cuò)誤如:

springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

簡(jiǎn)單來(lái)說(shuō)就是不用再使用ip了,因?yàn)橛胸?fù)載均衡機(jī)制;當(dāng)我們?nèi)サ暨@個(gè)注解后,我們自定義的組件就能運(yùn)行成功,效果圖和實(shí)例1一樣就不貼圖了;

使用scheduled刷新服務(wù)提供者信息

在微服務(wù)架構(gòu)中,如果某臺(tái)服務(wù)掛了之后,必須要及時(shí)更新client端的服務(wù)緩存信息,不然就可能請(qǐng)求到down的url去,基于這種考慮我這里采用了enablesched標(biāo)記來(lái)做定時(shí)刷新;首先在啟動(dòng)類增加 @enablescheduling ,然后定義一個(gè)刷行服務(wù)信息的服務(wù)如:

?
1
2
3
4
5
6
7
/**
   * 自動(dòng)刷新 服務(wù)提供者信息到map
   */
  @scheduled(fixeddelay = 1000 * 10)
  public void refreshservicesmap() {
    setservicesmap();
  }

為了方便看測(cè)試效果,我們?cè)趕erver,provider(2個(gè)),consumer已經(jīng)啟動(dòng)的情況下,再啟動(dòng)一個(gè)端口為2005的provider服務(wù);然后刷新consumer接口看下效果:

springcloud之自定義簡(jiǎn)易消費(fèi)服務(wù)組件

這個(gè)時(shí)候能夠看到調(diào)用2005端口的接口成功了,通過(guò)@scheduled定時(shí)服務(wù)吧最新或者失效的服務(wù)加入|移除掉,就達(dá)到了咋們的需求了;如果你覺(jué)得該篇內(nèi)容對(duì)你有幫助,不防贊一下,謝謝。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/wangrudong003/p/9134870.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美一级免费看 | 国产精品99久久久久久董美香 | 做爰裸体激情2 | 亚洲视频综合 | 二区三区四区视频 | 亚洲日本欧美 | 国产一区二区精品在线观看 | 免费人成在线播放 | 欧美五月婷婷 | 欧美高清一级片 | 91情侣在线偷精品国产 | 日韩av成人| 9999免费视频 | 性大片1000免费看 | 久草经典视频 | 日韩视频在线观看免费视频 | 欧美成人高清视频 | 一二区成人影院电影网 | 欧美成人一区二区三区电影 | 久久人人人| 国产精品久久久久av | 久久精品亚洲一区二区 | 亚洲国产色婷婷 | 色妞视频男女视频 | 黄色网址在线播放 | 国产精品国产成人国产三级 | 中文字幕在线看第二 | 九九热九九爱 | 欧美日韩精品一区二区三区蜜桃 | 亚洲影院在线播放 | 亚洲电影在线播放 | 91免费高清视频 | 成人福利软件 | 色女孩网 | 亚洲视频精选 | 欧美黄色试片 | 色a综合 | 99视频观看| 国产1区2 | 九色国产 | 久草热久 |