SpringCloud-day2

文章目录

  • 一.微服务之间通信
    • ①搭建user-common公共模块
    • ②user-server和pay-server依赖user-common
    • ③user-server编写controller 返回User对象
    • ④pay-server定义Bean(RestTemplate)
    • pay-server编写controller
  • 二.Ribbon(负载均衡)集成
    • ①创建user-server的集群
    • ②导入Ribbon的jar包
    • ③RestTemplate的@Bean定义的方法
    • ④改用服务名方式调用
    • ⑤定义负载均衡策略: 配置负载均衡的@Bean -> 负债均衡接口 IRule
  • 三.Feign(负载均衡)集成
    • ①新建项目order-server
    • ②导入依赖
    • ③开启Feign
    • ④写Feign的接口 :
    • ⑤注入 Fiegn接口,实现服务调用
    • ⑥定义负载均衡策略
  • 四.Ribbon&Hystrix(断路器)集成
    • 一.Hystrix(断路器)基本概念
    • 二.服务熔断
    • 三.Ribbon集成Hystrix
      • ①导入jar包
      • ②主配置类开启Hystrix
      • ③编写托底方法
  • 五.Feign&Hystrix(断路器)集成
    • ①注意:不用导包
    • ②开启Hystrix :
    • ③在@FeignClient标签,指定fallback属性指定托底类
    • ④写托底类:
  • 六.Zuul(服务网关)集成
    • 一.zuul网关认识
    • 二.zuu的集成
      • ①创建zuul项目
      • ②导入jar包: eureka-client ,web包,zuul包
      • ③主配置类: @EnabelZuulProxy
      • ④测试
      • ⑤zuul配置
      • ⑥超时配置
    • 三.zuul工作执行流程
    • 四.自定义filter
  • 七.分布式配置中心
    • 一.配置中心集成git
      • ①登录码云,新建仓库
      • ②新建文件
      • ③创建springcloud-config-server项目模块
      • ④4.导入jar包
      • ⑤主配置类:@EnableConfigServer
      • ⑥配置连接仓库
    • 二.微服务集成配置中心
      • ①导入jar包
      • ②创建bootstrap.yml文件

一.微服务之间通信

①搭建user-common公共模块

  • 因为用户服务和支付服务都需要使用User类,所以我们抽取一个公共的模块,服务依赖它就可以了
  • 创建一个普通maven项目,编写domain和User实体类
    SpringCloud-day2_第1张图片

②user-server和pay-server依赖user-common

<!--依赖user-common公共模块-->
<dependency>
    <groupId>cn.itsource</groupId>
    <artifactId>springcloud-user-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

③user-server编写controller 返回User对象

@RestController
public class UserController {
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable("id") Long id){
        return new User(id,"古老板","我创建了学荣ui port:1000");
    }
}

测试一下能够获取到User对象localhost:1000/user/11
SpringCloud-day2_第2张图片

④pay-server定义Bean(RestTemplate)

@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

pay-server编写controller

使用RestTemp调用user-server获取结果 - 使用ip:端口调用 -> “http://localhost:1000/user/”+id;

