认识并学会springCloud的使用

Posted mountaincold

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了认识并学会springCloud的使用相关的知识,希望对你有一定的参考价值。

SpringCloud将现在一些流行的技术整合到一起,实现如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。主要涉及的组件有

netflix

  • Eureka:注册中心

  • Zuul:服务网关

  • Ribbon:负载均衡

  • Feign:服务调用

  • Hystix:熔断器

环境准备:一个数据库和表tb_user

1.创建一个父工程,和子模块consumer-demo,eureka-server,eureka-server2(两个是eureka的高可用性练习),user-server,(user-server2是对user server的集群练习可以不要)zuul-Demo。

(完整代码:https://gitee.com/mountaincold/cloudDemo)

技术分享图片

2. 创建注册中心 eureka-server

  1.pom.xml 导入依赖 eureka服务端

技术分享图片

 

  2. 创建启动类 eureka1

 技术分享图片

  3. 设置application.yml

技术分享图片

eureka-server2相同把端口换成10087,注册地址换成10086就行了

2.创建服务提供者userservice

  1. pom.xml的配置 导入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
        </dependency>
        <!-- Eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

  2. 设置application.yml配置文件

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis
    username: root
    password: 960326
  application:
    name: userservice
logging:
  level:
    com.practice:
      debug
eureka:
  client:
    service-url: #eurekaServer 地址
      defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
  instance:
    prefer-ip-address: true #当调用getHostname获取实例的hostname时 返回ip而不是host名称
    ip-address: 127.0.0.1 #指定自己的ip信息 不指定的话会自己寻找
    lease-expiration-duration-in-seconds: 10 #服务失效时间 默认90秒
    lease-renewal-interval-in-seconds: 5 #服务续约时间的间隔,默认30秒
    instance-id: ${spring.application.name}:${server.port} #设置id

  2.创建启动类,和pojo对象类

技术分享图片

@Table(name = "tb_user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 用户名
    private String userName;

    // 密码
    private String password;

    // 姓名
    private String name;

    // 年龄
    private Integer age;

    // 性别,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 创建时间
    private Date created;

    // 更新时间
    private Date updated;

    // 备注
//    private String note;

    // 。。。省略getters和setters
    //TODO 需要手动添加getter,setter
}

  

  3.创建controller,service ,mapper

技术分享图片

 

package com.practice.controller;

import com.practice.pojo.User;
import com.practice.service.UserService;
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.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return this.userService.queryById(id);
    }
}

/**
*设置睡眠是为了测试熔断器
*/
package com.practice.service;

import com.practice.mapper.UserMapper;
import com.practice.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    public User queryById(Long id) {
        Long startTime = System.currentTimeMillis();
        int time = (int)(Math.random()*2000+1);
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        User user = this.userMapper.selectByPrimaryKey(id);
        Long endTime = System.currentTimeMillis();
        logger.info("本次查询:{},花费时间为{}ms",id,endTime-startTime);
        return user;
    }
}

/**
*通用mapper的使用,可以动态生成实现子类和查询语言适用于单表查询
*/

package com.practice.mapper;

import com.practice.pojo.User;
import tk.mybatis.mapper.common.Mapper;

public interface UserMapper extends Mapper<User> {
}

3创建服务消费者cosumer-demo

  1.pom.xml配置 需要的依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 添加OkHttp支持 -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.9.0</version>
        </dependency>
        <!-- Eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--Hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--Feign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

  2. application.xml的配置

Spring:
  application:
    name: consumer
eureka:
  client:
    service-url: #eurekaServer地址
      defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
    registry-fetch-interval-seconds: 5 #获取更新服务列表 默认时间为30秒

  instance:
    prefer-ip-address: true #当其它服务获取地址时提供ip而不是hostname
    ip-address: 127.0.0.1 #指定自己的ip信息 不指定的话会自己寻找
ribbon: #修改服务负载均衡的分流规则
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机 默认为轮询
  ConnectTimeout: 250 # ribbon 连接超时时间
  ReadTimeout: 1000 #Ribbon 数据读取超时时间
feign:
  hystrix:
    enabled: true #开启feign的熔断支持默认关闭
  compression:
    request:
      enabled: true # 开启请求压缩
      mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
      min-request-size: 2048 # 设置触发压缩的大小下限
logging:
  level:
    com.consumer:
      debug

  3. 创建启动类 和pojo对象类

