2021-03-05

springcloud的记忆和理解

	springcloud为微服务的而创建的一种微服务生态系统。随着企业服务的日益庞大,
	springboot已经越来越不适应这种环境,服务越多,服务之间的调用和耦合问题等,
	都决定了单个或者多个springboot项目的使用上限,因此,springcloud就应运而生。
	当然不能说springcloud是一种新的技术,他只是为了构建微服务而兴起的一个微服务的生态系统,
	能够一站式的解决微服务架构的各种常见问题,但是其底层还是springboot,无论是eureka,feign,
	hystrix等springcloud等组件,都必须构建springboot项目,然后导入对应的依赖,才能生效。
	因此,也可以说springcloud就是springboot项目的集合构成的微服务生态系统,
	为微服务的管理,解耦,远程调用,安全,分布式等提供了一站式解决方法。

微服务的远程调用:restful+http

	看如下代码:
1:消费者代码如下
@Autowired
    private RestTemplate restTemplate; 
    //没有注册中心时,可以直接通过localhost来直接调用 ,8001是服务提供者的端口号
    private static final String REST_URL_PREFIX="http://localhost:8001";
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") int id){
        Dept dept=restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
        System.out.println("消费者向服务提供者拿到消息了"+dept);
        return dept;
    }

2:服务提供者代码如下:

 @GetMapping("/dept/get/{id}")
    public Dept queryDept(@PathVariable("id") int id){
       Dept dept= deptService.queryDept(id);
       if(dept==null){
           throw new RuntimeException("该id不正确");
       }
        logger.info("dept=="+dept);
        return dept;
    }
	由上述代码可知:springcloud就是通过http协议价restful风格进行远程调用,和服务解耦的,消费者和服务提供者的代码相互独立,可以不产生干涉。

加入eureka功能

新建一个springboot modul,

一:导入依赖
 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
 		二:编写配置文件:注意defaultZone是搭建集群用的,关联其他eureka,本人搭建了三个eureka,
 server:
  	port: 7001

eureka:
  instance:
    hostname: eureka7001  #服务端的名称
  client:
    register-with-eureka: false #表示自己为注册中心
    fetch-registry: false  #如果为false则表示自己为祖册中心
    service-url:
      defaultZone: http://eureka7002:7002/eureka/,http://eureka7003:7003/eureka/
三:在主启动类上加入注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {
    public static void main(String[] args){
        SpringApplication.run(EurekaServer_7001.class,args);
    }
}
四:消费者和服务者需要注册到eurek中,所以他们二人也需要导入eureka依赖,并进行配置
   如下:
    ①在消费者和服务提供方分别导入eureka'的客户端依赖
     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  ②配置文件
  #配置eureka 
  服务提供者的配置文件
  spring:
  application:
    **name: springcloud-provider-dept**  #这个为服务名,eureka上显示的注册服务名称就是这个,记住这个
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001:7001/eureka/,http://eureka7002:7002/eureka/,http://eureka7003:7003/eureka/
    instance:
      instance-id: springcloud-wangz  # 修改eureka上的描述信息
      prefer-ip-address: true
消费者的配置文件:

eureka:
  client:
    register-with-eureka: false  #是否要注册到eureka,false表示不用,消费者只是去哪服务,不用把自己注册进去
    service-url:
      defaultZone: http://eureka7001:7001/eureka,http://eureka7002:7002/eureka,http://eureka7003:7003/eureka,

③:分别在消费者和服务提供者主启动类上 加上注解@EnableEurekaClient,开启eureka功能
@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {
    public static void main(String[] args){
        SpringApplication.run(ConsumerApplication.class,args);
    }
}
如此eureka就生效了:
当然现在服务提供者已经注册到eureka中了,消费者可以直接去eureka中去查询服务:http访问的网址可以更改为:

    @Autowired
    private RestTemplate restTemplate;
    //没有注册中心时,可以直接通过localhost来直接调用
    //private static final String REST_URL_PREFIX="http://localhost:8001";
    //现在是从注册中心中提取服务,所以需要改成服务的名称(该名称需要去提供服务的模块去提取,或者去页面上去eureka拷贝)
    																					 //springcloud-provider-dept  小写 这个就是上面提供者的spring项目名
    private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";   
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") int id){
        Dept dept=restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
        System.out.println("消费者向服务提供者拿到消息了"+dept);
        return dept;
    }
    @RequestMapping("/consumer/dept/add")
    public boolean addDept(Dept dept){
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
        paramMap.add("deptno",6);
        paramMap.add("deptname", "dongshizhang");
        paramMap.add("db_source", "springcloud");
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",paramMap,Boolean.class);
    }