@RestController
public class PayController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/pay/user/{id}")
    public User getUserById(@PathVariable("id") Long id){
        String url = "http://localhost:1000/user/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

SpringCloud-day2_第3张图片

二.Ribbon(负载均衡)集成

负载均衡Ribbon的工作原理

支付服务要调用用户服务,需要指定用户名"user-server".
因为用户微服务做了集群,那么"user-server"服务名对应了两个端口,Ribbon会通过服务名找到两个端口,根据负载均衡算法(轮询,随机等)选中其中一个实现调用。
SpringCloud-day2_第4张图片

①创建user-server的集群

多建立一个相同的user-server,注意:端口不一样 ,instance-id不一样 ,其他的一样

②导入Ribbon的jar包

pay-server导入Ribbon的jar包


        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
        dependency>

③RestTemplate的@Bean定义的方法

加上 @LoadBalanced相当于给予RestTemplate对象负载均衡的能力

//相当于给予RestTemplate对象负载均衡的能力
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

④改用服务名方式调用

修改pay-servercontroller,让RestTemplate使用服务名的方式实现调用 -> “http://user-server/user/”+id

@RestController
public class PayController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/pay/user/{id}")
    public User getUserById(@PathVariable("id") Long id){
        String url = "http://user-server/user/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

⑤定义负载均衡策略: 配置负载均衡的@Bean -> 负债均衡接口 IRule

//配置负载均衡算法为 - 随机
@Bean
public IRule randomRule(){
    return new RandomRule();
}

三.Feign(负载均衡)集成

  • Feign整合了Ribbon和hystrix,可以让我们不再需要显式地使用这两个组件。
  • 通过编写简单的接口和插入注解,就可以定义好http请求的参数、格式、地址等信息。
    接下来我们开始集成Feign

①新建项目order-server

首先我们重新创建一个项目order-server(订单服务)

②导入依赖

需要web,eureka-client , user-comm , openfeign包

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--  集成Web的jar包-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--依赖user-common公共模块-->
    <dependency>
        <groupId>cn.itsource</groupId>
        <artifactId>springcloud-user-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!--集成Feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

③开启Feign

主配置类:@EnableFeignClients

@SpringBootApplication
@EnableFeignClients  //开启Feign客户端
public class OrderServerApplication4000
{
    public static void main( String[] args )
    {
        SpringApplication.run(OrderServerApplication4000.class);
    }

}

④写Feign的接口 :

  • 接口上打: @FeignClient(value = “user-server”) :目标服务的名字
  • 接口中方法:跟目标服务的controller中的方法一致 1.url要一样 , 2参数要一样 , 3返回值要一样
@FeignClient(value = "user-server")//写远程调用的服务名
public interface MyFeignClient {
    //url,参数,返回值类型必须一样
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable("id") Long id);
}

⑤注入 Fiegn接口,实现服务调用

@RestController
public class OrderController {
    @Autowired
    private MyFeignClient myFeignClient;
    @GetMapping("/order/user/{id}")
    public User getUserById(@PathVariable("id") Long id){
        return myFeignClient.getUserById(id);
    }
}

⑥定义负载均衡策略

#配置ribbon
user-server:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机

四.Ribbon&Hystrix(断路器)集成

一.Hystrix(断路器)基本概念

雪崩效应:类似雪崩一样,滚雪球越滚越大
当一个微服务出问题,和该微服务有调用关系的微服务也会挂掉,以此类推可能导致大量微服务挂掉。
为了解决雪崩效应带来的问题,hystrix提供了如下的机制:

  • 资源隔离(限流):包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务的调用。
  • 熔断:当失败率达到阀值自动触发降级(如果因为网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。
  • 降级机制:超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。
  • 缓存:提供了请求缓存,请求合并实现。

二.服务熔断

正常情况下,断路器处于关闭状态
如果调用持续出错或者超时,电路被打开进入熔断状态,后续一段时间内所有的调用都会被拒绝
一段时间以后,保护器会尝试进入半熔断状态,允许少量请求进行尝试。
如果调用仍然失败,则回到熔断状态
如果调用成功,则回到电路闭合状态

三.Ribbon集成Hystrix

①导入jar包

<!--集成hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

②主配置类开启Hystrix

@EnableCircuitBreaker开启Hystrix

@SpringBootApplication
@EnableCircuitBreaker
public class PayServerApplication2000
{
    public static void main( String[] args )
    {
        SpringApplication.run(PayServerApplication2000.class);
    }

    //相当于给予RestTemplate对象负载均衡的能力
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    //配置负载均衡算法为 - 随机
    @Bean
    public IRule randomRule(){
        return new RandomRule();
    }
}

③编写托底方法

  • 方法打上@HystrixCommand(fallbackMethod = “payFallback”)
  • 编写拖底方法
@RestController
public class PayController {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "payFallback")
    @GetMapping("/pay/user/{id}")
    public User getUserById(@PathVariable("id") Long id){
        String url = "http://user-server/user/"+id;
        return restTemplate.getForObject(url, User.class);
    }
    //拖底方法
    public User payFallback(@PathVariable("id") Long id){
        return new User(-1L,"无此用户","用户服务不可用");
    }
}

五.Feign&Hystrix(断路器)集成

①注意:不用导包

②开启Hystrix :

配置文件:

#开启hystrix
feign:
  hystrix:
    enabled: true

③在@FeignClient标签,指定fallback属性指定托底类

@FeignClient(value = "user-server",fallback = MyFeignClientFallback.class)//写远程调用的服务名
public interface MyFeignClient {

    //url,参数,返回值类型必须一样
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable("id") Long id);
}

