Spring Cloud Alibaba(一) 如何使用nacos服務註冊和發現

  • 2019 年 10 月 18 日
  • 筆記

Nacos介紹

Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。

Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平台。 Nacos 是構建以「服務」為中心的現代應用架構 (例如微服務範式、雲原生範式) 的服務基礎設施。

Nacos 的關鍵特性

  • 服務發現和服務健康監測
  • 動態配置服務,帶管理介面,支援豐富的配置維度。
  • 動態 DNS 服務
  • 服務及其元數據管理

Nacos下載及部署

官方介紹文檔:Nacos 快速開始或者直接下載zip包,部署下載

windows環境部署過程遇到的問題匯總

jdk版本要求

一定要注意,jdk版本要求 64bit JDK 1.8+

運行報錯

運行startup.cmd,一閃而過。打開startup.cmd腳本,在最後一行添加 pause 使報錯不會立即結束方便查看報錯資訊,這時會發現以下報錯資訊:

Exception in thread "main" java.lang.UnsupportedClassVersionError: org/springfra  mework/boot/loader/PropertiesLauncher : Unsupported major.minor version 52.0          at java.lang.ClassLoader.defineClass1(Native Method)          at java.lang.ClassLoader.defineClass(ClassLoader.java:800)          at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14  2)          at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)          at java.net.URLClassLoader.access$100(URLClassLoader.java:71)          at java.net.URLClassLoader$1.run(URLClassLoader.java:361)          at java.net.URLClassLoader$1.run(URLClassLoader.java:355)          at java.security.AccessController.doPrivileged(Native Method)          at java.net.URLClassLoader.findClass(URLClassLoader.java:354)          at java.lang.ClassLoader.loadClass(ClassLoader.java:425)          at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)          at java.lang.ClassLoader.loadClass(ClassLoader.java:358)          at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)

產生以上問題的原因是我電腦上有些老項目使用jdk 1.7,所以項目是jdk1.7和jdk1.8交叉著使用。在cmd里查看版本 java -version 輸出然後是1.8.0_211(只會輸出最高的版本)

解決方案

  • 配置java_home,增加jdk1.8環境變數,怎麼添加環境變數需要自行百度,以下貼出我的java環境變數
C:UsersAdministrator>set java_home  JAVA_HOME=D:Program FilesJavajdk1.7.0_71    C:UsersAdministrator>set java8_home  JAVA8_HOME=D:Program FilesJavajdk1.8.0_201    C:UsersAdministrator>
  • 調整startup.cmd腳本,使用java8_home變數,使它能正確調用jdk1.8而非jdk1.7,以下是調整部分程式碼
if not exist "%JAVA8_HOME%binjava.exe" echo Please set the JAVA8_HOME variable in your environment, We need java(x64)! jdk8 or later is better! & EXIT /B 1  set "JAVA=%JAVA8_HOME%binjava.exe"

這裡只做個替換,把原來的JAVA_HOME規劃成JAVA8_HOME,運行startup.cmd,此時能正確運行Nacos服務了

查看介面

啟動成功,在瀏覽器上訪問:http://localhost:8848/nacos ,會跳轉到登陸介面,默認的登陸用戶名為nacos,密碼也為nacos。

登陸成功後,就可以操作管理介面了

使用Nacos服務註冊和發現

要使用nacos,需要在pom.xml添加必要的依賴

    <dependencyManagement>          <dependencies>              <dependency>                  <groupId>org.springframework.cloud</groupId>                  <artifactId>spring-cloud-dependencies</artifactId>                  <version>Greenwich.SR3</version>                  <type>pom</type>                  <scope>import</scope>              </dependency>              <dependency>                  <groupId>com.alibaba.cloud</groupId>                  <artifactId>spring-cloud-alibaba-dependencies</artifactId>                  <version>2.1.0.RELEASE</version>                  <type>pom</type>                  <scope>import</scope>              </dependency>          </dependencies>      </dependencyManagement>

服務註冊與發現示例程式碼創建

在本案例中,使用3個服務註冊到Nacos上,分別為服務提供者ali-nacos-provider和負載均衡ribbon消費者ali-nacos-consumer-ribbon、申明式服務調用feign消費者ali-nacos-consumer-feign。

什麼是ribbon和feign,及使用示例這裡不重複介紹,需要了解可以查看示例

創建服務提供者ali-nacos-provider

pom.xml添加nacos依賴

    <dependency>          <groupId>com.alibaba.cloud</groupId>          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>      </dependency>

application.yml配置

server:    port: 9000  #指定為9000埠    spring:    application:      name: ali-nacos-provider  #服務名    cloud:      nacos:        discovery:          server-addr: 127.0.0.1:8848 #服務註冊地址(nacos默認為8848埠)    management:    endpoints:      web:        exposure:          include: '*'

啟動類增加 @EnableDiscoveryClient 註解

package com.easy.aliNacosProvider;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.client.discovery.EnableDiscoveryClient;    @EnableDiscoveryClient  @SpringBootApplication  public class AliNacosProviderApplication {        public static void main(String[] args) {          SpringApplication.run(AliNacosProviderApplication.class, args);      }  }

寫個hello服務介面 HelloController.java

