二、服務註冊與發現
1、SpringCloud簡介
Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中涉及的配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式。
Spring Cloud包含了多個子專案(針對分散式系統中涉及的多個不同開源產品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud0 CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等專案。
2、服務治理
由於Spring Cloud為服務治理做了一層抽象介面,所以在Spring Cloud應用中可以支援多種不同的服務治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服務治理抽象層的作用下,我們可以無縫地切換服務治理實現,並且不影響任何其他的服務註冊、服務發現、服務呼叫等邏輯。
Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix專案下的服務治理模組。而Spring Cloud Netflix專案是Spring Cloud的子專案之一,主要內容是對Netflix公司一系列開源產品的包裝,它為Spring Boot應用提供了自配置的Netflix OSS整合。通過一些簡單的註解,開發者就可以快速的在應用中配置一下常用模組並構建龐大的分散式系統。它主要提供的模組包括:服務發現(Eureka),斷路器(Hystrix),智慧路由(Zuul),客戶端負載均衡(Ribbon)等。
建立“服務註冊中心”
建立一個maven工程,我們將其命名為microservice-spring-cloud,並在pom.xml檔案中引入如下的內容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR1</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>
然後我們在上面工程的基礎上,建立一個它的子模組。如果使用IDEA的話,直接在工程名右鍵,選擇New--->Module。子模組我們將其命名為microservice-discovery-eureka。子模組的pom.xml檔案中,我們需要引入如下的內容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies>
由於我們沒有使用Spring Initializr來建立工程,所以我們需要自己手動寫一個SpringBoot的啟動類。然後我們通過@EnableEurekaServer這個註解啟動一個服務註冊中心提供給其他應用進行對話,這一步非常簡單,只需要在SpringBoot的啟動類上新增這個註解即可。所以,整體程式碼如下:
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,只需要在application.yml
配置檔案中增加如下資訊:
security:
basic:
enabled: true
user:
name: admin
password: admin123
spring:
application:
name: microservice-discovery-eureka
server:
port: 1001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://admin:[email protected]:1001/eureka
為了與後續要進行註冊的服務區分,這裡將服務註冊中心的埠通過server.port屬性設定為1001。啟動工程後,訪問:http://localhost:1001/,輸入配置檔案中配置的賬號和密碼,可以看到下面的頁面,其中還沒有發現任何服務。
建立“服務提供方”
同樣在父工程下,新建一個子模組,新的子模組我們命名為microservice-provider-user,建立完成後,我們在pom.xml檔案中,引入如下所示的內容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!--監控系統健康情況的工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
可以看到我們在pom檔案中,引入了JPA模組、web模組、H2資料庫,引入這些座標是為我們的後續的演示做準備。除此之外,還有spring-cloud-starter-eureka這個座標。
在當前這個新建立的子模組中,我們在resources目錄下,建立一個schema.sql檔案和data.sql檔案,schema.sql檔案用於建立一個表,data.sql檔案用於給表中插入一些測試資料。
schema.sql
drop table user if exists; create table user( id bigint generated by default as identity , username varchar(40) , name varchar(40) , age int(3), balance decimal (10,2), primary key(id) );
data.sql
insert into user(id,username,name,age,balance) values (1,'user1','張三',18,100.00); insert into user(id,username,name,age,balance) values (2,'user2','李四',19,101.00); insert into user(id,username,name,age,balance) values (3,'user3','王五',20,102.00); insert into user(id,username,name,age,balance) values (4,'user4','週六',21,103.00);
application.yml
server:
port: 2001
spring:
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
datasource:
platform: h2
schema: classpath:schema.sql
data: classpath:data.sql
application:
name: microservice-provider-user
eureka:
client:
healthcheck:
enabled: true
serviceUrl:
defaultZone: http://admin:[email protected]:1001/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
通過spring.application.name
屬性,我們可以指定微服務的名稱後續在呼叫的時候只需要使用該名稱就可以進行服務的訪問。eureka.client.serviceUrl.defaultZone
屬性對應服務註冊中心的配置內容,指定服務註冊中心的位置。為了在本機上測試區分服務提供方和服務註冊中心,使用server.port
屬性設定不同的埠。
接下來,開始編碼工作。
User實體類
package cn.zhuangxp.entity; import javax.persistence.*; import java.io.Serializable; import java.math.BigDecimal; @Entity public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column private String username; @Column private String name; @Column private short age; @Column private BigDecimal balance; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getName() { return name; } public void setName(String name) { this.name = name; } public short getAge() { return age; } public void setAge(short age) { this.age = age; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } }
UserDao介面
public interface UserDao extends JpaRepository<User,Long> { }
UserController
@RestController public class UserController { @Autowired private UserDao userDao; @GetMapping("/getUser/{id}") public User getUserById(@PathVariable("id") Long id){ User user = userDao.findOne(id); return user; } }
最後使我們的啟動類MainAppProvider
@SpringBootApplication @EnableEurekaClient public class MainAppProvider { public static void main(String[] args) { SpringApplication.run(MainAppProvider.class, args); } }
@EnableEurekaClient註解能啟用Eureka中的DiscoveryClient實現,這樣才能實現Controller中對服務資訊的輸出。
上述工作完成,我們就可以啟動我們的工程了。啟動後,可以在註冊中心看到我們的工程。
我們繼續訪問這個模組提供的介面,開啟瀏覽器,輸入http://localhost:2001/getUser/1,可以看到瀏覽器成功為我們響應了資料