④写托底类:

注意:

  • 拖地类要实现Feign接口
  • 复写方法实现拖地数据
  • 托底类需要打 @Component标签
@Component
public class MyFeignClientFallback implements MyFeignClient{
    @Override
    public User getUserById(Long id) {
        return new User(-1L,"无此用户","用户服务无法访问");
    }
}

六.Zuul(服务网关)集成

一.zuul网关认识

zuul作为独立的应用,zuul作为微服务群的请求入口保护着微服务的安全,可以通过zuul实现,统一的权限验证、限流、请求日志/监控,负载均衡(请求分发等)功能,–>有点像之前学习的拦截器

注意:zuul也要注册进Eureka
SpringCloud-day2_第5张图片

二.zuu的集成

①创建zuul项目

②导入jar包: eureka-client ,web包,zuul包

<dependencies>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-zuulartifactId>
    dependency>
dependencies>

③主配置类: @EnabelZuulProxy

@SpringBootApplication
@EnableZuulProxy
public class ZuulServerApplication5000
{
    public static void main( String[] args )
    {
        SpringApplication.run(ZuulServerApplication5000.class);
    }
}

④测试

http://+zuul的ip:zuul的port/服务名字/资源路径
如:http:// localhost:5000/ pay-server /pay/user/1

⑤zuul配置

server:
  port: 1020
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1010/eureka/ #注册中心服务端的注册地址
  instance:
    prefer-ip-address: true
    instance-id: zuul-server:1020
spring:
  application:
    name: zuul-server

# 配置zuul
zuul:
  ignored-services: "*" #禁止浏览器 使用服务名的方式去访问目标服务
  routes:
    pay-server: "/pay/**"     
    order-server: "/order/**"    
  • ignored-services 忽略使用服务名的方式访问
  • routes :指定服务的访问路径
  • pay-server这个服务使用 /pay路径去访问
  • order-server这个服务使用 /order 路径去访问
  • http://localhost:5000/pay/pay/user/20 :访问方式: zuulip:zuul端口/服务的访问路径/资源路径

⑥超时配置

  host: #zuul主机超时
    connect-timeout-millis: 30000 #HTTP连接超时要比Hystrix的大
    socket-timeout-millis: 30000   #socket超时
	
# 下面ribbon和hystrix都可以配
ribbon: #ribbon超时
  ReadTimeout: 30000
  ConnectTimeout: 30000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 40000

三.zuul工作执行流程

执行流程图:
SpringCloud-day2_第6张图片

  • 正常执行流程:请求->pre filter(前置过滤器)–>routing filter(路由过滤器)–>origin server(微服务)–>再回到routing filter(路由过滤器)–>post filter–>响应
  • 若有自定义filter:请求->pre filter(前置过滤器)–>custom(自定义)filter -->routing filter(路由过滤器)–>origin server(微服务)–>再回到routing filter(路由过滤器)–>post filter–>响应
  • 若filter出现错误:请求->…发生错误的filter–>Error filter–>post filter–>响应
  • 若是post filter发生错误:请求->…post filter–>Error filter–>响应(直接执行完Error filter响应)

四.自定义filter

步骤:

  • 创建一个类继承ZuulFilter,记得打上@Component,覆写4个方法
  • filterType():设置过滤器类型
  • filterOrder():设置过滤顺序
  • shouldFilter():判断是否登录检查,返回true表示要做登录检查
  • run()当shouldFilter()方法返回true时,才会调用run方法,
    run方法,编写登录检查的代码,如果请求头中没有token,说明没有登录,
    阻止请求继续往下执行:不放行
@Component
public class LoginCheckFilter extends ZuulFilter {
    //过滤器类型
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    //顺序
    @Override
    public int filterOrder() {
        return 1;
    }