package com.easy.aliNacosProvider;    import lombok.extern.slf4j.Slf4j;  import org.springframework.web.bind.annotation.GetMapping;  import org.springframework.web.bind.annotation.PathVariable;  import org.springframework.web.bind.annotation.RestController;    @RestController  @Slf4j  public class HelloController {      @GetMapping(value = "/hello/{str}", produces = "application/json")      public String hello(@PathVariable String str) {          log.info("-----------收到消費者請求-----------");          log.info("收到消費者傳遞的參數:" + str);          String result = "我是服務提供者,見到你很高興==>" + str;          log.info("提供者返回結果:" + result);          return result;      }  }

創建ribbon服務消費者

pom.xml增加nocos和ribbon依賴

    <dependencies>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-actuator</artifactId>          </dependency>            <dependency>              <groupId>com.alibaba.cloud</groupId>              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>          </dependency>        </dependencies>

application.yml

server:    port: 9100    spring:    application:      name: ali-nacos-consumer-ribbon    cloud:      nacos:        discovery:          server-addr: 127.0.0.1:8848

服務調用HomeController.java

package com.easy.ancRibbon;    import lombok.extern.slf4j.Slf4j;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.web.bind.annotation.GetMapping;  import org.springframework.web.bind.annotation.RestController;  import org.springframework.web.client.RestTemplate;    @RestController  @Slf4j  public class HomeController {      @Autowired      private RestTemplate restTemplate;        @GetMapping(value = "/", produces = "application/json")      public String home() {          log.info("-----------------consumer調用開始-----------------");          String param = "雲天";          log.info("消費者傳遞參數:" + param);          String result = restTemplate.getForObject("http://ali-nacos-provider/hello/" + param, String.class);          log.info("收到提供者響應:" + result);          return "ribbon消費者," + result;      }  }  

啟用類AncRibbonConsumerApplication.java

package com.easy.ancRibbon;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  import org.springframework.cloud.client.loadbalancer.LoadBalanced;  import org.springframework.context.annotation.Bean;  import org.springframework.web.client.RestTemplate;    @SpringBootApplication  @EnableDiscoveryClient  public class AncRibbonConsumerApplication {        @Bean      @LoadBalanced      public RestTemplate restTemplate() {          return new RestTemplate();      }        public static void main(String[] args) {          SpringApplication.run(AncRibbonConsumerApplication.class, args);      }    }

創建feign服務消費者

pom.xml

    <dependencies>          <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-openfeign</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <dependency>              <groupId>com.alibaba.cloud</groupId>              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-actuator</artifactId>          </dependency>      </dependencies>

application.yml

server:    port: 9101    spring:    application:      name: ali-nacos-consumer-feign    cloud:      nacos:        discovery:          server-addr: 127.0.0.1:8848    main:      allow-bean-definition-overriding: true  #允許一樣的beanName

這裡有個坑要注意下,如果allow-bean-definition-overriding為設置為true,運行會報如下錯:

錯誤: Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

這裡有問題的詳細介紹問題原因

申請服務HelloService.java

package com.easy.ancFeign;    import org.springframework.cloud.openfeign.FeignClient;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestParam;    @FeignClient("ali-nacos-provider")  public interface HelloService {        @RequestMapping(path = "hello/{str}")      String hello(@RequestParam("str") String param);    }

服務調用HomeController.java

package com.easy.ancFeign;    import lombok.extern.slf4j.Slf4j;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;    import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.web.bind.annotation.GetMapping;  import org.springframework.web.bind.annotation.RestController;    @RestController  @Slf4j  public class HomeController {        @Autowired      private HelloService helloService;        @GetMapping(value = "/", produces = "application/json")      public String home() {          log.info("-----------------consumer調用開始-----------------");          String param = "雲天";          log.info("消費者傳遞參數:" + param);          String result = helloService.hello(param);          log.info("收到提供者響應:" + result);          return "feign消費者" + result;      }  }  

啟動類AncFeignConsumerApplication.java

package com.easy.ancFeign;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.openfeign.EnableFeignClients;    @SpringBootApplication  @EnableFeignClients(basePackages = {"com.easy.ancFeign"})  public class AncFeignConsumerApplication {      public static void main(String[] args) {          SpringApplication.run(AncFeignConsumerApplication.class, args);      }  }

使用示例

現有三個項目如下

ali-nacos-provider:服務提供者1,服務名:ali-nacos-provider,埠:9000
ali-nacos-consumer-ribbon:ribbon服務消費者,服務名:ali-nacos-consumer-ribbon,埠:9100
ali-nacos-consumer-feign:feign消費者,服務名:ali-nacos-consumer-feign,埠:9101

運行測試

首先要啟動服務註冊中心 nacos
其次,分別啟動ali-nacos-provider、ali-nacos-consumer-ribbon、ali-nacos-consumer-feign三個服務

  • 訪問地址:http://localhost:9100/,返回:ribbon消費者,我是服務提供者,見到你很高興==>雲天,說明ribbon消費成功了。
  • 訪問地址:http://localhost:9101/,返回:feign消費者我是服務提供者,見到你很高興==>雲天,說明feign消費費成功了。
  • 訪問地址:http://localhost:9000/hello/yuntian,返回:我是服務提供者,見到你很高興==>yuntian,說明服務提供者訪問成功了(PS:服務提供者一般是不對外公開的,怎麼隱蔽介面將在接下去的文章里介紹)
  • 訪問地址:http://localhost:8848/nacos/#/login,輸入用戶:nacos,密碼:nacos。進入服務管理介面,在服務管理-服務列表裡可以看到我們運行的三個服務了。

資料

Tags: