一、SpringCloud概述

1.什么是微服务:

http://www.martinfowler.com/articles/microservices.html)

2.微服务具备的特征

   A.每个微服务都可独立运行在自己的服务进程中;

  B.一系列独立运行的微服务共同搭建起整个系统;

  C.每个服务为独立的业务开发,一个微服务一般完成某个特定的功能,比如:订单管理,商品管理等;

  D.微服务之间通过一些轻量的童鞋机制进行通信,例如:通过REST API或者RPC的方式进行调用。

3.优点

  易于开发和维护;启动较快;局部修改容易部署;技术栈不受限;按需伸缩;DevOps

4.挑战

   运维要求较高;分布式的复杂性;接口调用成本高;重复劳动

5.设计原则

   单一职责原则,服务自治原则,轻量级通信原则,接口明确原则

二、创建服务注册中心

    服务注册中心我需要使用组件上Spring Cloud Netflix的Eureka,eureka只用一个服务注册和发现模块。我们可以将自己定义的API接口注册到Spring Cloud Eureka上,Eureka服务服务的注册与发现。构成Eureka体系包括:服务注册中心、服务提供者、服务消费者。

微服务项目如何部署到宝塔 微服务平台搭建_微服务

上图描述了(图片来源于网络):

  A.两天Eureka服务注册中构成的注册复制集群;

  B.然后服务提供者想注册中心进行注册、续约、下线服务等;

  C.服务消费者向Eureka注册中拉去服务列表并维护在本地;

  D.然后服务消费者根据从Eureka服务注册中心获取的服务列表选取一个服务提供者进行消费服务。

1.创建一个web-app的maven工程。此处命名为:springcloud;

微服务项目如何部署到宝塔 微服务平台搭建_微服务_02

在该工程下创建module;快速创建一个名为eureka的springboot工程。 

微服务项目如何部署到宝塔 微服务平台搭建_ci_03

勾选Eureka Server。注意springboot版本,建议使用2.0以上版本

微服务项目如何部署到宝塔 微服务平台搭建_spring_04

2.创建好之后,看下pom.xml是否导入了依赖

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

3.在启动类中加入注解@EnableEurekaServer

package com.springcloud.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @EnableEurekaServer 启动一个服务注册中心提供给其他应用进行对话
 *     @EnadbleEuredaServe Import导入了EurekaMarkerConfiguration类,eurekaServerMarkerBean会往Spring容器中注入一个空类Marker;
 *     Marker类是一个开关标志,用了激活EurekaServerAutoConfiguration类。
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }

}

4.将application.properties修改为application.yml,添加配置

server:
  port: 8761

spring:
  application:
    name: eureka

eureka:
  instance:
    hostname: localhost 
  client:
    register-with-eureka: true #false:即禁止自己注册自己
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #配置服务注册中心访问地址

访问:http://localhost:8761/

微服务项目如何部署到宝塔 微服务平台搭建_微服务_05

可以看到,此时注册中心注册了自己;一般我们都会禁止注册中心注册自己。修改application.yml中register-with-eureka: false即可

三、创建服务生产者

1.快速创建一个名为client的springboot工程

微服务项目如何部署到宝塔 微服务平台搭建_ci_06

 

我这为了方便测试,加入了myql、mybatis和Web开发相关组件;pom.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springcloud</groupId>
    <artifactId>client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <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>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.在启动类ClientApplication.java中加入注解@EnableEurekaClient

package com.springcloud.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @EnableEurekaClient  表明自己是一个生产者
 */
@SpringBootApplication
@EnableEurekaClient
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

3.application.yml配置

#配置服务注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

spring:
  application:
    name: service-client
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/dny_website?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver

server:
  port: 8765

