新微服務項目多半採用Nacos做爲服務註冊與發現中心,可是舊項目可能使用Eureka、zookeeper、Consul、Nacos做爲服務註冊中心。
新項目建議使用Nacos做爲服務註冊中心html
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.spz.demo</groupId> <artifactId>spring-cloud-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <!-- <module>api-common</module> <module>ms-provider</module> <module>ms-consumer</module> <module>eureka-server</module> --> </modules> <!-- 統一管理jar包版本 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <mysql.version>8.0.16</mysql.version> <druid.version>1.1.16</druid.version> <mybatis.plus.version>3.3.2</mybatis.plus.version> <jackson-version>2.9.9</jackson-version> </properties> <dependencyManagement> <dependencies> <!-- Spring Boot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring Cloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring Cloud Alibaba --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis.plus.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> </dependencies> </dependencyManagement> </project>
首先須要在根pom.xml的modules標籤下加入該模塊:java
<modules> <module>api-common</module> <!-- <module>ms-provider</module> <module>ms-consumer</module> --> <module>eureka-server</module> </modules>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.spz.demo</groupId> <artifactId>spring-cloud-demo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-server</artifactId> <packaging>jar</packaging> <description>Eureka註冊中心</description> <dependencies> <!-- Eureka Server--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.spz.demo</groupId> <artifactId>api-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
package com.spz.demo.scloud.register.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class RegisterServerEureka { public static void main(String[] args) { SpringApplication.run(RegisterServerEureka.class, args); } }
server.port=6001 spring.application.name=@project.artifactId@ # Eureka 配置 # Eureka Server 實例 hostname eureka.instance.hostname=eureka6001 # 服務端不須要註冊本身 eureka.client.register-with-eureka=false # 服務端不須要檢索服務 eureka.client.fetch-registry=false # Eureka Server 向其餘服務端註冊本身,實現Eureka的高可用集羣 eureka.client.service-url.defaultZone=http://eureka6002:6002/eureka,http://eureka6003:6003/eureka # 關閉自我保護機制,保證不可用服務被及時踢除,建議生產環境保持默認 #eureka.server.enable-self-preservation=false #eureka.server.eviction-interval-timer-in-ms=2000
eureka 服務端實例實現高可用集羣的方法是多個Eureka Server節點互相註冊。好比A、B、C三個節點,A把本身做爲Eureka客戶端註冊到B、C節點;B把本身註冊到A、C節點;C把本身註冊到A、B節點。這樣三個節點互相具有其餘服務端節點的信息,客戶端列表數據也至關於保存了三分,這時候某個服務端節點失效,並不會形成客戶端信息缺失,由此實現了高可用集羣。下面介紹高可用集羣實現方法:mysql
127.0.0.1 eureka6001 127.0.0.1 eureka6002 127.0.0.1 eureka6003
-Dserver.port=6001 -Deureka.instance.hostname=eureka6001 -Deureka.client.service-url.defaultZone=http://eureka6002:6002/eureka,http://eureka6003:6003/eureka
vm options:git
-Dserver.port=6002 -Deureka.instance.hostname=eureka6002 -Deureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6003:6003/eureka
vm options:web
-Dserver.port=6003 -Deureka.instance.hostname=eureka6003 -Deureka.client.service-url.defaultZone=http://eureka6002:6002/eureka,http://eureka6001:6001/eureka
IDEA方式啓動
啓動RegisterServerEureka600一、RegisterServerEureka600二、RegisterServerEureka6003便可,啓動後分別訪問三個節點的管理端:spring
例如訪問 http://eureka6001:6001/sql
如圖eureka6001節點的DS Replicas出現了另外兩個相鄰節點,說明這三個節點組成了一個集羣,這時候訪問另外兩個節點的管理頁,也能一樣看到DS Replicas裏出現其餘兩個節點。另外,當有客戶端註冊進服務端時,三個服務端節點裏應該有同一份的客戶端列表信息。至此Eureka集羣搭建成功。apache
首先須要在根pom.xml的modules標籤下加入該模塊:json
<modules> <module>api-common</module> <module>ms-provider</module> <!-- <module>ms-consumer</module> --> <module>eureka-server</module> </modules>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.spz.demo</groupId> <artifactId>spring-cloud-demo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>ms-provider</artifactId> <packaging>jar</packaging> <description>服務提供者模塊</description> <dependencies> <!-- sleuth zipkin 服務追蹤 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <!-- eureka client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.spz.demo</groupId> <artifactId>api-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
server.port=8001 spring.application.name=MS-PROVIDER # 服務追蹤 #spring.zipkin.base-url=http://localhost:9411 #採樣率值介於 0 到 1 之間,1 則表示所有采集 #spring.sleuth.sampler.probability=1 # eureka 配置 # 是否將本身註冊進 EurekaServer 默認爲true eureka.client.register-with-eureka=true # 是否從 EurekaServer 抓取已有的註冊信息,默認爲true。單節點無所謂,集羣必須設置爲true才能配合ribbon使用負載均衡 eureka.client.fetchRegistry=true eureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6002:6002/eureka,http://eureka6003:6003/eureka # 實例ID eureka.instance.instance-id=${spring.application.name}-${server.port} # 訪問路徑能夠顯示IP地址 eureka.instance.prefer-ip-address=true # Eureka客戶端向服務端發送心跳的時間間隔,單位爲秒(默認是30秒) eureka.instance.lease-renewal-interval-in-seconds=1 # Eureka服務端在收到最後一次心跳後等待時間上限,單位爲秒(默認是90秒),超時將剔除服務 eureka.instance.lease-expiration-duration-in-seconds=10
package com.spz.demo.scloud.provider.controller; import com.spz.demo.scloud.common.core.bean.RestBean; import com.spz.demo.scloud.common.service.AppService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("") public class IndexController { @Autowired private AppService appService; /** * 獲取項目信息 * @return */ @RequestMapping("/projectInfo") public RestBean projectInfo(){ String msg = appService.instanceNameAndPort(); return RestBean.ok(msg); } }
package com.spz.demo.scloud.provider.service; import com.spz.demo.scloud.common.service.AppService; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** * App Service 接口實現類 */ @Service public class AppServiceImpl implements AppService { /** * 項目端口 */ @Value("${server.port}") private Integer projectServerPort; /** * 項目名稱 */ @Value("${spring.application.name}") private String projectApplicationName; @Override public String instanceNameAndPort(){ return projectApplicationName + ":" + projectServerPort; } }
package com.spz.demo.scloud.provider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @EnableDiscoveryClient @SpringBootApplication public class ProviderApp { public static void main(String[] args) { SpringApplication.run(ProviderApp.class, args); } }
客戶端服務(這裏是本機,因此只須要配置一次,若是是不一樣服務器則須要配置)也須要配置hosts,否則沒法訪問Eureka註冊中心集羣後端
127.0.0.1 eureka6001 127.0.0.1 eureka6002 127.0.0.1 eureka6003
vm options:
-Dserver.port=8001 -Deureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6002:6002/eureka,http://eureka6003:6003/eureka
vm options:
-Dserver.port=8002 -Deureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6002:6002/eureka,http://eureka6003:6003/eureka
IDEA方式啓動
啓動ProviderApp800一、ProviderApp8002便可,啓動後分別訪問三個註冊中心的管理端:
訪問三個註冊中心管理端,應該都可以看到這裏有相同的客戶端信息
服務提供者集羣搭建完成
首先須要在根pom.xml的modules標籤下加入該模塊:
<modules> <module>api-common</module> <module>ms-provider</module> <module>ms-consumer</module> <module>eureka-server</module> </modules>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.spz.demo</groupId> <artifactId>spring-cloud-demo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>ms-consumer</artifactId> <packaging>jar</packaging> <description>消費者模塊</description> <dependencies> <!-- sleuth zipkin 服務追蹤 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <!-- eureka client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.spz.demo</groupId> <artifactId>api-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
server.port=7001 spring.application.name=MS-CONSUMER # 服務追蹤 #spring.zipkin.base-url=http://localhost:9411 #採樣率值介於 0 到 1 之間,1 則表示所有采集 #spring.sleuth.sampler.probability=1 # Eureka 註冊中心配置 # 是否將本身註冊進 Eureka Server 默認爲true eureka.client.register-with-eureka=true # 實例ID eureka.instance.instance-id=${spring.application.name}-${server.port} # 訪問路徑能夠顯示IP地址 eureka.instance.prefer-ip-address=true # 是否從 Eureka Server 抓取已有的註冊信息,默認爲true 單節點無所謂,集羣必須設置爲true才能配合ribbon使用負載均衡 eureka.client.fetchRegistry=true # Eureka Server 集羣 eureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6002:6002/eureka,http://eureka6003:6003/eureka
package com.spz.demo.scloud.consumer.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** * RestTemplate 配置 */ @Configuration public class RestTemplateConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
package com.spz.demo.scloud.consumer.controller; import com.spz.demo.scloud.common.core.bean.RestBean; import com.spz.demo.scloud.common.service.AppService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.net.URI; import java.util.List; /** * 註冊中心 - Eureka - 測試接口 */ @Slf4j @RestController @RequestMapping("/discovery/eureka") public class DiscoveryEurekaController { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; /** * 服務遠程調用測試 - 使用 RestTemplate * @see AppService#instanceNameAndPort() * @return */ @RequestMapping("/appService/projectInfo") public RestBean appServiceProjectInfo(){ RestBean restBean = restTemplate.postForObject("http://MS-PROVIDER/projectInfo",null, RestBean.class); return restBean; } /** * 獲取已在 Eureka Server 註冊的服務名稱列表 * 注意不是服務名下的實例名稱列表,是 Eureka的Application名稱列表 * @return */ @RequestMapping("/services") public RestBean services(){ List<String> services = discoveryClient.getServices(); return RestBean.ok(services); } /** * 根據名稱獲取實例列表 * 1. 如多個服務註冊到Eureka服務端,他們的名稱均爲MS-PROVIDER,則使用MS-PROVIDER可查詢出全部已註冊實例 * 2. 獲取到ServiceInstance對象裏包含實例的ServiceId、host、port、uri等 * @param name eg. MS-PROVIDER * @return */ @GetMapping("/instances/{name}") public RestBean instancesByName(@PathVariable(name = "name", required = true) String name){ List<ServiceInstance> instances = discoveryClient.getInstances(name); return RestBean.ok(instances); } }
package com.spz.demo.scloud.consumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @EnableDiscoveryClient @SpringBootApplication public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class, args); } }
vm options:
-Dserver.port=7001 -Deureka.client.service-url.defaultZone=http://eureka6001:6001/eureka,http://eureka6002:6002/eureka,http://eureka6003:6003/eureka
http://localhost:7001/discovery/eureka/appService/projectInfo
能夠發現返回的端口號會在8001和8002之間交替變化,說明服務提供者註冊的兩個實例都可以訪問
{ "code": 2000, "message": "MS-PROVIDER:8001", "data": null } { "code": 2000, "message": "MS-PROVIDER:8002", "data": null }
於服務提供者集羣實現方式類似,這裏再也不贅述
QQ羣
歡迎加入Java交流羣(qq羣號: 776241689 )
公衆號
PS:小到Java後端技術、計算機基礎知識,大到微服務、Service Mesh、大數據等,都是本人研究的方向。我將按期在公衆號中分享技術乾貨,但願以我一己之力,拋磚引玉,幫助朋友們提高技術能力,共同進步!
博客
原創不易,轉載請在開頭著名文章來源和做者。若是個人文章對您有幫助,請點贊/收藏/關注鼓勵支持一下吧❤❤❤❤❤❤