如此eureka的功能就实现了:
第一步:创建属于eureka的modul;淡入对应的依赖,然后再主启动类上加上@EnableEurekaServer注解,表示开启服务功能。
第二步:分别在消费者和提供者modul中导入eureka对应的客户端依赖,在application.yml中进行配置,然后在主启动类上加上:@EnableEurekaClient,开启注册eureka功能(消费者能够去查询服务,提供者可以去注册服务),
第三步:将消费者中的http访地址修改,改为eureka的服务名。

仅此

加入feign功能

	feign可以认为是服务内部的网关,但是在笔者看来,其实只是restfui+http进行远程调用的另一种模式:
	大家都知道java是面向对象的语言,在企业开发时,服务调用都是面向接口编程(例如controll层调用service),所以一群人就不习惯http+restful远程调用服务,就整出fegin这个功能;
	这个功能不难,对比着上面看就好:

一:在整个项目的公共模块中;加入feign依赖

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

二:在整个项目的公共模块中,创建接口类,接口的内的抽象方法为服务提供者controller层方法(方法名参数必须保持一致)如下,接口上加上注解@FeignClien,里面的参数为服务提供者的名字(大写,若不清楚可以观看上面内容中服务提供者的配置文件)

@Component
@FeignClient(value = “SPRINGCLOUD-PROVIDER-DEPT”)
public interface DeptService {

@GetMapping("/dept/get/{id}")
Dept queryDept(@PathVariable("id") int id);

}

然后主启动类上加上注解@EnableFeignClients
(basePackages = “com.wangz.servicefeign”) basepacket为:公共模块中接口所在包(上面接口),必须要能够扫描到

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.wangz.servicefeign")
@ComponentScan(value = {"com.wangz.servicefeign","com.wangz.config","com.wangz.controller"})
/**
 * 在微服务启东时会自动加载Ribbon负载均衡策略类(该类可以自定义,最好放在和启动类不同的包下,以便识别
 *  否则会被Ribbin共享)
 *  name:需要负载均衡的服务   configuration:负载均衡的策略
 *
 *  注:使用该注解一般为加载自定义的负载均衡策略,若Ribbin类中已经有则不需要该注解,直接
 *  在ConfigBean类中配置一个负载均衡策略的bean就好
 */
//@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration= IRule.class)
public class FeignConsumerApplication {
    public static void main(String[] args){
        SpringApplication.run(FeignConsumerApplication.class,args);
    }

}

做好这些之后,就差不多了,之后消费者就可以通过调用上面的接口进行服务调用(也就是面向接口编程)

消费者调用的代码再次更改为:
 @Autowired
    private DeptService deptService: #注入的是公共模块中书写的接口类

    /**
     * 加入eureka后默认返回xml格式,若想返回json格式,则需要添加produces 指定返回格式
     */
    @RequestMapping(value = "/consumerfeign/dept/get/{id}",produces = "application/json; charset=UTF-8")
    public Dept get(@PathVariable("id") int id){
        System.out.println("dddddddddddd");
        Dept dept=deptService.queryDept(id);
        System.out.println(dept);
        return dept;
    }

加入ribbin功能

ribbin的主要功能就是负载均衡:这个功能的使用可以说是可最简单的:
第一:导入依赖
  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
修改配置类:在配置的restTemplate上加上@LoadBalanced 注解即可
(RestTemplate,从最开始就最好交给spring容器管理,使用负载均衡功能加入一个注解就好)
@Configuration

public class ConfigBean {

@Bean
@LoadBalanced  //配置负载均衡
public RestTemplate getReatTemplate(){
    return new RestTemplate();
}

}

如此ribbin功能实现完毕简单,当然默认的如在均衡是随机访问
若想想其他的负载均衡策略,再加一个bean即可:

    @Bean
    @LoadBalanced  //配置负载均衡
    public RestTemplate getReatTemplate(){
        return new RestTemplate();
    }

    @Bean
    public IRule myIRule(){
        return new RandomRule();  //这里new了什么策略,上面的@LoadBalanced就会采用那种策略。当然可以自定义
    }
}