mybatis:
  mapper-locations: classpath:mapping/*Mapper.xml
  type-aliases-package: com.springcloud.client.entity


logging:
  level:
    com:
      springcloud:
        client:
          Dao: debug

项目结构(springboot整合mybatis这里就不细说了,有兴趣的可以看下这篇博客:)

微服务项目如何部署到宝塔 微服务平台搭建_微服务项目如何部署到宝塔_07

控制层代码:

package com.springcloud.client.Controller;

import com.springcloud.client.entity.Admin;
import com.springcloud.client.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/admin")
public class AdminController {
    @Autowired
    private AdminService adminService;

    @RequestMapping("/list")
    public List<Admin> home(Integer permissions){
        return adminService.adminList(permissions);
    }
}

4.启动测试

启动服务提供者项目后,查看注册中心

微服务项目如何部署到宝塔 微服务平台搭建_微服务项目如何部署到宝塔_08

 

使用postman进行测试:

微服务项目如何部署到宝塔 微服务平台搭建_spring_09

四、创建服务消费者

方式一:ribbon+RestTemplate

   创建一个名为ribbon的springboot项目。

微服务项目如何部署到宝塔 微服务平台搭建_ci_10

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springcloud</groupId>
    <artifactId>ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ribbon</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.application.yml配置

eureka:
    client:
        serviceUrl:
            defaultZone: http://localhost:8761/eureka/
server:
    port: 8762
spring:
    application:
        name: service-ribbon

 3.启动类加入注解@EnableDiscoveryClient

package com.springcloud.ribbon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class RibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonApplication.class, args);
    }

    /**
     * 加入restTemplate以消费相关的服务。
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate()
    {
        return new RestTemplate();
    }
}

4.创建Service和Contoller

package com.springcloud.ribbon.service;

import com.springcloud.customer.entity.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.List;

@Service
public class RibbonService {
    @Autowired
    private RestTemplate restTemplate;

    public String StringServcie(){
        return restTemplate.getForObject("http://SERVICE-CLIENT/admin/string",String.class);
    }

    public List<Admin> ListService(Integer permissions){
        /**
         * 方法getForObject(url,?.class)中的url必须使用服务提供者的项目名称“CLIENT”,不能使用IP地址
         * RestTemplate接收List集合数据时,必须用数组接收
         */
        Admin[] admin=restTemplate.getForObject("http://SERVICE-CLIENT/admin/list?permissions="+permissions,Admin[].class);
        for(Admin a:admin){
            System.out.println(a.getAdmin_name());
        }
        List<Admin> list= Arrays.asList(admin);
        return list;
    }
}
package com.springcloud.ribbon.controller;

import com.springcloud.customer.entity.Admin;
import com.springcloud.customer.service.RibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/ribbon")
public class RibbonController {
    @Autowired
    private RibbonService testService;
    @RequestMapping("/string")
    public String findString(){
        return testService.StringServcie();
    }
    @RequestMapping("/list")
    public List<Admin> AdminList(Integer permissions){
        return testService.ListService(permissions);
    }
}

测试:

微服务项目如何部署到宝塔 微服务平台搭建_ci_11

方式二:Feign

创建项目,导入依赖;pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springcloud</groupId>
    <artifactId>customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>customer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8764
spring:
  application:
    name: service-feign
#feign的配置,连接超时及读取超时配置
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic

主类CustomerApplication:

package com.springcloud.customer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @EnableDiscoveryClient 声明自己是一个服务消费者
 * @EnableFeignClients 启用feign客户端
 */

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class CustomerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomerApplication.class, args);
    }
}

创建Service和Controller:

package com.springcloud.customer.service;

import com.springcloud.customer.entity.Admin;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;


import java.util.List;

/**
 * feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,
 * 可在使用Feign时提供负载均衡的http客户端。
 */
@FeignClient(value = "service-client")
public interface FeignService {
    @RequestMapping("/admin/string")
    public String StringService();

    @PostMapping("/admin/list")
    public List<Admin> FeignList(@RequestParam("permissions")Integer permissions);
}
package com.springcloud.customer.controller;

import com.springcloud.customer.entity.Admin;
import com.springcloud.customer.service.FeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/feign")
public class FeignController {
    @Autowired
    private FeignService feignService;
    @RequestMapping("/string")
    public String FeignString(){
        return feignService.StringService();
    }
    @RequestMapping("/list")
    public List<Admin> FeignList(Integer permissions){
        return feignService.FeignList(permissions);
    }
}

测试:

微服务项目如何部署到宝塔 微服务平台搭建_spring_12

SpringCloud搭建(下)------断路器(Netflix Hystrix)+网关(Netflix Zuul)+配置中心(Spring Cloud Config)