package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient
@SpringBootApplication
//@EnableHystrix
@EnableFeignClients
public class Consumer {
//    @Bean
//    @LoadBalanced //开启负载均衡
//    public RestTemplate restTemplate(){
//    // 使用OKHTTP客户端,只需注入工厂
//       return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
//    }
// 因为Feign 中自动集成 Ribbon 负载均衡 所以不需要自定义RestTemplate
    public static void main(String[] args) {
        SpringApplication.run(Consumer.class);

    }
}
/**
*属性类型和user-service中相同但是不用加@table之类的注解
*/
public class User  {

    private static final long serialVersionUID = 1L;

    private Long id;

    // 用户名
    private String userName;

    // 密码
    private String password;

    // 姓名
    private String name;

    // 年龄
    private Integer age;

    // 性别,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 创建时间
    private Date created;

    // 更新时间
    private Date updated;


    //TODO 需要手动添加getter,setter
}

  4. 创建 controller,service,config (dao是测试hystrix时创建的,feign中支持熔断所以不用创建)

 技术分享图片

package com.consumer.controller;

import com.consumer.pojo.User;
import com.consumer.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("consume")
public class ConsumerController {
    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> consume(@RequestParam("ids")List<Long> ids){
    return this.userService.queryUserByIds(ids);
    }
}



package com.consumer.service;

import com.consumer.config.UserFeignClient;
import com.consumer.config.impl.UserFeignClientImpl;
import com.consumer.dao.UserDao;
import com.consumer.pojo.User;
//import com.netflix.discovery.DiscoveryClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserService {



  /**
   * 根据服务名称,获取服务实例
   * */

     @Autowired
     private UserFeignClient userFeignClient;
    public List<User> queryUserByIds(List<Long> ids) {
        List<User> users = new ArrayList<>();

        ids.forEach(id ->{
            users.add(userFeignClient.queryById(id));
           /* try {
                Thread.sleep(500);
线程睡眠用于测试可以删除
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
        });
        return users;
    }
  
}


package com.consumer.config;

import com.consumer.config.impl.FeignConfig;
import com.consumer.config.impl.UserFeignClientImpl;
import com.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "userservice",fallback = UserFeignClientImpl.class,configuration = FeignConfig.class)

public interface UserFeignClient {
    @GetMapping("/user/{id}")
    public User queryById(@PathVariable("id") Long id);
}



package com.consumer.config.impl;

import com.consumer.config.UserFeignClient;
import com.consumer.pojo.User;
import org.springframework.stereotype.Component;

@Component
public class UserFeignClientImpl implements UserFeignClient {

    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setId(id);
        user.setName("请求超时,请稍后重试--feign");
        return user;
    }
}



package com.consumer.config.impl;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 编写配置类定义feign的日志级别 feign支持四种级别
 * - NONE:不记录任何日志信息,这是默认值。
 * - BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
 * - HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
 * - FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
 */
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

4. 创建zuul网关

     1.pom.xml中的依赖

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

  2. application.yml

server:
  port: 10010
spring:
  application:
    name: gateway
zuul:
  routes:
    userservice: userservice/**  #简便方式
  prefix: /api #添加路由前缀
 #     path: /userservice/** #这是映射路径
#    serviceId: userservice #指定服务名称
#      url: http://127.0.0.1:8081 映射路径对应的实际url地址
eureka:
  client:
    registry-fetch-interval-seconds: 5 #循环获取服务列表
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127:0.0.1

  3. 创建启动器

package com.zuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy //开启网关功能
public class Zuul {
    public static void main(String[] args) {
        SpringApplication.run(Zuul.class);
    }
}

  测试成功的页面:

技术分享图片

技术分享图片

技术分享图片

 



以上是关于认识并学会springCloud的使用的主要内容,如果未能解决你的问题,请参考以下文章

Nacos一篇学会:认识-安装-注册-配置,服务分级存储模型等

springcloud报错-------关于 hystrix 的异常 FallbackDefinitionException:fallback method wasn't found(代码片段

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段

SpringCloud系列四:Eureka 服务发现框架(定义 Eureka 服务端Eureka 服务信息Eureka 发现管理Eureka 安全配置Eureka-HA(高可用) 机制Eur(代码片段

SpringCloud Nacos 注册中心 -- 认识和安装Nacos

7天学会springCloud(一) 7个例子与7个周期