欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2018年06月05日 10:06:15   作者:神牛步行3  
這篇文章主要介紹了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)看一副手工圖:

手工圖上能夠看出消費(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)分析;首先添加依賴如:

<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層類和代碼:

@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è)試:

@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:

@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)方顯示的效果:

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

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

/**
 * 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)用):

@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ò)誤如:

簡(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ù)如:

/**
   * 自動(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接口看下效果:

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

相關(guān)文章

  • 詳解Mybatis的分頁(yè)插件

    詳解Mybatis的分頁(yè)插件

    這篇文章主要介紹了詳解Mybatis的分頁(yè)插件,在 Mybatis中,如何對(duì)數(shù)據(jù)進(jìn)行分頁(yè)是一個(gè)非常常見(jiàn)的問(wèn)題,現(xiàn)在,我們可以通過(guò)使用 Mybatis 的分頁(yè)插件來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)的分頁(yè),需要的朋友可以參考下
    2023-05-05
  • 關(guān)于SpringBoot的自動(dòng)裝配原理詳解

    關(guān)于SpringBoot的自動(dòng)裝配原理詳解

    這篇文章主要介紹了關(guān)于SpringBoot的自動(dòng)裝配原理詳解,Spring?Boot自動(dòng)裝配原理是指Spring?Boot在啟動(dòng)時(shí)自動(dòng)掃描項(xiàng)目中的依賴關(guān)系,根據(jù)依賴關(guān)系自動(dòng)配置相應(yīng)的Bean,從而簡(jiǎn)化了Spring應(yīng)用的配置過(guò)程,需要的朋友可以參考下
    2023-07-07
  • springcloud gateway聚合swagger2的方法示例

    springcloud gateway聚合swagger2的方法示例

    這篇文章主要介紹了springcloud gateway聚合swagger2的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • mybatis一對(duì)多兩種mapper寫(xiě)法實(shí)例

    mybatis一對(duì)多兩種mapper寫(xiě)法實(shí)例

    這篇文章主要介紹了mybatis一對(duì)多兩種mapper寫(xiě)法實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • java long轉(zhuǎn)String +Codeforces110A案例

    java long轉(zhuǎn)String +Codeforces110A案例

    這篇文章主要介紹了java long轉(zhuǎn)String +Codeforces110A案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • SpringBoot通過(guò)@MatrixVariable進(jìn)行傳參詳解

    SpringBoot通過(guò)@MatrixVariable進(jìn)行傳參詳解

    這篇文章主要介紹了SpringBoot使用@MatrixVariable傳參,文章圍繞@MatrixVariable展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • Java 獲取網(wǎng)站圖片的示例代碼

    Java 獲取網(wǎng)站圖片的示例代碼

    本文主要介紹了Java 獲取網(wǎng)站圖片的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java中Set集合的使用和底層原理解析

    Java中Set集合的使用和底層原理解析

    這篇文章主要介紹了Java中Set集合的使用和底層原理,Set集合的功能上基本上與Collection的API一致, Set集合沒(méi)有擴(kuò)展額外的API,本文通過(guò)示例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2022-12-12
  • Jenkins集成SonarQube的方法詳解

    Jenkins集成SonarQube的方法詳解

    這篇文章主要介紹了Jenkins集成SonarQube的方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 使用springBoot中的info等級(jí)通過(guò)druid打印sql

    使用springBoot中的info等級(jí)通過(guò)druid打印sql

    這篇文章主要介紹了使用springBoot中的info等級(jí)通過(guò)druid打印sql,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論