    //判断是否应该检查登录,返回true表示要做登录检查
    @Override
    public boolean shouldFilter() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        //判断url是否是登录请求
        String requestURI = request.getRequestURI();
        if(StringUtils.hasLength(requestURI)&&requestURI.endsWith("login")){
            return false;
        }
        return true;
    }

    //做登录检查,如果请求头中没有token,说明没有登录
    @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");

        //获取请求头token,判断是否登录
        String token = request.getHeader("token");
        request.getHeader("token");
        if(!StringUtils.hasLength(token)){
            //如果token为空,表示没有登录,返回提示登录信息,阻止请求继续往下执行,不放行
            Map<String,Object> result = new HashMap<>();
            result.put("success",false);
            result.put("message","您还未登录,请先登录");
            try {
                response.getWriter().print(JSON.toJSONString(result));
                //并且阻止请求继续往下执行:不放行
                currentContext.setSendZuulResponse(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

七.分布式配置中心

微服务架构中,每个项目都有一个yml配置,管理起来麻烦。分布式配置中心的作用就是用来管理微服务的配置
在spring cloud config 组件中,分两个角色,一是config server,二是config client。

架构图
SpringCloud-day2_第7张图片

一.配置中心集成git

配置中心可以和svn,git集成,但是推荐使用github 集成使用

  1. 登录码云,新建仓库
  2. 新建文件,将项目中配置文件的内容拷贝到码云创建的文件中
  3. 创建springcloud-config-server项目模块
  4. 导入jar包(eureka-client、web、spring-cloud-config-server)
  5. 主配置类:@EnableConfigServer //开启配置中心服务
  6. 配置文件:配置码云仓库的访问链接,用户名,密码
    到这里可以测试一下,看配置中心是否可以拿到配置文件的信息
  7. 以order为例,在order-server导入spring-cloud-starter-config包
  8. 删除原有的配置文件(改名备份),创建bootstrap.yml文件(配置配置中心地址,配置文件名称,环境)

①登录码云,新建仓库

SpringCloud-day2_第8张图片

②新建文件

仓库中新建文件,将项目中配置文件的内容拷贝到码云创建的文件中
SpringCloud-day2_第9张图片

③创建springcloud-config-server项目模块

④4.导入jar包

导入jar包(eureka-client、web、spring-cloud-config-server)

<dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-config-serverartifactId>
        dependency>

    dependencies>

⑤主配置类:@EnableConfigServer

主配置类:@EnableConfigServer //开启配置中心服务

@SpringBootApplication
@EnableConfigServer //开启配置中心服务
public class ConfigServerApplication6000 {
    public static void main( String[] args )
    {
        SpringApplication.run(ConfigServerApplication6000.class);
    }
}

⑥配置连接仓库

配置文件:配置码云仓库的访问链接,用户名,密码

server:
  port: 6001

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3000/eureka/ #注册中心服务端的注册地址
  instance:
    prefer-ip-address: true #使用ip进行注册
    instance-id: config-server:6001 #服务注册到注册中心的id
spring:
  application:
    name: config-server #应用的名称

  #码云配置
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/biaowww/springcould-config.git
          username: [email protected]
          password: luo1998biao45

到这里可以测试一下,看配置中心是否可以拿到配置文件的信息
配置中心ip+端口+仓库文件名,访问仓库文件的内容
http://localhost:6001/application-order-dev.yml
SpringCloud-day2_第10张图片
注意:config-server的配置文件和eureka-server的配置文件,不能交给仓库管理

二.微服务集成配置中心

①导入jar包

以order为例,在order-server导入spring-cloud-starter-config包

<dependency>
     <groupId>org.springframework.cloudgroupId>
     <artifactId>spring-cloud-starter-configartifactId>
 dependency>

②创建bootstrap.yml文件

删除原有的配置文件(改名备份),创建bootstrap.yml文件(配置配置中心地址,配置文件名称,环境)

#指向配置中心,拉取order-server的配置文件
spring:
  cloud:
    config:
      uri: http://localhost:6001 #配置中心的地址
      name: application-order  #配置文件的名称
      profile: dev  #环境

测试启动order-server,看端口号,仓库更改配置端口号,再次启动,看更改是否成功

你可能感兴趣的:(java)