Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,均可以用Spring Boot的開發風格作到一鍵啓動和部署。Spring Cloud並無重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,經過Spring Boot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包。如今咱們一一體驗一下這些組件的功能做用。首先從服務提供者和消費者開始。javascript
microcloud-api 模塊,做爲公共的信息導入配置模塊;html
microcloud-provider-product:做爲服務提供者;java
microcloud-consumer:做爲微服務調用的客戶端使用;mysql
新建一個maven父項目:microcloudnginx
其中pom文件以下git
<?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>hdk</groupId> <artifactId>springcloud</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>microcloudapi</module> <module>microcloudproviderproduct</module> <module>microcloudconsumer</module> </modules> <properties> <jdk.version>1.8</jdk.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <!-- 進行SpringCloud依賴包的導入處理 --> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <!-- SpringCloud離不開SpringBoot,因此必需要配置此依賴包 --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.2.RELEASE</version> <type>pom</type> <scope>import</scope> </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>hdk</groupId> <artifactId>microcloud-api</artifactId> <version>1.0.0</version> </dependency> </dependencies> </dependencyManagement> <build> <finalName>microcloud</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${jdk.version}</source><!-- 源代碼使用的開發版本 --> <target>${jdk.version}</target><!-- 須要生成的目標class文件的編譯版本 --> </configuration> </plugin> </plugins> </build> </project>
【microcloud-api】模塊,創建一個公共模板,這模塊的主要功能是提供公共處理的工具類,實體,接口等。github
pom文件以下:web
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-api</artifactId> <version>1.0.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project> 因爲實體對象無論是服務提供放仍是消費者都須要用到,實體對象先建立到api模塊中,建立一個Product實體 package hdk.vo; import java.io.Serializable; public class Product implements Serializable { private Long productId; private String productName; private String productDesc; public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public Long getProductId() { return productId; } public void setProductId(Long productId) { this.productId = productId; } @Override public String toString() { return "Product{" + "productId=" + productId + ", productName='" + productName + '\'' + ", productDesc='" + productDesc + '\'' + '}'; } }
因爲實體對象無論是服務提供放仍是消費者都須要用到,實體對象先建立到api模塊中,建立一個Product實體spring
package cn.hdk.vo; import java.io.Serializable; public class Product implements Serializable { private Long productId; private String productName; private String productDesc; public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public Long getProductId() { return productId; } public void setProductId(Long productId) { this.productId = productId; } @Override public String toString() { return "Product{" + "productId=" + productId + ", productName='" + productName + '\'' + ", productDesc='" + productDesc + '\'' + '}'; } }
建立一個Product Rest提供者的項目模塊,這個模塊對應的數據庫腳本以下sql
CREATE DATABASE springcloud CHARACTER SET UTF8 ; USE springcloud ; CREATE TABLE product ( prodcutId BIGINT AUTO_INCREMENT , productName VARCHAR(50) , productDesc VARCHAR(50) , CONSTRAINT pk_prodcut_id PRIMARY KEY(prodcutId) ) ; INSERT INTO product(productName,productDesc) VALUES ('電子鎖骨',database()) ; INSERT INTO product(productName,productDesc) VALUES ('Springboot',database()) ; INSERT INTO product(productName,productDesc) VALUES ('水錶',database()) ; INSERT INTO product(productName,productDesc) VALUES ('門禁',database()) ; INSERT INTO product(productName,productDesc) VALUES ('攝像頭',database()) ;
【microcloud-provider-product】模塊繼續使用mybaits對數據庫進行操做,pom文件以下
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <version>1.0.0</version> <artifactId>microcloud-provider-product</artifactId> <dependencies> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-api</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
【microcloud-provider-product】建立一個ProductMapper對數據庫的操做接口,這個接口方法特別簡單
package hdk.mapper; import hdk.vo.Product; import java.util.List; public interface ProductMapper { boolean create(Product product); public Product findById(Long id); public List<Product> findAll(); }
【microcloud-provider-product】新增修改application.yml文件,追加對mybatis以及數據庫的支持
server: port: 8080 mybatis: mapper-locations: # 全部的mapper映射文件 - classpath:mapping/*.xml spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置當前要使用的數據源的操做類型 driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驅動程序類 url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=GMT%2B8 # 數據庫鏈接地址 username: root # 數據庫用戶名 password: 111111% # 數據庫鏈接密碼 logging: level: hdk.mapper: debug
【microcloud-provider-product】建立修改src/main/resources/mapping/ProductMapper.xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="hdk.mapper.ProductMapper"> <select id="findById" resultType="cn.hdk.vo.Product" parameterType="long"> select productId,productName,productDesc from product WHERE productId=#{id} ; </select> <select id="findAll" resultType="cn.hdk.vo.Product"> SELECT productId,productName,productDesc from product; </select> <insert id="create" parameterType="cn.hdk.vo.Product"> INSERT INTO product(productName,productDesc) VALUES (#{productName},database()) ; </insert> </mapper>
【microcloud-provider-product】創建IProductService接口,並建立相關實現類
package hdk.service; import hdk.vo.Product; import java.util.List; public interface IProductService { Product get(long id); boolean add(Product product); List<Product> list(); } package hdk.service.impl; import hdk.mapper.ProductMapper; import hdk.service.IProductService; import hdk.vo.Product; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; @Service public class ProductServiceImpl implements IProductService { @Resource private ProductMapper productMapper; @Override public Product get(long id) { return productMapper.findById(id); } @Override public boolean add(Product product) { return productMapper.create(product); } @Override public List<Product> list() { return productMapper.findAll(); } }
【microcloud-provider-product】 定義主程序類,並定義好mapper掃描包
package hdk; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("hdk.mapper") public class ProductApp{ public static void main(String[] args) { SpringApplication.run(ProductApp.class,args); } }
【microcloud-provider-product】編寫單元測試
package hdk; import hdk.service.IProductService; import hdk.vo.Product; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; @SpringBootTest(classes = ProductApp.class) @RunWith(SpringRunner.class) public class ProductServiceTest { @Resource private IProductService iProductService; @Test public void testGet() { System.out.println(iProductService.get(1)); } @Test public void testAdd() { Product dept = new Product() ; dept.setProductName("lison-" + System.currentTimeMillis()); System.out.println(iProductService.add(dept)); } @Test public void testList() { System.out.println(iProductService.list()); } }
【microcloud-provider-product】創建ProductController創建一個Rest服務類
package hdk.controller; import hdk.service.IProductService; import hdk.vo.Product; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController @RequestMapping("/prodcut") public class ProductController { @Resource private IProductService iProductService; @RequestMapping(value="/get/{id}") public Object get(@PathVariable("id") long id) { return this.iProductService.get(id) ; } @RequestMapping(value="/add") public Object add(@RequestBody Product product) { return this.iProductService.add(product) ; } @RequestMapping(value="/list") public Object list() { return this.iProductService.list() ; } }
瀏覽器訪問:
調用get請求:localhost:8080/product/get/1
調用list請求:localhost:8080/product/list
建立一個maven新模塊:【microcloud-consumer】這個模塊做爲服務的消費方,調用前面的product服務
【microcloud-consumer】修改pom文件,pom文件內容以下
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-consumer</artifactId> <dependencies> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
【microcloud-consumer】修改application.yml配置文件
server:
port: 80
【microcloud-consumer】建立Rest配置類,在這須要調用Rest服務,通常須要用到RestTemplate類對象
package hdk.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
【microcloud-consumer】新建一個controller,負責使用RestTemplate調用遠程的product服務
package hdk.controller; import hdk.vo.Product; 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.util.List; @RestController @RequestMapping("/consumer") public class ConsumerProductController { public static final String PRODUCT_GET_URL = "http://localhost:8080/prodcut/get/"; public static final String PRODUCT_LIST_URL="http://localhost:8080/prodcut/list/"; public static final String PRODUCT_ADD_URL = "http://localhost:8080/prodcut/add/"; @Resource private RestTemplate restTemplate; @RequestMapping("/product/get") public Object getProduct(long id) { Product product = restTemplate.getForObject(PRODUCT_GET_URL + id, Product.class); return product; } @RequestMapping("/product/list") public Object listProduct() { List<Product> list = restTemplate.getForObject(PRODUCT_LIST_URL, List.class); return list; } @RequestMapping("/product/add") public Object addPorduct(Product product) { Boolean result = restTemplate.postForObject(PRODUCT_ADD_URL, product, Boolean.class); return result; } }
【microcloud-consumer】編寫啓動類
package hdk; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
調用測試
新增:http://localhost/consumer/product/add?productName=lison
列表查詢:http://localhost/consumer/product/list
得到單個數據:http://localhost/consumer/product/get?id=1
前面使用了RestTemplate進行遠程接口調用,但要注意,這些Rest服務最終均可能暴露在公網的,任何人均可能調用,若是你的Rest服務屬於一些私密信息,這樣會致使信息的泄露。
若是想進行安全方面的處理,首先要在服務的提供方上進行處理。
【microcloud-provider-product】修改pom文件,追加 SpringSecurity 相關依賴信息
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
【microcloud-provider-product】修改application.yml配置文件,進行安全的用戶名配置
spring: security: user: name: admin # 認證用戶名 password: hdk # 認證密碼 roles: - USER # 受權角色
在項目中訪問rest接口,localhost:8080/product/list,這個時候會要求先輸入用戶名以及密碼才能容許訪問
【microcloud-consumer】 修改RestConfig配置類,在裏面添加 HttpHeaders 的配置信息
package cn.hdk.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Base64; @Configuration public class RestConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public HttpHeaders getHeaders() { // 要進行一個Http頭信息配置 HttpHeaders headers = new HttpHeaders(); // 定義一個HTTP的頭信息 String auth = "admin:hdk"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 String authHeader = "Basic " + new String(encodedAuth); headers.set("Authorization", authHeader); return headers; } }
【microcloud-consumer】 修改ConsumerProductController,在進行服務端調用的時候加上這個頭信息
package hdk.controller; import hdk.vo.Product; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; 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.util.List; @RestController @RequestMapping("/consumer") public class ConsumerProductController { public static final String PRODUCT_GET_URL = "http://localhost:8080/prodcut/get/"; public static final String PRODUCT_LIST_URL="http://localhost:8080/prodcut/list/"; public static final String PRODUCT_ADD_URL = "http://localhost:8080/prodcut/add/"; @Resource private RestTemplate restTemplate; @Resource private HttpHeaders httpHeaders; @RequestMapping("/product/get") public Object getProduct(long id) { Product product = restTemplate.exchange(PRODUCT_GET_URL + id,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), Product.class).getBody(); return product; } @RequestMapping("/product/list") public Object listProduct() { List<Product> list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), List.class).getBody(); return list; } @RequestMapping("/product/add") public Object addPorduct(Product product) { Boolean result = restTemplate.exchange(PRODUCT_ADD_URL, HttpMethod.POST,new HttpEntity<Object>(product,httpHeaders), Boolean.class).getBody(); return result; } }
調用測試
新增:http://localhost/consumer/product/add?productName=lison
列表查詢:http://localhost/consumer/product/list
得到單個數據:http://localhost/consumer/product/get?id=1
如今服務提供方只有一個Product服務,但真實的項目開發中必然有多個服務提供方,絕大多數狀況下,這些服務都會用到安全驗證,並且密碼也會同樣,若是每一個服務都單獨維護,每次密碼變更改動都會很大,因此應該單獨創建一個安全驗證的模塊
建立一個microcloud-security模塊,修改其pom文件以下
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <version>1.0.0</version> <artifactId>microcloud-security</artifactId> <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.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
【springcloud】修改父工程pom文件,把相應的版本依賴加到裏面
<dependency> <groupId>hdk</groupId> <artifactId>microcloud-api</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-security</artifactId> <version>1.0.0</version> </dependency>
【microcloud-security】創建一個統一的安全配置類,這個類負責用戶以及密碼相關的配置
package hdk.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("root").password(new BCryptPasswordEncoder().encode("hdk")).roles("USER"). and().withUser("admin").password(new BCryptPasswordEncoder().encode("hdk")).roles("USER", "ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic().and().authorizeRequests().anyRequest() .fullyAuthenticated(); http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } }
【microcloud-provider-product】修改pom文件,刪除spring-boot-starter-security的依賴信息,並加入本身定義的microcloud-security依賴
<!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-security</artifactId>--> <!--</dependency>--> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-security</artifactId> </dependency>
【microcloud-provider-product】修改application.yml,刪除與安全相關的配置項。
# security: # user: # roles: # - USER # 受權角色 # name: root # password: hdk
調用測試
新增:http://localhost/consumer/product/add?productName=lison
列表查詢:http://localhost/consumer/product/list
得到單個數據:http://localhost/consumer/product/get?id=1
新建一個microcloud-eureka模塊,這模塊作的事情很是簡單,既啓動Eureka的服務端,pom文件以下
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-eureka</artifactId> <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.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
【microcloud-eureka】修改application.yml文件,在裏面配置eureka相關信息
server: port: 7001 eureka: instance: # eureak實例定義 hostname: localhost # 定義 Eureka 實例所在的主機名稱
【microcloud-eureka】新增Eureka啓動類,增長Eureka服務端註解
package hdk; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApp { public static void main(String[] args) { SpringApplication.run(EurekaApp.class,args); } }
在瀏覽器上執行
http://localhost:7001/
【microcloud-provider-product】修改pom文件,增長eureka客戶端相關信息
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
【microcloud-provider-product】修改application.yml配置文件,在者個文件中定義要註冊的eureka服務的地址
eureka: client: # 客戶端進行Eureka註冊的配置 service-url: defaultZone: http://localhost:7001/eureka
【microcloud-provider-product】修改啓動類,在這個類上增長eureka客戶端的註解信息
package hdk; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @MapperScan("cn.hdk.mapper") @EnableEurekaClient public class ProductApp{ public static void main(String[] args) { SpringApplication.run(ProductApp.class,args); } }
啓動後發現Application的名字是UNKNOWN,爲此應該爲這單獨取一個名字
【microcloud-provider-product】修改application.yml配置文件,爲這個微服務起一個名字
spring: application: name: microcloud-provider-product
【microcloud-provider-product】修改application.yml配置文件,追加主機名稱的顯示:
eureka: client: # 客戶端進行Eureka註冊的配置 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microcloud-provider-product
【microcloud-provider-product】修改application.yml配置文件
eureka: client: # 客戶端進行Eureka註冊的配置 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microcloud-provider-product prefer-ip-address: true #顯示IP
【microcloud-provider-product】若是想看狀態信息須要增長actuator模塊,這一塊的內容已經在講springboot的時候講過,修改pom文件,增長
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
【microcloud-provider-product】修改application.yml文件,追加info相關配置
info: app.name: microcloud-provider-product company.name: hdk build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$
注意:因爲在yml文件中使用了$,這個時候啓動是會報錯的,所以還須要一個maven-resources-plugin插件的支持
【microcloud】在父工程增長插件,修改pom文件
<build> <finalName>microcloud</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimiter>$</delimiter> </delimiters> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${jdk.version}</source><!-- 源代碼使用的開發版本 --> <target>${jdk.version}</target><!-- 須要生成的目標class文件的編譯版本 --> </configuration> </plugin> </plugins> </build>
啓動後:
另外在關閉【microcloud-provider-product】項目後,刷新eureka發現項目還在,隔一段時間後會發現
這其實就是觸發了安全模式
【microcloud-eureka】設置服務的清理間隔時間,修改application.yml文件
server: port: 7001 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false instance: # eureak實例定義 hostname: localhost # 定義 Eureka 實例所在的主機名稱
【microcloud-provider-product】修改application.yml配置
eureka: client: # 客戶端進行Eureka註冊的配置 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microcloud-provider-product prefer-ip-address: true lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒) lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒)
因爲全部的服務都註冊到了 Eureka 之中
這樣若是配置了「lease-expiration-duration-in-seconds」此選項,
表示距離上一次發送心跳以後等待下一次發送心跳的間隔時間,若是超過了此間隔時間,則認爲該微服務已經宕機了。
【microcloud-provider-product】對於註冊到 Eureka 上的服務,能夠經過發現服務來獲取一些服務信息,修改ProductController,增長一個方法
package hdk.controller; import cn.hdk.service.IProductService; import cn.hdk.vo.Product; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController @RequestMapping("/prodcut") public class ProductController { @Resource private IProductService iProductService; @Resource private DiscoveryClient client ; // 進行Eureka的發現服務 @RequestMapping(value="/get/{id}") public Object get(@PathVariable("id") long id) { return this.iProductService.get(id) ; } @RequestMapping(value="/add") public Object add(@RequestBody Product product) { return this.iProductService.add(product) ; } @RequestMapping(value="/list") public Object list() { return this.iProductService.list() ; } @RequestMapping("/discover") public Object discover() { // 直接返回發現服務信息 return this.client ; } }
【microcloud-provider-product】修改ProductApp, 在主程序中啓用發現服務項
package hdk; import org.mybatis.spring.annotation.MapperScan; 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; @SpringBootApplication @MapperScan("cn.hdk.mapper") @EnableEurekaClient @EnableDiscoveryClient public class ProductApp{ public static void main(String[] args) { SpringApplication.run(ProductApp.class,args); } }
訪問:localhost:8080/prodcut/discover
通常狀況下Eureka 和服務的提供註冊者都會在一個內網環境中,但免不了在某些項目中須要讓其餘外網的服務註冊到Eureka,這個時候就有必要讓Eureka增長一套安全認證機制了,讓全部服務提供者經過安全認證後才能註冊進來
【microcloud-eureka】修改pom文件,引入SpringSecurity的依賴包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
【microcloud-eureka】 修改application.yml文件,增長用戶、密碼驗證
server: port: 7001 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: defaultZone: http://admin:hdk@localhost:7001/eureka instance: # eureak實例定義 hostname: localhost # 定義 Eureka 實例所在的主機名稱 spring: security: user: name: admin password: hdk
【microcloud-provider-product】修改application.yml文件,增長驗證信息
eureka: client: # 客戶端進行Eureka註冊的配置 service-url: defaultZone: http://admin:hdk@localhost:7001/eureka instance: instance-id: microcloud-provider-product prefer-ip-address: true lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒) lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒)
【microcloud-eureka】新增配置類EurekaSecurityConfig,重寫configure方法,把csrf劫持關閉
package hdk; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class EurekaSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); super.configure(http); } }
如今的Eureka仍是單節點的狀況,若是Eureka出現了錯誤,將會致使整個集羣沒法繼續使用,這個時候就須要考慮Eureka的高可用了。
如今須要3個eureka ,每一個eureka都須要配置hostname,全部先修改hosts文件內容以下
127.0.0.1 eureka1
127.0.0.1 eureka2
127.0.0.1 eureka3
【microcloud-eureka】爲了方便操做,講microcloud-eureka項目複製兩份,分別複製爲【microcloud-eureka2】、 【microcloud-eureka2】
【microcloud-eureka】修改application.yml配置文件,修改端口以及註冊位置
server: port: 7001 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka1 # 定義 Eureka 實例所在的主機名稱 spring: security: user: name: admin password: hdk
【microcloud-eureka2】修改application.yml配置文件
server: port: 7002 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka2 # 定義 Eureka 實例所在的主機名稱 spring: security: user: name: admin password: hdk
【microcloud-eureka3】修改application.yml配置文件
server: port: 7003 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka3 # 定義 Eureka 實例所在的主機名稱 spring: security: user: name: admin password: hdk
啓動eureka,eureka2,eureka3,進入服務的後臺查看副本
登錄http://localhost:7001/
【microcloud-provider-product】修改application.yml配置文件,配置多臺enreka的註冊
server: port: 8080 mybatis: mapper-locations: # 全部的mapper映射文件 - classpath:mapping/*.xml spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置當前要使用的數據源的操做類型 driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驅動程序類 url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=GMT%2B8 # 數據庫鏈接地址 username: root # 數據庫用戶名 password: root1234% # 數據庫鏈接密碼 application: name: microcloud-provider-product # security: # user: # roles: # - USER # 受權角色 # name: root # password: hdk logging: level: cn.hdk.mapper: debug eureka: client: # 客戶端進行Eureka註冊的配置 service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: instance-id: microcloud-provider-product prefer-ip-address: true lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒) lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒) info: app.name: microcloud-provider-product company.name: hdk build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$
在項目中,須要講Eureka發佈到具體服務器上進行執行,打包部署其實和springboot裏面講的大同小異和properties文件稍微有點不一樣,對於properties文件,不一樣的環境會有不一樣的配置文件好比application-dev.properties,application-test.properties,application-pro.properties等
但若是是yml文件,全部的的配置都再同一個yml文件中
【microcloud-eureka】修改application.yml文件
spring: profiles: active: - dev-7001 --- server: port: 7001 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka1 # 定義 Eureka 實例所在的主機名稱 spring: profiles: dev-7001 security: user: name: admin password: hdk application: name: microcloud-eureka --- server: port: 7002 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka2 # 定義 Eureka 實例所在的主機名稱 spring: profiles: dev-7002 security: user: name: admin password: hdk application: name: microcloud-eureka2 --- server: port: 7003 eureka: server: eviction-interval-timer-in-ms: 1000 #設置清理的間隔時間,然後這個時間使用的是毫秒單位(默認是60秒) enable-self-preservation: false #設置爲false表示關閉保護模式 client: fetch-registry: false register-with-eureka: false service-url: defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: # eureak實例定義 hostname: eureka3 # 定義 Eureka 實例所在的主機名稱 spring: profiles: dev-7003 security: user: name: admin password: hdk application: name: microcloud-eureka3
【microcloud-eureka】添加一個打包插件,修改pom文件
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-eureka</artifactId> <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.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </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-security</artifactId> </dependency> </dependencies> <build> <finalName>eureka-server</finalName> <plugins> <plugin> <!-- 該插件的主要功能是進行項目的打包發佈處理 --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- 設置程序執行的主類 --> <mainClass>cn.hdk.EurekaApp</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
【microcloud-eureka】 在pom文件所在目錄
mvn clean install package
接下來就能夠在項目的編譯目錄發現
eureka-server.jar 文件
採用默認的方式執行 eureka-server.jar那麼此時將運行在 7001 端口上:java -jar eureka-server.jar
運行其它的兩個 profile 配置:
· 運行「dev-7002」profile:java -jar eureka-server.jar --spring.profiles.active=dev-7002;
· 運行「dev-7003」profile:java -jar eureka-server.jar --spring.profiles.active=dev-7003
如今服務提供方已經能夠經過Eureka進行註冊了,但對於服務的消費者,目前並無處理,對於服務的消費方,也應該鏈接上eureka,進行服務的獲取,這個時候就應該使用Ribbon這個組件了
ribbon對應的pom文件以下
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
【microcloud-consumer】 修改pom文件,增長eureka的支持
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-consumer</artifactId> <dependencies> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project>
【microcloud-consumer】 修改RestConfig配置類,在獲取RestTemplate對象的時候加入Ribbon的配置信息
package cn.hdk.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Base64; @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public HttpHeaders getHeaders() { // 要進行一個Http頭信息配置 HttpHeaders headers = new HttpHeaders(); // 定義一個HTTP的頭信息 String auth = "root:hdk"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 String authHeader = "Basic " + new String(encodedAuth); headers.set("Authorization", authHeader); return headers; } }
【microcloud-consumer】 修改RestConfig配置類,在獲取RestTemplate對象的時候加入Ribbon的配置信息```
server: port: 80 eureka: client: register-with-eureka: false service-url: defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka
【microcloud-consumer】修改項目啓動類,增長Eureka客戶端的配置註解
package hdk; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
【microcloud-consumer】 修改ConsumerProductController控制器
如今在eureka中註冊的服務名稱都是大寫字母:
MICROCLOUD-PROVIDER-PRODUCT
package hdk.controller; import hdk.vo.Product; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; 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.util.List; @RestController @RequestMapping("/consumer") public class ConsumerProductController { public static final String PRODUCT_GET_URL = "http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/get/"; public static final String PRODUCT_LIST_URL="http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/list/"; public static final String PRODUCT_ADD_URL = "http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/add/"; @Resource private RestTemplate restTemplate; @Resource private HttpHeaders httpHeaders; @RequestMapping("/product/get") public Object getProduct(long id) { Product product = restTemplate.exchange(PRODUCT_GET_URL + id,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), Product.class).getBody(); return product; } @RequestMapping("/product/list") public Object listProduct() { List<Product> list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), List.class).getBody(); return list; } @RequestMapping("/product/add") public Object addPorduct(Product product) { Boolean result = restTemplate.exchange(PRODUCT_ADD_URL, HttpMethod.POST,new HttpEntity<Object>(product,httpHeaders), Boolean.class).getBody(); return result; } }
訪問地址:http://localhost/consumer/product/list
這個時候Ribbon與Eureka已經整合成功
經過上面的代碼發現咱們用到了一個註解@LoadBalanced,根據這名字大概就能知道Ribbon是能夠實現負載均衡的
【microcloud-provider-product】 複製兩份
分別爲【microcloud-provider-product2】與【microcloud-provider-product3】
【springcloud數據庫】複製兩份
分別爲【springcloud2數據庫】【springcloud3數據庫】 裏面分別執行spingcloud數據庫的腳本
【microcloud-provider-product2】修改application.yml文件以下
server: port: 8081 mybatis: mapper-locations: # 全部的mapper映射文件 - classpath:mapping/*.xml spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置當前要使用的數據源的操做類型 driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驅動程序類 url: jdbc:mysql://localhost:3306/springcloud2?serverTimezone=GMT%2B8 # 數據庫鏈接地址 username: root # 數據庫用戶名 password: root1234% # 數據庫鏈接密碼 application: name: microcloud-provider-product # security: # user: # roles: # - USER # 受權角色 # name: root # password: hdk logging: level: hdk.mapper: debug eureka: client: # 客戶端進行Eureka註冊的配置 service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: instance-id: microcloud-provider-product2 prefer-ip-address: true lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒) lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒) info: app.name: microcloud-provider-product2 company.name: hdk build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$
【microcloud-provider-product3】修改application.yml文件以下
server: port: 8082 mybatis: mapper-locations: # 全部的mapper映射文件 - classpath:mapping/*.xml spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置當前要使用的數據源的操做類型 driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驅動程序類 url: jdbc:mysql://localhost:3306/springcloud3?serverTimezone=GMT%2B8 # 數據庫鏈接地址 username: root # 數據庫用戶名 password: root1234% # 數據庫鏈接密碼 application: name: microcloud-provider-product # security: # user: # roles: # - USER # 受權角色 # name: root # password: hdk logging: level: cn.hdk.mapper: debug eureka: client: # 客戶端進行Eureka註冊的配置 service-url: #defaultZone: http://admin:hdk@localhost:7001/eureka defaultZone: http://admin:hdk@eureka1:7001/eureka,http://admin:hdk@eureka2:7002/eureka,http://admin:hdk@eureka3:7003/eureka instance: instance-id: microcloud-provider-product3 prefer-ip-address: true lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒) lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒) info: app.name: microcloud-provider-product3 company.name: hdk build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$
分別啓動3個服務提供方,訪問
http://localhost:8080/product/get/1
http://localhost:8081/product/get/1
http://localhost:8082/product/get/1
確認3個服務是能正確提供訪問的
【microcloud-consumer】啓動
訪問:http://localhost/consumer/product/list
前面已經使用Ribbon實現了路由,經過測試,也不難發現默認Ribbon使用的路由策略是輪詢,能夠看下源代碼BaseLoadBalancer
全局路由配置
這種負載均衡的策略其實也是能夠由用戶來修改的,若是想要去修改,可使用自定義的LoadBalance
【microcloud-consumer】 修改RestConfig
package hdk.config; import com.netflix.loadbalancer.IRule; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Base64; @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public HttpHeaders getHeaders() { // 要進行一個Http頭信息配置 HttpHeaders headers = new HttpHeaders(); // 定義一個HTTP的頭信息 String auth = "root:hdk"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 String authHeader = "Basic " + new String(encodedAuth); headers.set("Authorization", authHeader); return headers; } @Bean public IRule ribbonRule() { // 其中IRule就是全部規則的標準 return new com.netflix.loadbalancer.RandomRule(); // 隨機的訪問策略 } }
這個時候重啓測試發現,默認的路由規則已經變成了隨機
有時候,某個消費者可能須要訪問多個多個服務提供方,而但願每一個服務提供方提供的路由規則並不相同,這個時候就不能讓Spring掃描到IRULE,須要經過@RibbonClient 來指定服務於配置的關係
【microcloud-consumer】 修改RestConfig,刪除IRULE
package cn.hdk.config; import com.netflix.loadbalancer.IRule; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Base64; @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public HttpHeaders getHeaders() { // 要進行一個Http頭信息配置 HttpHeaders headers = new HttpHeaders(); // 定義一個HTTP的頭信息 String auth = "root:hdk"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 String authHeader = "Basic " + new String(encodedAuth); headers.set("Authorization", authHeader); return headers; } // @Bean // public IRule ribbonRule() { // 其中IRule就是全部規則的標準 // return new com.netflix.loadbalancer.RandomRule(); // 隨機的訪問策略 // } }
【microcloud-consumer】新增一個路由規則的配置類,注意這個類不該該放到SpringCloud掃描不到的位置,不然又回變成全局的IRULE,因此這個時候應該單獨使用一個新的包,着個包和啓動並不在同一個包下
package hdk.config; import com.netflix.loadbalancer.IRule; import org.springframework.context.annotation.Bean; public class RibbonConfig { @Bean public IRule ribbonRule() { // 其中IRule就是全部規則的標準 return new com.netflix.loadbalancer.RandomRule(); // 隨機的訪問策略 } }
【microcloud-consumer】 修改啓動類,使用@RibbonClient指定配置類
package hdk; import hdkconfig.RibbonConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.netflix.ribbon.RibbonClients; @SpringBootApplication @EnableEurekaClient @RibbonClient(name ="MICROCLOUD-PROVIDER-PRODUCT" ,configuration = RibbonConfig.class) public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
這裏的name 只服務的名稱,若是須要有多個服務提供方,這個時候可使用@RibbonClients進行配置
在服務的消費方,也是能夠獲取到服務提供方的具體信息
【microcloud-consumer】修改ConsumerProductController
package cn.hdk.controller; import cn.hdk.vo.Product; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; 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.util.List; @RestController @RequestMapping("/consumer") public class ConsumerProductController { public static final String PRODUCT_GET_URL = "http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/get/"; public static final String PRODUCT_LIST_URL="http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/list/"; public static final String PRODUCT_ADD_URL = "http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/add/"; @Resource private RestTemplate restTemplate; @Resource private HttpHeaders httpHeaders; @Resource private LoadBalancerClient loadBalancerClient; @RequestMapping("/product/get") public Object getProduct(long id) { Product product = restTemplate.exchange(PRODUCT_GET_URL + id,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), Product.class).getBody(); return product; } @RequestMapping("/product/list") public Object listProduct() { ServiceInstance serviceInstance = this.loadBalancerClient.choose("MICROCLOUD-PROVIDER-PRODUCT") ; System.out.println( "【*** ServiceInstance ***】host = " + serviceInstance.getHost() + "、port = " + serviceInstance.getPort() + "、serviceId = " + serviceInstance.getServiceId()); List<Product> list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), List.class).getBody(); return list; } @RequestMapping("/product/add") public Object addPorduct(Product product) { Boolean result = restTemplate.exchange(PRODUCT_ADD_URL, HttpMethod.POST,new HttpEntity<Object>(product,httpHeaders), Boolean.class).getBody(); return result; } }
以前所用Ribbon都是從Eureka中獲取服務並經過@LoadBalanced來實現負載均衡的,其實Ribbon也能夠脫離Eureka來使用
複製【microcloud-consumer】 成一個新的模塊【microcloud-consumer-ribbon】
【microcloud-consumer-ribbon】 修改pom文件,刪除eureka的依賴添加ribbon的依賴
<?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"> <parent> <artifactId>springcloud</artifactId> <groupId>hdk</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microcloud-consumer-ribbon</artifactId> <dependencies> <dependency> <groupId>hdk</groupId> <artifactId>microcloud-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--<dependency>--> <!--<groupId>org.springframework.cloud</groupId>--> <!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>--> <!--</dependency>--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies> </project>
【microcloud-consumer-ribbon】 修改application.yml配置文件
server: port: 80 ribbon: eureka: enabled: false MICROCLOUD-PROVIDER-PRODUCT: ribbon: listOfServers: http://localhost:8080,http://localhost:8081,http://localhost:8082
【microcloud-consumer-ribbon】 修改 RestConfig,刪除@LoadBalanced註解
package hdk.config; import com.netflix.loadbalancer.IRule; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Base64; @Configuration public class RestConfig { @Bean //@LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public HttpHeaders getHeaders() { // 要進行一個Http頭信息配置 HttpHeaders headers = new HttpHeaders(); // 定義一個HTTP的頭信息 String auth = "root:hdk"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 String authHeader = "Basic " + new String(encodedAuth); headers.set("Authorization", authHeader); return headers; } }
【microcloud-consumer-ribbon】修改ConsumerProductController,修改服務的調用URI
package hdk.controller; import cn.hdk.vo.Product; import cn.xiangxue.config.RibbonConfig; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; 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; @RestController @RequestMapping("/consumer") public class ConsumerProductController { public static final String PRODUCT_TOPIC = "MICROCLOUD-PROVIDER-PRODUCT"; @Resource private RestTemplate restTemplate; @Resource private HttpHeaders httpHeaders; @Resource private LoadBalancerClient loadBalancerClient; @RequestMapping("/product/list") public Object listProduct() { ServiceInstance serviceInstance = this.loadBalancerClient.choose(PRODUCT_TOPIC) ; System.out.println( "【*** ServiceInstance ***】host = " + serviceInstance.getHost() + "、port = " + serviceInstance.getPort() + "、serviceId = " + serviceInstance.getServiceId()); URI uri = URI.create(String.format("http://%s:%s/prodcut/list/" , serviceInstance.getHost(), serviceInstance.getPort())); List<Product> list = restTemplate.exchange(uri,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), List.class).getBody(); return list; } }
【microcloud-consumer-ribbon】啓動
訪問:http://localhost/consumer/product/list
前面已經學習了Ribbon,從Eureka獲取服務的實例在經過RestTemplate調用,並轉換成須要的對象
List
list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity