SpringCloud 实践(上)

公司之前一直使用 WebService 作为各个服务之间的通信技术,在半个月前,终于下决心用 SpringCloud 取代了 WebService。以下是我在此之前根据 Demo 写的一些实践心得。

为什么选择了 SpringCloud

其实选择 SpringCloud 之前,我是比较倾向于 Dubbo 的,毕竟 Dubbo 的底层使用 RPC 协议,从某种程度上说性能自然是比 SpringCloud 这种基于 Http 协议的更高。可是我们公司的现有的业务规模,也远远没有到拼性能的地步,使用内网调用也是很快的,我们更看重 SpringCloud 的体系比较完整,就像一个全家桶,很多东西 SpringCloud 已经把我们安排的明明白白的了,而使用 Dubbo 可能还需要我们四处去集成,比如 监控就需要自己去定制,而SpringCloud 可以无缝整合 Zipkin ,实现链路监控。出于这些原因,所以选择了 SpringCloud。

服务治理和发现

SpringCloud 本身提供了多种服务发现组件的支持,比如我们熟悉的 Zookeeper,还有 Consul 和 Eureka。我们选择了 Eureka, 是Netflix 开源的服务发现组件,本身是基于 REST 服务,SpringCloud 将它集成在子项目 SpringCloud Netflix 中,从而实现微服务的注册和发现。

因为我们必须还要考虑一个比较重要的就是如果是单节点 Eureka 挂掉了,整个服务缺了注册中心而当掉了,是一个很恐怖的事情,所以为了保证 Eureka 的高可用,我们是使用多节点的 Eureka 集群。

  • 代码流程
  1. 新建一个 maven 项目,名为 eureka ,pom 中引入
    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.5.6.RELEASE</version>
   </parent>

   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-dependencies</artifactId>
               <version>Edgware.RELEASE</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>

   <dependencies>

       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.16.18</version>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-eureka-server</artifactId>
       </dependency>

   </dependencies>
   
  1. 新建一个主类 App.class

@SpringBootApplication
@EnableEurekaServer
public class App {

   public static void main(String[] args) {
       System.out.println("------------------- start -------------------");
       SpringApplication.run(App.class, args);
       System.out.println("-------------------  end  -------------------");
   }

}

  1. application.yml 如下

app:
   name: register

spring:
 application:
   name: eureka

---
spring:
 profiles: peer1

server:
   port: 9080

eureka:
 instance:
   hostname: localhost
 client:
   service-url:
      defaultZone: http://localhost:9070/eureka/

---
spring:
 profiles: peer2

server:
   port: 9070

eureka:
 instance:
   hostname: localhost
 client:
   service-url:
      defaultZone: http://localhost:9080/eureka/

这里就是使用通过多个实例相互注册的方式实现高可用部署,Eureka 实例会彼此增量的同步信息,从而确保所有节点数据一致。
使用 Spring 的多配置,在启动脚本上选择启动的配置。

  • 启动步骤

    1. mvn package
    2. 将打包生成的 eureka-server.jar 复制到两个文件夹
    3. 在第一个文件夹 执行 java -jar eureka-server.jar --spring.profiles.active=peer1
    4. 在第二个文件夹 执行 java -jar eureka-server.jar --spring.profiles.active=peer2
    5. 浏览器打开 http://localhost:9080 或者 http://localhost:9070 查看

服务生产者

SpringCloud 的服务生产者比较朴素,说白了就是一个个接口,暴露出来,注册到 Eureka 中,不仅别的微服务可以调用,Web、Android 和 IOS 也是可以调用的。 我们的做法是把服务生产者的协议和项目分成两个 Module ,协议打包成 jar ,供消费者使用从而对生成者进行调用,而调用的方式则是 SpringCloud 推荐使用的 Feign,使用 Feign 最大的优势在于 SpringCloud 对Feign 实现了增强,使得 Feign 支持了 Spring MVC 注解,这样生产者可以直接实现 Feign 接口,使得生产者和消费者默认使用同一协议,节约代码成本。

  • 代码流程
  1. 新建一个 maven 项目,名为 autumn ,pom 中引入
 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>

    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

  1. 创建协议 Module autumnbase,pom引入

 <dependencies>

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

    </dependencies>


  1. 创建一些 model 和 传输载体,略过

  2. 创建 FeignClient 类 UserFeignClient.class, UserFallback 是 SpringCloud 的熔断机制,在使用 SpringCloud 的过程中,如果出现异常(比如超时),会降级使用 UserFallback 里面的数据,这里展示两种调用方式,一种是 GET 请求,一种是POST 请求,请求的注解看起来和 Spring MVC 一模一样,这样使得消费者和生产者的代码都更加好写。


