SpringCloud入門(eureka叢集和feign負載均衡)
什麼是springcloud?
這是spring官網對springcloud的介紹,大致意思就是:讓分散式系統簡單化。springcloud是建立在springboot之上的,也就是說他是需要依賴springboot的,因此學習springcloud首先就要了解springboot。在上一篇文章中有介紹到springboot。
這張圖說明了Spring Cloud是實施微服務的一系列套件,包括:服務註冊與發現、斷路器、服務狀態監控、配置管理、智慧路由、一次性令牌、全域性鎖、分散式會話管理、叢集狀態管理等。
下面就用IDEA搭建springcloud專案,來看看springcloud是如何整合這些元件。
搭建一個小型的springcloud專案
1.首先使用IDEA建立一個maven父工程,在pom.xml裡引入需要的jar包依賴,dependencyManagement用來管理jar包版本。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.9.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> </dependencies> </dependencyManagement>
2.然後建立子工程,首先建立一個provider工程,作為服務提供者。
右鍵選中父工程後new一個module,選擇maven就可以新建一個子工程了。
每建立一個新工程首先在pom.xml裡新增一些基礎的依賴。
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId><!--簡化javabean開發的jar,用註解的方式快速寫setter,getter,--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- actuator監控資訊完善 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId><!--eureka元件,後面沒帶server,即為客戶端client--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.9.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId><!--因該是將javabean變為配置檔案的jar包--> <optional>true</optional> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> </dependencies>
接著是編寫application.yml檔案
server:
port: 8001
spring:
application:
name: userapi #服務提供者名字,最終會顯示在eureka註冊中心的名字上,消費者通過這個名字找到服務並呼叫
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/testspringboot
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource #阿里巴巴的連線池
dbcp2:
max-total: 5 #最大維持連線數
min-idle: 5 #最小維持連線數
initial-size: 5 #初始化大小
max-wait-millis: 200 #等待連接獲取的最大等待時間
jpa:
hibernate:
ddl-auto: update #若資料庫中有表,則不建立。
show-sql: true
這裡的持久層框架使用的是SpringJPA,比較方便。
下面看下provide工程的目錄結構:
這裡provider8001代表是執行在8001埠上的服務提供者,後面要實現負載均衡還會建立多個服務提供者。
注意每個子工程都是一個獨立的springboot專案,因此每次新建完一個子module都要編寫springboot的啟動類。且啟動類的位置要包含其他所有的包,這樣這個啟動類在能在啟動時載入其他的需要放入spring容器中的bean,也就是對其他的包進行管理。
啟動類的通用寫法:
package com.tellhow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
public class ProviderApplicationRun8001 {
public static void main(String args[]){
SpringApplication.run(ProviderApplicationRun8001.class,args);
}
}
controller層程式碼:
package com.tellhow.controller;
import com.tellhow.repository.UserRepository;
import com.tellhow.entity.User;
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 java.util.List;
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private UserRepository userRepository;
@RequestMapping("test")
public String testProvider(){
return "Hello world";
}
@RequestMapping(value = "/users",method = RequestMethod.GET)
public List<User> getUsers(){
return userRepository.findAll();
}
@RequestMapping(value = "/user",method = RequestMethod.POST)
public boolean addUser(User user){
userRepository.save(user);
return true;
}
@RequestMapping(value = "/user",method = RequestMethod.PUT)
public boolean updateUser(User user){
userRepository.save(user);//如果主鍵存在則修改。
return true;
}
}
主要就是查詢資料庫裡的user列表,用來展示分散式呼叫的。持久層實現參見上一篇文章springboot整合jpa.
服務層就大致寫完了,寫完之後需要驗證一下是否正常可用,保證下寫消費者呼叫時能正常執行。
代表服務消費者可以正常啟動,下面就可以來寫消費者了。
1.與建立服務提供者同樣的操作,右鍵父工程,新建module,新增pom.xml依賴,編寫applicaton.yml檔案。編寫啟動類
applicaton.yml檔案裡只需要配置一個埠即可
server:
port: 80
啟動類:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = {"com.tellhow"})//指定啟動時掃描哪些需要管理的包,若將啟動類放在需要管理的包的上一級,則不需要此註解
public class ConsumerApplicationRun {
public static void main(String args[]){
SpringApplication.run(ConsumerApplicationRun.class,args);
}
}
conctroller層:通過RestTemplate呼叫服務提供者。由此可以看出,springcloud的分散式呼叫,是用rest來進行呼叫,不同於dubbo的RPC呼叫。
使用RestTemplate之前需要將其注入到spring容器中。
package com.tellhow.cfgBean;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RetryRule;
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;
@Configuration
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller:
package com.tellhow.controller;
import com.tellhow.beans.User;
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;
import java.util.List;
@RestController
public class UserController {
@Autowired
public RestTemplate restTemplate;
//public static final String PREX="http://localhost:8001";
public static final String PREX="http://USERAPI";//通過eureka上註冊的服務名來呼叫
@RequestMapping(value = "/consumer/user",method = RequestMethod.GET)
public List<User> getUsers(){
return restTemplate.getForObject(PREX+"/user/users",List.class);
}
}
然後先啟動服務提供者,再啟動服務消者,檢視結果,因為消費者工程的埠後是80,因此可以訪問地址可以省略埠
可以看到,成功呼叫。
加入eureka註冊中心
eureka是用來做服務註冊與發現的,也就是服務提供者將服務註冊到eureka註冊中心,然後消費者在註冊中心對服務進行呼叫消費。例如:想要開淘寶店需要先到淘寶平臺註冊店鋪,然後買家才可以在淘寶上找到該店鋪進行消費購買。
當然eureka還有很多功能:通過心跳檢測、健康檢查、客戶端快取等機制,保證了系統具有高可用和靈活性。
接下來建立一個eureka的子工程。建立module的過程不做贅述了。
pom.xml依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId><!--eureka 服務-->
</dependency>
</dependencies>
application.yml
server:
port: 7000
eureka:
instance:
hostname: eureka7000.com #eureka主機名
client:
register-with-eureka: false #表示不向註冊中心註冊自己
fetch-registry: false # 表示自己端就是註冊中心,職責就是維護服務例項,不需要檢索服務。
service-url:
defaultZone: http://eureka7001.com:7000/eureka/
啟動類:
package com.tellhow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //Eureka服務類,接受其他服務註冊進來。
public class EurekaApplicationRun {
public static void main(String args[]){
SpringApplication.run(EurekaApplicationRun.class,args);
}
}
如此,eureka註冊中心就建立完成了,之後需要在privoder工程裡新增向註冊中心註冊的相關東西。pom.xml新增eureka依賴
首先provider工程啟動類上添加註解:@EnableEurekaClient //啟動eureka客戶端
然後application.yml改為如下:
server:
port: 8001
spring:
application:
name: userapi #服務提供者名字,最終會顯示在eureka註冊中心的名字上,消費者通過這個名字找到服務並呼叫
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/testspringboot
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource #阿里巴巴的連線池
dbcp2:
max-total: 5 #最大維持連線數
min-idle: 5 #最小維持連線數
initial-size: 5 #初始化大小
max-wait-millis: 200 #等待連接獲取的最大等待時間
jpa:
hibernate:
ddl-auto: update #若資料庫中有表,則不建立。
show-sql: true
eureka:
client:
service-url:
defaultZone: http://eureka7000.com:7000/eureka #後面必須加個eureka 才能註冊上去。
instance:
instance-id: userAPI-8001 #註冊在eureka上的服務的例項的id
prefer-ip-address: true #顯示IP地址,方便查詢
info:
app.name: TestMaven
company.name: www.tellhow.com
.artifactId: $project.artifactId$
buibuildld.version: $project.version$
消費者工程裡也做相似的改動:啟動類添加註解:
@EnableEurekaClient //eureka是服務註冊中心,所以對用向服務中心註冊服務的,和向服務中心消費服務的,都是eureka客戶端
application.yml
server:
port: 80
eureka:
client:
register-with-eureka: false #消費者 不向服務端註冊
service-url:
defaultZone: http://eureka7000.com:7000/eureka/
修改完成後先啟動註冊中心工程,再啟動服務提供者工程,接著是消費者。
啟動完成後訪問:http://127.0.0.1:7000如果能出現一下畫面則代表eureak註冊中心工程建立成功。
今天先寫到這裡,明天繼續寫eureka高可用