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
[email protected]
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("[email protected]");
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);
}