@FeignClient(name = "autumn", fallbackFactory = UserFallback.class)
public interface UserFeignClient {

    @RequestMapping(value = "/user/get", method = RequestMethod.GET)
    AutumnResponse findById(@RequestParam("id") Integer id);

    @RequestMapping(value = "/user/add", method = RequestMethod.POST)
    AutumnResponse addUser(@RequestBody User user);

}

  1. 创建项目主体 Module autumncore ,pom 引入 其中第一个就是 上面的 协议 Module

    <dependencies>

        <dependency>
            <groupId>lindian</groupId>
            <artifactId>autumn-base</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

    </dependencies>

  1. 新建 主类 App.class

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableHystrix
public class App {

    public static void main(String[] args) {
        System.out.println("------------------- start -------------------");
        SpringApplication.run(App.class, args);
        System.out.println("-------------------  end  -------------------");
    }

}

  1. 新建 Controller,Controller 实现 协议中的 UserFeignClient ,然后 完成一个 简单的 get 和 post 请求

@RequestMapping(value = "/user")
@RestController
public class UserController implements UserFeignClient {

    private static Map<Integer, User> map = new ConcurrentHashMap<Integer, User>();

    static {
        map.put(1, new User(1, "傅红雪"));
        map.put(2, new User(2, "李寻欢"));
        map.put(3, new User(3, "任我行"));
        map.put(4, new User(4, "令狐冲"));
    }

    @RequestMapping(value = "/get", method = {RequestMethod.GET}, produces = {"application/json;charset=UTF-8"})
    @Override
    public AutumnResponse findById(Integer id) {
        AutumnResponse response = new AutumnResponse();
        User user = findUserById(id);
        if (user == null) {
            response.setStatus(AutumnResponse.STATUS_FAIL);
            return response;
        }
//        try {
//            Thread.sleep(500);
//        } catch (Exception e) {
//
//        }
        response.setUser(user);
        System.out.println(response.toString());
        return response;
    }

    @RequestMapping(value = "/add", method = {RequestMethod.POST}, produces = {"application/json;charset=UTF-8"})
    @Override
    public AutumnResponse addUser(@RequestBody User user) {
        int len = map.size();
        int id = len + 1;
        User iUser = new User(id, user.getName());
        map.put(id, iUser);
        AutumnResponse response = new AutumnResponse();
        response.setUser(iUser);
        return response;
    }

    private User findUserById(int id) {
        return map.get(id);
    }

}

  1. 项目配置,同Eureka 一样,为了保证项目的高可用,也是 使用了多节点注册

app:
    name: autumn

eureka:
  client:
    service-url:
       defaultZone: http://localhost:9080/eureka/,http://localhost:9070/eureka/
  instance:
    prefer-ip-address: true

spring:
  application:
    name: autumn
  sleuth:
    sampler:
      percentage: 1.0
  zipkin:
    base-url: http://localhost:9411


logging:
  level: info

---
spring:
  profiles: peer1

server:
    port: 9091

---
spring:
  profiles: peer2

server:
    port: 9092

  • 启动步骤

    1. mvn clean install
    2. 进入 autumncore 执行 mvn package
    3. 将打包生成的 autumn.jar 复制到两个文件夹
    4. 在第一个文件夹 执行 java -jar autumn.jar --spring.profiles.active=peer1
    5. 在第二个文件夹 执行 java -jar autumn.jar --spring.profiles.active=peer2

至此,便完成了生产者的启动

(未完待续)

SpringCloud实践(下)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容