前面我们了解了服务调用Rest和服务注册中心Eureka。现在我们来了解微服务架构springcloud技术栈之Ribbon负载均衡器。
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
添加以上Eureka-client客户端依赖时,工程会自动引入Ribbon相关的依赖
server:
port: 80
eureka:
client:
registerWithEureka: false # 服务注册,false表示不将本消费者注册到 Eureka 服务器
fetchRegistry: true # 服务发现,true从 Eureka 服务器中获取注册信息
serviceUrl:
defaultZone:
http://eureka6001.com:6001/eureka/,http://eureka6002.com:6002/eureka/
package com.mengxuegu.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* 自定义配置类,
* @Auther: xiaomingjun
*/
@Configuration
public class ConfigBean {
//@LoadBalanced表示这个RestTemplate开启负载均衡,在调用服务提供者的接口时,
//可使用 服务名称 替代真实IP地址。服务名称 就是服务提供者在application.yml中
//配置的spring.application.name属性的值。
@LoadBalanced
@Bean // 向容器中添加 RestTemplate 组件,直接通过此组件可调用 REST 接口
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
package com.mengxuegu.springcloud.controller;
import com.mengxuegu.springcloud.entities.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Auther: xiaomingjun
*/
@RestController
public class ProductController_Consumer {
//private static final String REST_URL_PREFIX = "http://localhost:8001";
//修改为Eureka注册中心的地址
private static final String REST_URL_PREFIX = "http://MICROSERVICE-PRODUCT";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/consumer/product/add")
public boolean add(Product product) {
return restTemplate.postForObject(REST_URL_PREFIX + "/product/add", product,Boolean.class);
}
@RequestMapping(value = "/consumer/product/get/{id}")
public Product get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/product/get/" + id,Product.class);
}
@RequestMapping(value = "/consumer/product/list")
public List list() {
return restTemplate.getForObject(REST_URL_PREFIX + "/product/list",List.class);
}
}
package com.mengxuegu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Auther:xiaomingjun
*/
@EnableEurekaClient //向服务注册中心进行注册
@SpringBootApplication
public class MicroserviceProductConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(MicroserviceProductConsumer_80.class, args);
}
}
测试:
启动2个Eureka集群,再启动microservice-cloud-03-provider-product-8001服务提供者工程兵注册进Eureka
接着启动microservice-cloud-04-consumer-product-80服务消费者工程
访问: http://localhost/consumer/product/get/1
http://localhost/consumer/product/list
http://localhost/consumer/product/add?product_name=spring
通过以上测试,我们发现Ribbon和Eureka整合之后,消费者Consumer可以直接调用提供者服务,而不用再关心地址和端口号
com.mengxuegu.springcloud
microservice-cloud-02-api
${project.version}
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
org.springframework.boot
spring-boot-starter-test
junit
junit
mysql
mysql-connector-java
com.alibaba
druid
DROP DATABASE IF EXISTS springcloud_db02;
CREATE DATABASE springcloud_db02 CHARACTER SET UTF8;
USE springcloud_db02;
CREATE TABLE product
(
pid BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(50),
db_source VARCHAR(50)
);
INSERT INTO product(product_name,db_source) VALUES('格力空调',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('海尔冰箱',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('小短裙',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('羽绒服',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('韩版休闲鞋',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('高贵鞋',DATABASE());
SELECT * FROM product;
server:
port: 8002 # 服务端口
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.mengxuegu.springcloud.entities # 所有Entity别名类所在包
mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservice-product #这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动包
url: jdbc:mysql://127.0.0.1:3306/springcloud_db02?serverTimezone=GMT%2B8 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 150 # 等待连接获取的最大超时时间
eureka:
client:
registerWithEureka: true # 服务注册开关
fetchRegistry: true # 服务发现开关
serviceUrl: # 客户端(服务提供者)注册到哪一个Eureka Server服务注册中心,多个用逗号分隔
# 单机版 Eureka 服务注册中心
#defaultZone: http://localhost:6001/eureka
# 集群版 Eureka 服务注册中心
defaultZone:
http://eureka6001.com:6001/eureka,http://eureka6002.com:6002/eureka
instance:
instanceId: ${spring.application.name}:${server.port} # 指定实例ID,就不会显示主机名了
preferIpAddress: true #访问路径可以显示IP地址
package com.mengxuegu.springcloud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Auther:xiaomingjun
*/
@EnableEurekaClient //本服务启动后会自动注册进Eureka服务器中
@MapperScan("com.mengxuegu.springcloud.mapper") //扫描包下面所有Mapper接口
@SpringBootApplication
public class ProductProvider_8002 {
public static void main(String[] args) {
SpringApplication.run(MicroserviceProductProvider_8002.class, args);
}
}
测试:
启动2个Eureka集群
microservice-cloud-05-eureka-6001、 microservice-cloud-05-eureka-6002
启动2个商品提供者 微服务,并各自测试通过
http://localhost:8001/product/list
http://localhost:8002/product/list
启动服务消费者工程
microservice-cloud-04-consumer-product-80
客户端通过Ribbon完成负载均衡并访问上一步的Product微服务
http://localhost/consumer/product/list
注意观察看到返回的数据库名字,各不相同,负载均衡实现