Spring cloud服务的注册和发现
可参考:http://blog.csdn.net/liaomin416100569/article/details/78059174
服务(service) 发送邮件
服务的概念:
服务注册和发现
地址:https://cloud.spring.io/spring-cloud-netflix/
配置注册中心:
在eurekaserver中加入依赖
<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.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
注册中心的资源文件application.yml
server:
port: 8761#eureka默认端口
eureka:
instance:
hostname: localhost#主机名
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
网址:
http://cloud.spring.io/spring-cloud-static/Dalston.SR5/single/spring-cloud.html#spring-cloud-eureka-server
注册中心的启动类(EnableEurekaServer)
package cn.et;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
eurekaServer的访问地址:localhost:8761 出现界面
eureka client 的配置(客户端)
spring.mail.host=smtp.163.com
Spring.mail.password=123456
spring.mail.port=25
spring.mail.protocol=smtp
spring.mail.username=raya_l@163.com
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.application.name=email
server.port=8081
在注册中的main方法上加@EnableEurekaClient启动自动注册
Eureka客户端启动类
package cn.et;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
@EnableEurekaClient和@EnableDiscoveryClient是一样的
Ribbon的main方法
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(value="EMAIL")
/**
* 表示当前这个服务需要调用其他的服务的名称
* @author Administrator
*
*/
@Configuration
public class Main {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
Ribbon用get发送和post发送
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
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 RestTemplate restTemplate;//通过restTemplate来调用ribbon
@Autowired
private LoadBalancerClient loadBalancer;
/**
* 启动多个发布者 端口不一致 程序名相同
* 使用
* @LoadBalanced必须添加
* @return
*/
@ResponseBody
@RequestMapping("/choosePub")
public String choosePub() {
StringBuffer sb=new StringBuffer();
for(int i=0;i<=10;i++) {
ServiceInstance ss=loadBalancer.choose("EMAILSERVER");//从两个idserver中选择一个 这里涉及到选择算法
sb.append(ss.getUri().toString()+"<br/>");
}
return sb.toString();
}
@GetMapping("/sendClient")
public String send(String email_to,String email_subject ,String email_content){
//调用email服务
String controller="/send";
//通过注册中心客户端负载均衡 获取一台主机来调用
try {
controller += "?email_to="+email_to+"&email_subject="+email_subject+"&email_content="+email_content;
String result=restTemplate.getForObject("http://EMAILSERVER"+controller, String.class);
} catch (RestClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "redirect:/error.html";
}
//通过redirect返回string类型跳转,不允许spring控制器用@ResponseBody
return "redirect:/suc.html";
}
/**
* 演示post
* @param email_to
* @param email_subject
* @param email_content
* @return
*/
@PostMapping("/sendClientpost")
public String postsend(String email_to,String email_subject ,String email_content){
try {
//
HttpHeaders headers=new HttpHeaders();
Map<String,Object> map=new HashMap<String,Object>();
map.put("email_to",email_to );
map.put("email_subject", email_subject);
map.put("email_content", email_content);
HttpEntity<Map> request=new HttpEntity<Map>(map, headers);
String result=restTemplate.postForObject("http://EMAILSERVER/send",request, String.class);
} catch (RestClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "redirect:/error.html";
}
return "redirect:/suc.html";
}
/**
* 演示调用sendmail的/user/这个请求
* @return
*/
@ResponseBody
@GetMapping("/invokeUser")
public String invokeUser(String id){
String resul=restTemplate.getForObject("http://EMAILSERVER/user/{id}",String.class,id);
return resul;
}
}
发送邮件的控制类
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
private JavaMailSender jms;
@PostMapping("/send")
public String send(@RequestBody Map<String,Object> map){
SimpleMailMessage mailMessage=new SimpleMailMessage();
mailMessage.setFrom("raya_l@163.com");
mailMessage.setTo(map.get("email_to").toString());
mailMessage.setSubject(map.get("email_subject").toString());
mailMessage.setText(map.get("email_content").toString());
jms.send(mailMessage);
return "1";
}
@GetMapping("/a")
public String a(){
return "2";
}
@GetMapping("/user/{userId}")
public Map getUser(@PathVariable String userId){
Map map=new HashMap();
map.put("id", userId);
map.put("name", "zs_"+userId);
return map;
}
}
启动MailController
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
@RibbonClient(value = "EMAILSERVER")
/**
* 表示当前这个服务需要调用其他的服务的名称
*
* @author Administrator
*
*/
@Configuration
public class Main {
@LoadBalanced//启动负载均衡
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
定义LoadBalancerClient 可以用于测试选择的服务器的算法 负载的算法的类需要实现 IRule 接口 以下列表摘自网络
策略名 | 策略描述 |
BestAvailableRule | 选择一个最小的并发请求的server |
AvailabilityFilteringRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) |
WeightedResponseTimeRule | 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 |
RetryRule | 对选定的负载均衡策略机上重试机制。 |
RoundRobinRule | roundRobin方式轮询选择server |
RandomRule | 随机选择一个server |
ZoneAvoidanceRule | 复合判断server所在区域的性能和server的可用性选择server |
ribbon默认的配置类为 RibbonClientConfiguration 其中配置IRule的bean为
负载均衡的规则配置:
EMAILSERVER:用户名
EMAILSERVER.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
Feign(面向接口式)
加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
配置文件:
spring.application.name=EMAIL
server.port=8888
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#服务器的算法(随机)
EMAILSERVER.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
接口
package cn.et;
import java.util.Map;
import org.springframework.cloud.netflix.feign.FeignClient;
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;
@FeignClient("EMAILSERVER")
public interface IsendMail {
@GetMapping("/user/{userId}")
public Map getUser(@PathVariable("userId") String userId);
@PostMapping("/send")
public String send(@RequestBody Map<String,Object> map);
}
控制类
package cn.et;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
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.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestClientException;
@Controller
public class SendController {
@Autowired
private IsendMail sendMail;
@GetMapping("/sendClient")
public String send(String email_to,String email_subject ,String email_content){
//调用email服务
String controller="/send";
//通过注册中心客户端负载均衡 获取一台主机来调用
try {
controller += "?email_to="+email_to+"&email_subject="+email_subject+"&email_content="+email_content;
//String result=restTemplate.getForObject("http://EMAILSERVER"+controller, String.class);
} catch (RestClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "redirect:/error.html";
}
return "redirect:/suc.html";
}
/**
* 演示post
* @param email_to
* @param email_subject
* @param email_content
* @return
*/
@PostMapping("/sendClientpost")
public String postsend(String email_to,String email_subject ,String email_content){
try {
Map<String,Object> map=new HashMap<String,Object>();
map.put("email_to",email_to );
map.put("email_subject", email_subject);
map.put("email_content", email_content);
sendMail.send(map);
} catch (RestClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "redirect:/error.html";
}
return "redirect:/suc.html";
}
/**
* 演示调用sendmail的/user/这个请求
* @return
*/
@ResponseBody
@GetMapping("/invokeUser")
public String invokeUser(String id){
Map map=sendMail.getUser(id);
return map.get("name").toString();
}
}
启动类
package cn.et;
import java.util.Map;
import org.springframework.cloud.netflix.feign.FeignClient;
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;
@FeignClient("EMAILSERVER")
public interface IsendMail {
@GetMapping("/user/{userId}")
public Map getUser(@PathVariable("userId") String userId);
@PostMapping("/send")
public String send(@RequestBody Map<String,Object> map);
}