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