=========================================================================================
当然也可以在主启动类上加注解
/**
 * 在微服务启东时会自动加载Ribbon负载均衡策略类(该类可以自定义,最好放在和启动类不同的包下,以便识别
 *  否则会被Ribbin共享)
 *  name:需要负载均衡的服务   configuration:负载均衡的策略
 *
 *  注:使用该注解一般为加载自定义的负载均衡策略,若Ribbin类中已经有则不需要该注解,直接
 *  在ConfigBean类中配置一个负载均衡策略的bean就好
 */
//@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration= IRule.class)
public class FeignConsumerApplication {
    public static void main(String[] args){
        SpringApplication.run(FeignConsumerApplication.class,args);
    }

}

加入hystrix功能(熔断降级)

	熔断:断的是提供服务的一方;当调用的服务链比较长或者服务链从中断裂时,客户端或者消费端就会返回异常,这通常是我们不愿意看到的,因此提出了熔断一说,给每个服务都提供一个备用方案,那个服务出现问题时,就讲备份服务返回给客户端。
	降级:降得是消费者(客户端一方),当提供服务的服务器出现问题时,或者一访问服务就出错,或者其他服务在某一时间需要大量的系统资源时,将本服务暂时关闭,这种情况下采用降级最好,降级就是在消费者方提供一个备份方法,当服务端不能访问时,直接在客户端就调用备份方法(俗称降级服务),不占用服务端的任何cpu资源。

一:服务端熔断

第一步导入依赖:
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
第二步:在方法上加上注解@HystrixCommand,并准备备用方法
 @GetMapping("/dept/get/{id}")
  @HystrixCommand(fallbackMethod = "HystrixqueryDept")
    public Dept queryDept(@PathVariable("id") int id){
       Dept dept= deptService.queryDept(id);
        if(dept==null){
            throw new RuntimeException("该id不正确");
        }
        logger.info("dept=="+dept);
        return dept;
    }
    //备用方法
    public Dept HystrixqueryDept(@PathVariable("id") int id){
        Dept dept=new Dept(id,"id为"+id+"的部门不存在","数据库中也没有");
        return dept;
    }
    第三步:在主启动类上加上注解@EnableCircuitBreaker,开启熔断功能。

二:客户端降级

还记得在feign功能的内容中,创建的一个接口类,该接口类中创建的抽象方法,都是服务提供方控制层的方法吧

在公共模块中导入依赖
     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

二:书写上面接口类的实现类:实现FallbackFactory接口,重写方法
@Component
public class ServicefeginHystrix implements FallbackFactory {
    @Override
    public Object create(Throwable throwable) {
        return new DeptService() {
            @Override
            public Dept queryDept(int id) {
                return new Dept(-1,"服务已经暂停开启,请关注官网通告");
            }
        };
    }
}
三;在接口类上加上注解:value:服务名称 fallbackFactory:实现的降级类
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory=ServicefeginHystrix.class)
public interface DeptService {
    @GetMapping("/dept/get/{id}")
    Dept queryDept(@PathVariable("id") int id);
}

hystrix功能就此完结

zuul功能添加

创建新moudl:
第一步:导入依赖

 <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

第二步:在主启动类中加上注解
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class SpringcloudZuul {
    public static void main(String[] args) {
        SpringApplication.run(SpringcloudZuul.class,args);
    }
}
zuul也是需要注册到eureka中的

第三步:书写配置
spring:
  application:
    name: springcloud-wanngz-zuul

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001:7001/eureka/,http://eureka7002:7002/eureka/,http://eureka7003:7003/eureka/
    instance:
      instance-id: springcloud-zuul  # 修改eureka上的描述信息
      prefer-ip-address: true


info:
  app.name: wangz-springcloud
  company-name: blog.wangz.log


zuul:
  routes:
    mydept.serviceId: springcloud-provider-dept
    mydept.path: /mydept/**
  ignored-services: "*"        #springcloud-provider-dept  #不能在使用这个路径访问了
  prefix: /wangz             #设置公共的前缀


zuul搞定
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值