Ribbon 是 Netflix 发布的云中间层服务开源项目,其主要功能是提供客户侧软件负载均衡算法,将 Netflix 的中间层服务连接在一起。
ribbon使用RestTemplate实现http调用 提供了客户端负载均衡的能力
ribbon是和EUREKA(注册中心)相辅相成的。
一个简单的demo
先启动一个注册中心 如何启动请参考 点击打开链接
我们写两个小程序 注册到注册中心(【以发送邮件为例 发送邮件的具体操纵请参考 点击打开链接】第一个程序是提交一个表单[表单含提交的标题,内容和接收人]到第二个程序中[此程序就负则发送])
第一个程序(表单提交数据)
引入ribbon的依赖
<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>cn.et</groupId>
<artifactId>SPRINGCLOUD-CLIENT</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ribbon依赖 用于去发现服务-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
</project>
表单
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="sendClient">
接收人:<input type="text" name="email_to"><br/>
主 题:<input type="text" name="email_subject"><br/>
内 容:<textarea rows="20" cols="28" name="content"></textarea><br/>
<input type="submit" value="发送">
</form>
</body>
</html>
表单请求的路径
package cn.et;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Controller
public class SendController {
//测试负载均衡 我们会在第二个程序写好后会测试一下
@Autowired
private LoadBalancerClient loadBalancer;
@ResponseBody
@GetMapping("/choosePub")
public String choosePub(){
StringBuffer sb=new StringBuffer();
for(int i=0;i<=10;i++){
ServiceInstance ss=loadBalancer.choose("email");
sb.append(ss.getUri().toString()+"<br/>");
}
return sb.toString();
}
@Autowired
RestTemplate restTemplate;
@GetMapping("/sendClient")
public String send(String email_to,String email_subject,String content){
//通过注册中心客户端负载均衡 获取一台主机来调用
try {
//创建一个请求头
HttpHeaders headers=new HttpHeaders();
//把表单提交的数据放入map中
Map<String,Object> map=new HashMap<String,Object>();
map.put("email_to", email_to);
map.put("email_subject", email_subject);
map.put("content", content);
//需要一个请求体(参数map)和一个请求头
HttpEntity he=new HttpEntity(map, headers);
//email服务名包含了ip地址和端口
restTemplate.postForObject("http://email/send",he, String.class);
} catch (RestClientException e) {
return "redirect:/a.html";//失败页面
}
return "redirect:/suc.html";//成功页面
}
}
#往注册中心注册的程序名字
spring.application.name=client
#服务的端口
server.port=8888
#注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#默认是轮询 添加此条可以随机选择
email.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
启动main方法往注册中心注册
package cn.et;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@Configuration
//表示当前这个服务需要调用其他服务的名称 value="email"服务名
@RibbonClient(value="email")
public class Main {
@LoadBalanced //启动负载均衡
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
第二个程序用于接收第一个程序提交的数据并发送邮件
加依赖
<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>cn.et</groupId>
<artifactId>SPRINGBOOT-SENDMAIL</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 发送邮件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- 发布到注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
</project>
application.properties文件
#是smtp服务器的地址
spring.mail.host=smtp.126.com
#发送者的邮箱密码
spring.mail.password=123
#邮箱的端口
spring.mail.port=25
#通过何种协议发送
spring.mail.protocol=smtp
#发送者的邮箱账号
spring.mail.username=pan1193@126.com
#注册到注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#服务注册到注册中心的名字 名字包含了ip地址和端口
spring.application.name=email
#服务程序的端口
server.port=8081
发送邮件的核心代码
package cn.et;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Mailcontroller {
@Autowired
JavaMailSender jms;
@PostMapping("/send")
//@RequestBody 接收json的数据
public String send(@RequestBody Map<String,Object> map){
SimpleMailMessage smm=new SimpleMailMessage();
//发送者
smm.setFrom("pan1193@126.com");
//接收者
smm.setTo(map.get("email_to").toString());
//标题
smm.setSubject(map.get("email_subject").toString());
//内容
smm.setText(map.get("content").toString());
jms.send(smm);
return "发送成功";
}
}
main方法启动服务
package cn.et;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
我们把application.properties中的端口改为8082 再启动 这样就有两个发送邮寄和提交表单的程序启动(如下图) 我们来测试一下
测试结果 下图可知是随机选取一台机器
我们来测试整个部署好的程序 在下图中内容
我这里发送成功了 如图