主要内容:
- 不同服务之间如何通信,传递什么
- Ribbon是什么,怎么集成
- Feign是什么,怎么集成
- Hystrix是什么,怎么集成(和Ribbon、Feign),以及这两者区别
- Zuul是什么,怎么集成
不同服务之间的通信
现在要做springboot-pay-server(支付服务)与springboot-user-server(用户服务)之间的通信
1.新创建一个springcloud-user-common公共访问模块
提供一个公共可访问的domain:User
2.springcloud-producer-user-server-1000用户端暴露接口
对外暴露一个接口(Controller):
@RestController
public class UserController {
//pay-server来调用
//@RequestMapping(value = "/user",method = "GET")
//localhost:port/user/11
//PathVariable将URL 中占位符参数绑定到控制器处理方法的入参中
@GetMapping(value = "/user/{id}")
public User getUserById(@PathVariable("id") Long id){
return new User(id,"zs:"+id,"wo shi zs : port=1000");
}
}
访问这个接口:
3.springcloud-consumer-pay-server-2000支付端暴露接口
支付端应该远程调用客户端来获取其user对象而不是再new一个user出来
需要用到RestTemplate:一个spring封装的http工具
PayController :
@RestController
public class PayController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/pay/user/{id}")
public User pay(@PathVariable("id") Long id){
//远程调用user-server获取user对象并返回 : 在Java代码中发送http请求 - RestTemplate
String url = "http://localhost:1000/user/"+id;
return restTemplate.getForObject(url,User.class);
}
}
PayServerApplication2000 :
@SpringBootApplication
public class PayServerApplication2000
{
public static void main( String[] args )
{
SpringApplication.run(PayServerApplication2000.class);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
Ribbon集成
ribbon是负载均衡器,是基于RestTemplate ,它赋予了RestTemplate 负载均衡的能力
1.复制一个springcloud-producer-user-server-1000,并修改端口为1001
两台相同的服务(端口号不同)是为了后面的支付模块(springcloud-consumer-pay-server-2000)来调用
2.支付端springcloud-consumer-pay-server-2000集成Ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3.修改支付模块启动类
@LoadBalanced让RestTemplate具有负载均衡的能力
@SpringBootApplication
public class PayServerApplication2000
{
public static void main( String[] args )
{
SpringApplication.run(PayServerApplication2000.class);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
4.修改支付模块暴露接口
原先是localhost:1000,由于在appliction中指定了服务名
spring:
application:
name: user-server
并且有两个(服务相同,端口不同)
所以进行替换,让Ribbon按某种规则去选择一个服务去执行
@RestController
public class PayController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/pay/user/{id}")
public User pay(@PathVariable("id") Long id){
String url = "http://user-server/user/"+id;
return restTemplate.getForObject(url,User.class);
}
}
5.负载均衡规则
随机均衡算法:
@SpringBootApplication
public class PayServerApplication2000
{
public static void main( String[] args )
{
SpringApplication.run(PayServerApplication2000.class);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
public IRule randomRule(){
return new RandomRule();
}
}
Feign集成
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
1.新建一个springcloud-consumer-order-server-4000模块
导包修改端口
2.修改启动类
@SpringBootApplication
//作用是开启支持和指定接口
@EnableFeignClients({"cn.itsource.feignclients"})
public class OrderServerApplication4000
{
public static void main( String[] args )
{
SpringApplication.run(OrderServerApplication4000.class);
}
}
3.创建接口
这个接口中的方法就是用来调用目标服务中的方法
//指定这个接口要访问那个服务名,这个服务名是对应一个端口+ip的
//Fiegn通过服务名user-server就能从注册中心到要调用的目标服务,根据方法上的url就能够找到目标服务的具体的Controller,就相当于拼接了一个url:http://user-server/user/11
@FeignClient(value = "user-server")
public interface UserFeignClient {
//参数类型、返回值、url要和@FeignClient注解指定的服务中的对应方法一致
@GetMapping(value = "/user/{id}")
User getUserById(@PathVariable("id") Long id);
}
集成Hystrix
解决服务器故障(雪崩)的一个组件 ,它可以实现:隔离 ,熔断 ,降级,缓存
- 隔离 :包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。
- 熔断 :当请求次数达到规定的阀值都出现服务故障(超时),Hystrix就把服务标记为短路状态.
正常情况下,断路器处于关闭状态(Closed),如果调用持续出错或者超时,电路被打开进入熔断状态(Open),后续一段时间内的所有调用都会被拒绝(Fail Fast),一段时间以后,保护器会尝试进入半熔断状态(Half-Open),允许少量请求进来尝试,
如果调用仍然失败,则回到熔断状态
如果调用成功,则回到电路闭合状态; - 降级 :高并发情况下 ,为了保证一些主要的服务有足够的资源不出问题 ,会认为的关掉一些无关紧要的服务,然后返回一些托底的数据,给用户一个友好的提示。
- 缓存 :Hystrix内部会把请求做缓存
1.在哪儿集成
应该在支付端集成,因为支付端会去调用用户端的数据,用户端的服务是可以人为关闭的,关闭了的话集成Hystrix也没有效果
2.Ribbon集成Hystrix
- 导包
- 主启动类加上@EnableCircuitBreaker开启熔断机制
- Controller中创建托底方法
3.Feign集成Hystrix
已经集成了,我们只需要开启就好了
- 在application.yml中:
#开启hystrix服务
feign:
hystrix:
enabled: true
- 在@FeignClient标签,指定fallback属性指定托底类
@FeignClient(value = "user-server", fallback = UserFeignClientFallback.class)
public interface UserFeignClient {
//要调用的服务的Controller中的方法,建议直接拷贝过来:
//1.url要一样 , 2参数要一样 , 3返回值要一样
@GetMapping(value = "/user/{id}")
User getUserById(@PathVariable("id") Long id);
}
- 编写托底类:注意拖地类要实现Feign接口 ,复写方法实现拖地数据,注意加上@Component
@Component
public class UserFeignClientFallback implements UserFeignClient {
@Override
public User getUserById(Long id) {
return new User(-1L,"无此用户","用户服务不可用");
}
}
Ribbon与Feign集成Hystrix的区别
前者是在Controller需要熔断的方法上加@HystrixCommand(fallbackMethod = “payFallback”)从而指定托底方法,这个托底方法就可以写在Controller中。
而后者是在用来调用user-server的客户端接口UserFeignClient处指定熔断类:fallback = UserFeignClientFallback.class,让这个被指定的类帮我们返回托底方法。
zuu的集成
zuu在云平台上提供动态路由、监控、弹性、安全等服务,相当于Web网站后端所有请求的前门,要注册到注册中心
1.新建一个模块springcloud-zuul-server-5000
2.导包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
3.在配置文件application中指定zuul的注册中心
4.修改主启动类
@SpringBootApplication
//开启zuul
@EnableZuulProxy
public class ZuulServerApplication5000
{
public static void main( String[] args )
{
SpringApplication.run(ZuulServerApplication5000.class);
}
}
5.配置路由
不配置路由的话可以绕过zuul,直接去访问需要的资源
并且现在我们是直接访问的服务名
1.禁用服务名访问方式
zuul:
ignored-services: "*" #禁止浏览器 使用服务名的方式去访问目标服务
2.指定服务用什么名字取访问
可以理解为起别名,达到隐藏服务名的作用
zuul:
routes:
pay-server: "/pay/**" # pay-server这个服务使用 /pay路径去访问
order-server: "/order/**" #order-server这个服务使用 /order 路径去访问
# http://localhost:5000/hrm/pay/pay/user/20 :访问方式: zuulip:zuul端口/前缀/服务的访问路径/资源路径