spring cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端 负载均衡的工具
简单的说 Ribbon 是Netflix 发布的开源的项目 主要功能就是提供客户端的软件负载均衡算法 将Netflix的中间层服务连接在一起 Ribbon 客户组件提供一系列完善的配置项如 连接超时 重试等 简单的说就是在配置 文件中列出 Load Balancer (简称 LB) 后面所有的机器 Ribbon 会自动帮助你基于某种规则( 如 简单轮询,随机连接)去连接这些机器。我们也很容易使用Ribbon 实现自定义负载均衡算法
LB即负载均衡(Load Balance)在未付或分布式集群中经常用一种应用、负载均衡简单的说就是将 用户的请求平摊的分配到多个服务上 从而达到系统的HA(高可用)、常见的有 Nginx Lvs 硬件F5等 相应的中间件 比如 dubbo和springcloud中均 提供了负载均衡,springcloud 的负载均衡算法可以自定义
集中式 LB
即在服务的消费方和提供方之间 使用 独立的LB设施(可以是硬件 例如F5 也可以是软件 如nginx)由该设施负责访问请求通过某种策略转发至服务的提供方
进程内LB
将LB 逻辑集成到 消费方 消费方从服务注册中心 获知有哪些地址可用,然后自己再从这些地址选出一个合适的服务器 Ribbon就是属于进程内LB 它只是一个类库, 集成与消费方的进程 消费方通过他来获取到服务提供方的地址
搭建(消费者8084)
pom文件
依赖
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-ribbon
org.springframework.cloud
spring-cloud-starter-config
server:
port: 8084
eureka:
client: #客户端注册进eureka服务列表内
register-with-eureka: false # 自己不能注册
service-url:
defaultZone: http://euerka7001.com:7001/eureka/,http://euerka7002.com:7002/eureka/,http://euerka7003.com:7003/eureka/
# 现在是集群
现在的消费端
消费端的RestTemplate上添加注解
@LoadBalanced//开启负载均衡 Ribbon实现了一套客户端 负载均衡的工具
package com.xxx.cfgbeans;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration //相当与配置 文件application.xml
public class ConfigBean {
@Bean
@LoadBalanced//开启负载均衡 Ribbon实现了一套客户端 负载均衡的工具
public RestTemplate geRestTemplate() {
return new RestTemplate();
}
}
private static final String REST_URL_PREFIX="http://MICROSERVICECLOUD-DEPT";
MICROSERVICECLOUD-DEPT 是你注册到 Eureka的服务名
package com.xxx.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.xxx.user.User;
@Controller
public class UserControllerConsumer {
//定义提供者的http://.........
private static final String REST_URL_PREFIX="http://MICROSERVICECLOUD-DEPT";
@Autowired
private RestTemplate restTemplate; //RestTemplate提供了很多的便捷访问远程Http服务的方法 是一种简洁的访问restfuiA模板类。
//是Spring提供的用于 访问 REst服务的 客户端模板工具类
/**
* 消费者 查询
* @return
*/
/*使用 使用restTemplate访问restful接口非常的简单 (url, requestMap,
ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。*/
@RequestMapping(value="/tt/user/list", method = RequestMethod.GET)
@ResponseBody
public String list(ModelMap map) {
//定义的http+"提供者的方法",类型.class 应为我的提供者方法是 String 所以这里也是String
return restTemplate.getForObject(REST_URL_PREFIX+"/list/user",String.class);
}
// 测试@EnableDiscoveryClient,消费端可以调用服务发现
@RequestMapping(value = "/tt/dept/discovery")
@ResponseBody
public Object discovery()
{
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
}
}
package com.xxx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.filters.discovery.PatternServiceRouteMapper;
@SpringBootApplication
@EnableEurekaClient
public class UserConsumerApp {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApp.class, args);
}
}
现在 就时候测试 一下 访问 微服务 的真实名字 是否可以
因为我 是Eureka集群所以 启动3个 集群的项目*(7001,7002,7003) 在启动我的 提供者(8083) 在启动我的消费者(8084) 所以要启动5个 服务
打开 页面 访问
见下图 项目是完全可以访问的
首先建立多个提供者
2)创建啊8082
还是在父级上右击创建maven Module
3个pom 文件都是一样的 就是体现 有多个 提供者 更好的理解负载均衡
com.xxx
microservicecloud-api
${project.version}
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-config
junit
junit
mysql
mysql-connector-java
runtime
com.alibaba
druid
ch.qos.logback
logback-core
org.mybatis.spring.boot
mybatis-spring-boot-starter
org.springframework.boot
spring-boot-starter-jetty
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
org.springframework.boot
spring-boot-starter-freemarker
下面就是吧 以前 创建好的 代码 分别拷贝 到其他两个项目中
package com.xxx.controller;
import java.util.List;
import org.bouncycastle.jcajce.provider.asymmetric.dsa.DSASigner.detDSA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.xxx.service.UserService;
import com.xxx.user.User;
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private DiscoveryClient client;
@RequestMapping(value = "/list/user", method = RequestMethod.GET)
public String list(ModelMap map){
List list=userService.list();
map.put("list", list);
return "user";
}
@RequestMapping(value = "/dept/discovery", method = RequestMethod.GET)
@ResponseBody
public Object discovery()
{
List list = client.getServices();
System.out.println("**********" + list);
List srvList = client.getInstances("MICROSERVICECLOUD-DEPT");
for (ServiceInstance element : srvList) {
System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
+ element.getUri());
}
return this.client;
}
}
package com.xxx.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.xxx.user.User;
@Mapper
public interface UserMapper {
public List findAll();
}
package com.xxx.service;
import java.util.List;
import com.xxx.user.User;
public interface UserService {
public List list();
}
package com.xxx.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xxx.mapper.UserMapper;
import com.xxx.service.UserService;
import com.xxx.user.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List list() {
// TODO Auto-generated method stub
return userMapper.findAll();
}
}
同时我还让这3个消费者 连接 不同 的数据库 这三个表分别 对照 8081,8082,8083,
server:
port: 8083
mybatis:
type-aliases-package: com.xxx.user # 所有user别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservicecloud-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/1807 # 数据库名称
username: root
password: root
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 200
eureka:
client: #客户端注册进eureka服务列表内
service-url:
# defaultZone: http://localhost:7001/eureka
defaultZone: http://euerka7001.com:7001/eureka/,http://euerka7002.com:7002/eureka/,http://euerka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-dept8083
prefer-ip-address: true # 显示ip地址
info:
app.name: atguigu-microservicecloud
company.name: www.baidu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
freemarker:
template-loader-path: classpath:/templates/
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html; charset=utf-8
expose-request-attributes: true
expose-session-attributes: true
request-context-attribute: request # 等待连接获取的最大超时时间
logging:
level:
com.xxx.mapper: debug
Insert title here
姓名
性别
年龄
修改
删除
<#list list as user>
${user.userId}
${user.userName}
${user.userSex}
${user.userAge}
修改
删除
#list>
新增
自己访问自己本身的项目 自测一下
首先8081(提供者) 对应的是1807库
8082 (提供者)对应的是1808库
8083提供者)对应的是1809库
现在打开Eureka 就可以看见这三个提供者的服务了已经注册到Eureka了
现在 在去 用我的 消费者(8084) 去访问
RoundRobinRule | 轮询 |
---|---|
RandomRule | 随机 |
AvailabilityFilteringRule | 会先过滤掉由于多次访问故障而处于熔断器跳闸状态的服务,还有并发的连接数量超过閥值的服务,然后对剩下的服务列表按照轮询的策略访问 |
WeightedResponseTimeRule | 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率高。刚启动时如果统计信息不足,则使用 RoundRobinRule策略,等统计信息足够,会切回到WeightedResponseTimeRule |
RetryRule | 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务 |
BestAvailableRule | 会先过滤由于多次访问故障而处于熔断器跳闸状态的服务,然后选择一个并发量最小的服务 |
ZoneAvoidanceRule | 默认规则 复合判断server 所在区域性能和 server的可用选择性服务器 |
|