五大组件:Eureka(注册中心),
Ribbon/Feign(负载均衡),
Zuul(网关),
Config(配置中心),
Hystrix(熔断器)
注:本文章较长,但是五大组件全都包含
新建一个父模块,导包,包含SpringCloud以及SpringBoot的包
1.1在SpringCloud官网 找到Eureka(How to includ Eureka)
1.2新建模块Eureka,导包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1.3application.yml
server:
port: 1000
eureka:
instance:
hostname: localhost #主机
client:
registerWithEureka: false #禁止注册中心向自己注册
fetchRegistry: false #禁止注册中心拉取注册地址清单
serviceUrl: #微服务向注册中心注册的地址
defaultZone: http://localhost:1000/eureka/
1.4在主配置类上打标签 @EnableEurekaServer 开启Eureka事务
package cn.itsource.springboot;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaApplication.class).web(true).run(args);
}
}
2.1为什么使用Eureka高可用集群?
答:当只有一个EurekaServer,如果挂掉了,那么整个微服务都不可用,所以要进行集群
2.2
在“我的电脑”C:\Windows\System32\drivers\etc这个路径下 添加两个peer1和peer2
127.0.0.1 peer1
127.0.0.1 peer2
2.3 application.yml配置如下
spring:
profiles:
active: peer1
---
server:
port: 1000
eureka:
instance:
hostname: peer1 #主机
client:
registerWithEureka: false #禁止注册中心向自己注册
fetchRegistry: false #禁止注册中心拉取注册地址清单
serviceUrl: #微服务向注册中心注册的地址
defaultZone: http://peer2:1001/eureka/
spring:
profiles: peer1
---
server:
port: 1001
eureka:
instance:
hostname: peer2 #主机
client:
registerWithEureka: false #禁止注册中心向自己注册
fetchRegistry: false #禁止注册中心拉取注册地址清单
serviceUrl: #微服务向注册中心注册的地址
defaultZone: http://peer1:1000/eureka/
spring:
profiles: peer2
ribbon是负载均衡器,是基于RestTemplate ,它赋予了RestTemplate 负载均衡的能力
在客户端order中使用Ribbon
3.1导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3.2 写一个类,里面写RestTemplate方法
RestTemplate简介: pring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
package cn.itsource.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;
@Configuration
public class BeanConfig {
//交给Bean管理
//@LoadBalanced :让RestTemplate 有负载均衡的能力
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.3主配置类
package cn.itsource.springcloud;
import cn.itsource.springcloud.config.BeanConfig;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@Import(BeanConfig.class)
public class OrderApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(OrderApplication.class).web(true).run(args);
}
}
3.4 Controller层方法
@GetMapping("/order/user/{id}")
public User getUserById(@PathVariable("id") Long id){
//String url = "http://localhost:2000/user/"+id;
String url = "http://user-server/user/"+id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
3.5 application.yml
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/
instance:
instance-id: first-one
prefer-ip-address: true
server:
port: 2000
spring:
application:
name: order
简介:Feign是基于Ribbon,同样具有负载均衡的能力
4.1引入Feign的jar包
org.springframework.cloud
spring-cloud-starter-openfeign
4.2 配置类打上标签 @EnableFeignClients(“cn.itsource.springcloud.feignclient”) feignclient是接口类的包名
package cn.itsource.springcloud;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients("cn.itsource.springcloud.feignclient")
public class OrderApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(OrderApplication.class).web(true).run(args);
}
}
4.3 写一个接口类
package cn.itsource.springcloud.feignclient;
import cn.itsource.springcloud.domain.User;
import cn.itsource.springcloud.fallback.UserFeignClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//该客户端接口用来调用用户服务(user-server)
// http://user-server/userserver/user/11 -> ribbon
@FeignClient(value = "customer",fallback = UserFeignClientFallback.class)
public interface UserFeignClient {
//调用根据id获取用户的接口
@GetMapping("/userserver/user/{id}")
User getUserById(@PathVariable("id") Long id);
}
4.4 再写一个实现类
package cn.itsource.springcloud.fallback;
import cn.itsource.springcloud.domain.User;
import cn.itsource.springcloud.feignclient.UserFeignClient;
import org.springframework.stereotype.Component;
@Component
public class UserFeignClientFallback implements UserFeignClient {
@Override
public User getUserById(Long id) {
//返回托底数据
return new User(-1L,"null","用户服务获取失败");
}
}
4.5 Controller控制层调用接口类
package cn.itsource.springcloud.web.controller;
import cn.itsource.springcloud.domain.User;
import cn.itsource.springcloud.feignclient.UserFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//订单服务,消费者
@RestController
@RequestMapping("/orderserver")
public class OrderServerController {
@Autowired
private UserFeignClient userFeignClient ;
//浏览器调用,根据id获取用户 : 有负载均衡
@GetMapping("/user/{id}")
public User getUserById(@PathVariable("id")Long id){
return userFeignClient.getUserById(id);
}
}
4.6 application.yml
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/
instance:
instance-id: order-second
prefer-ip-address: true
server:
port: 2001
spring:
application:
name: order-second
5.1 导包
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
5.2 配置类打上注解标签(开启Hystrix)
@EnableCircuitBreaker
5.3 Controller控制层 (需在公共类上写一个AjaxResult)
package cn.itsource.springcloud.web.controller;
import cn.itsource.springcloud.domain.User;
import cn.itsource.springcloud.utils.AjaxResult;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;
@RestController
@RequestMapping("/orderserver")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
//这是订单服务,调用用户服务
@HystrixCommand(fallbackMethod = "getUserByIdFallback")
@GetMapping("/user/{id}")
public AjaxResult getUserById(@PathVariable("id")Long id){
String url = "http://customer/userserver/user/"+id;
//customer是yml配置中application.name名
//userserver是控制层的mapping
User user = restTemplate.getForObject(url, User.class);
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.getData(user);
return ajaxResult;
}
//编写降级方法
public AjaxResult getUserByIdFallback(@PathVariable("id")Long id){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setSuccess(false);
ajaxResult.setErroMessage("抱歉,订单服务不可能");
return ajaxResult;
}
}
5.4 application.yml
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/
instance:
instance-id: first-one
prefer-ip-address: true
server:
port: 2000
spring:
application:
name: order
6.1 导入jar包
org.springframework.cloud
spring-cloud-starter-netflix-zuul
6.2 主配置类上打注解标签 @EnableZuulProxy//开启zuul网关
package cn.itsource.springcloud;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.web.bind.annotation.RestController;
@EnableZuulProxy//开启zuul网关
@SpringBootApplication
@RestController
public class ZuulApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ZuulApplication.class).web(true).run(args);
}
}
6.3 application.yml
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/
instance:
instance-id: first-one
prefer-ip-address: true
server:
port: 4000
spring:
application:
name: zuul-server
zuul:
routes:
order: "/order/**" #别名---order是订单服务yml中application.name的名字
prefix: "/pre" #前缀
#浏览器访问格式:http://localhost:4000/pre/order/orderserver/user/10
6.4 写一个过滤器的类,继承ZuulFilter,实现登录检查
package cn.itsource.springcloud.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
public class ZuulByFilter extends ZuulFilter{
//过滤器的类型 PRE_TYPE
@Override
public String filterType() {
return "pre";
}
//过滤器的顺序
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
//获取请求上下文
RequestContext currentContext = RequestContext.getCurrentContext();
//获取请求对象
HttpServletRequest request = currentContext.getRequest();
//获取请求的地址
String requestURI = request.getRequestURI();
//如果包含了login,则返回false
if (requestURI.toUpperCase().contains("LOGIN")){
return false;
}
return true;
}
//执行run方法-----中心方法
@Override
public Object run() throws ZuulException {
//获取上下文对象
RequestContext currentContext = RequestContext.getCurrentContext();
//获取对象
HttpServletRequest request = currentContext.getRequest();
//获取相应对象
HttpServletResponse response = currentContext.getResponse();
//获取响应的数据格式
response.setContentType("application/json;charset:utf-8");
//获取请求头x-token
String token = response.getHeader("x-token");
//如果不存在请求头,则让重新登录
if (StringUtils.isBlank(token)){
HashMap map = new HashMap<>();
map.put("success", "false");
map.put("errorMessage","麻烦请登录" );
currentContext.setSendZuulResponse(false);
}
return null;
}
}
7.1 导入jar包
org.springframework.cloud
spring-cloud-config-server
7.2 主配置类打上注解标签
package cn.itsource.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
//@EnableDiscoveryClient
//@EnableConfigServer :开启配置中心
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication5000 {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication5000.class);
}
}
7.3 application.yml (放在码云仓库中)
server:
port: 5000
spring:
application:
name: config-server
#码云仓库地址
cloud:
config:
server:
git:
uri: https://gitee.com/xxxxx/zuul-server.git #码云仓库
username: xxxxx
password: xxxxx
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/
instance:
prefer-ip-address: true #使用ip注册到注册中心
instance-id: config-server:5000 #指定服务的id
7.4 浏览器访问地址: localhost:5000/application-config-dev.yml
实际要看码云中仓库名