集羣組件以及關係
部署(eureka-client *2 ,ribbon 1 ,eureka-server3)
eureka-client
eureka-client:微服務的服務具體實現,單節點具體服務註冊,註冊到同一eureka集羣可實現集羣部署
ribbon:負載均衡,客戶端訪問的是該節點,實現多種負載均衡策略
eureka-server
EurekaServer同時也是EurekaClient。用於微服務集羣的管理
eureka-server部署
項目結構
服務端客戶端唯一區別在標紅部分註解不一樣。pom文件版本必須一致
eureka pom,parent,dependencies,dependencyManagement,build,repositories:
<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.cxz</groupId>
<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<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-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
java:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Hello world!
*
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
單機eureka
單機啓動時
application.yml配置如下:
server:
port: 8761
eureka:
instance:
hostname: eureka1
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://eureka1:8761/eureka/
注意,name不能用localhost
hostname在hosts中添加映射
127.0.0.1 eureka1
127.0.0.1 eureka2
127.0.0.1 eureka3
完成後即可啓動成功,訪問對應主頁即可
集羣eureka
application-dev1.yml配置如下:
server:
port: 8762
#spring:
# application:
# name: spring-cloud-eureka-server
eureka:
instance:
#服務註冊中心實例的主機名
hostname: eureka1
# = true 就可以將IP註冊到Eureka Server上,而如果不配置就是機器的主機名。
prefer-ip-address: false
client:
#是否向服務註冊中心註冊自己
register-with-eureka: true
#是否檢索服務
fetch-registry: true
#服務註冊中心的配置內容,指定服務註冊中心的位置
serviceUrl:
defaultZone: http://eureka2:8763/eureka/, http://eureka3:8764/eureka/
application-dev2.yml配置如下:
server:
port: 8763
#spring:
# application:
# name: spring-cloud-eureka-server
eureka:
instance:
hostname: eureka2
# = true 就可以將IP註冊到Eureka Server上,而如果不配置就是機器的主機名。
prefer-ip-address: false
client:
register-with-eureka: true
fetch-registry: true
serviceUrl:
defaultZone: http://eureka1:8762/eureka/, http://eureka3:8764/eureka/
application-dev3.yml配置如下:
server:
port: 8764
#spring:
# application:
# name: spring-cloud-eureka-server
eureka:
instance:
#要用域名,不能用localhost
hostname: eureka3
# = true 就可以將IP註冊到Eureka Server上,而如果不配置就是機器的主機名。
prefer-ip-address: false
client:
register-with-eureka: true
fetch-registry: true
serviceUrl:
defaultZone: http://eureka1:8762/eureka/, http://eureka2:8763/eureka/
application.properties內容如下:
[email protected]@
#java -jar eureka-server.jar --spring.profiles.active=dev2
#java -jar eureka-server.jar --spring.profiles.active=dev3
#java -jar eureka-server.jar --spring.profiles.active=dev4
打包時,運行對應的文件即可
成功後,相關界面顯示如下:
踩坑總結
1.版本boot和cloud有相關版本對應關係,不兼容會啓動失敗
SpringBoot SpringCloud
1.2.X Angel
1.3.X Brixton
1.4.X Camden
1.5.X Dalston、Edgware
2.0.X Finchley
2.1.X Greenwich
2.available-replicas爲空
= true 就可以將IP註冊到Eureka Server上,而如果不配置就是機器的主機名。
prefer-ip-address: false
3.項目用properties,官網用yml
可以同時使用
client註冊
具體服務
繼續使用springboot項目onemillion作爲具體服務提供者:
pom中增加和eureka-server相同配置:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mysqlVersion>8.0.13</mysqlVersion>
<druidVersion>1.1.14</druidVersion>
<springCloudVerion>Greenwich.RELEASE</springCloudVerion>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${springCloudVerion}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
然後在項目啓動類加入註解@EnableEurekaClient即可:
@SpringBootApplication
//@EnableEurekaClient 和 @EnableDiscoveryClient的區別:
//這兩個都是服務發現的註解,區別是:前者是隻針對註冊中心是Eureka使用的註解,後者是兼容所有的註冊中心,例如:Zookeeper等。
@EnableEurekaClient
//因爲多模塊中其他配置模塊也需要spring組件功能,所以發佈模塊需要加載其他模塊的內容.
@ComponentScan(basePackages = {"org.million.**"})
//mybatis掃描
@MapperScan("org.million.dao.**")
public class Start extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
爲了方便定位服務,我們application.properties給項目起個明作爲服務名,以及註冊到eureka集羣中心
#app
server.port=8898
spring.application.name=one-million
server.servlet.context-path=/one-million-dev
# 註冊中心地址,如果是集羣,那就逗號分隔
eureka.client.serviceUrl.defaultZone=http://eureka1:8762/eureka/, http://eureka2:8763/eureka/,http://eureka3:8764/eureka/
使用不同端口啓動:
項目名稱ONE-MILLION 在後面ribbon中需要用到
ribbon
我們用ribbon作爲服務對外的真正提供者,使用之前用的testboot作用ribbon項目
ribbon pom和onemillion這個具體服務者pom文件類似,只是多新增了一個ribbon包依賴
<!-- 服務提供者.利用Ribbon實現。 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
啓動類新增client掃描@EnableDiscoveryClient以及模板注入
/**
* Hello world!
*
*/
@SpringBootApplication
//因爲多模塊中其他配置模塊也需要spring組件功能,所以發佈模塊需要加載其他模塊的內容.
@ComponentScan(basePackages = {"boot.**"})
//服務發現
@EnableDiscoveryClient
//mybatis掃描
@MapperScan("boot.dao.**")
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
/**
* Spring提供的用於訪問Rest服務的客戶端
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
新增application.yml配置
eureka:
client:
service-url:
defaultZone: http://eureka1:8762/eureka/, http://eureka2:8763/eureka/,http://eureka3:8764/eureka/
instance:
appname: ribbon-client
server:
port: 8092
spring:
application:
name: ribbon-client
在ribbon中新建一個controller作爲代理
TestRibbonApi:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping(value = "/test")
public class TestRibbonApi {
/**
* 注入RestTemplate
*/
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/get" ,method = RequestMethod.GET)
public String testGetNameOfBlog(){
String url="http://ONE-MILLION/one-million-dev/redisTest";
return restTemplate.getForObject(url,String.class);
}
}
訪問rest/get時,真正訪問的是ONE-MILLION集羣中one-million-dev/redisTest具體服務
redisTest,開啓兩個端口作爲集羣:
8898端口
@GetMapping("/redisTest")
public String redisTest() {
MDC.clear();
MDC.put("uuid", StringUtils.getUUID());
if (StringUtils.isEmpty(redisService.getNew("hello"))) {
redisService.setNew("hello", "world world world");
}
System.out.println(new Gson().toJson(redisSetting));
logger.info("hello-------:"+redisService.getNew("hello"));
logger.info("hello-------:"+redisService.getNew("hello"));
return redisService.getNew("hello")+" new-----------";
}
redisTest:
8896端口
@GetMapping("/redisTest")
public String redisTest() {
MDC.clear();
MDC.put("uuid", StringUtils.getUUID());
if (StringUtils.isEmpty(redisService.getNew("hello"))) {
redisService.setNew("hello", "world world world");
}
System.out.println(new Gson().toJson(redisSetting));
logger.info("hello-------:"+redisService.getNew("hello"));
logger.info("hello-------:"+redisService.getNew("hello"));
return redisService.getNew("hello")+" old-----------";
}
根據ip訪問具體服務節點:
http://localhost:8898/one-million-dev/redisTest 返回 world new-----------
http://localhost:8896/one-million-dev/redisTest 返回 world old----------
訪問ribbon部署的端口號8092:http://localhost:8092/test/get 返回爲world new-----------或者world old----------交替出現