微服务入门

                                           

目录                                           

框架选型

项目结构

项目搭建

父工程搭建

公共工程搭建

模块工程搭建  提供者8001

模块工程搭建  提供者8002

模块工程搭建  消费者80

注册中心nacos接入

nacos下载启动

 提供者8001/8002模块接入nacos

服务调用openfeign接入

服务网关gateway接入

 网关模块搭建 服务8003

 调用网关服务

 配置中心nacos接入

服务限流、降级sentinel接入

下载启动sentinel

提供者8001/8002做限流


框架选型

项目结构

项目搭建

父工程 cloud_init 依赖管理

pom文件

<?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>
    <groupId>com.mote.cloud</groupId>
    <artifactId>cloud_init</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud_init</name>

    <packaging>pom</packaging>

    <!--统一管理jar包和版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!-- log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

公共工程 cloud_init_common  定义公共实体类

pom文件

<?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>com.mote.cloud</groupId>
        <artifactId>cloud_init</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.mote.cloud</groupId>
    <artifactId>cloud_init_common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud_init_common</name>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {

    private int code;
    private String message;
    private T date;

    public CommonResult(int code, String message) {
        this(code, message, null);
    }
}
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Payment {

    private long id;
    private String serial;

}

模块工程 cloud_init_provider_payment8001  提供者8001

pom文件

<?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>
        <artifactId>cloud_init</artifactId>
        <groupId>com.mote.cloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.mote.cloud</groupId>
    <artifactId>cloud_init_provider_payment8001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud_init_provider_payment8001</name>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mote.cloud</groupId>
            <artifactId>cloud_init_common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

controller

@RestController
public class PaymentController {

    @GetMapping("/pay/get/{id}")
    public CommonResult get(@PathVariable("id") int id) {
        Payment payment = new Payment();
        payment.setId(8081).setSerial("i am 8081 provider");
        return new CommonResult(200, "查询成功", payment);
    }
}

yml

server:
  port: 8001
  
spring:
  application:
    name: cloud-payment-service

访问

模块工程 cloud_init_provider_payment8002  提供者8002

<?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>
        <artifactId>cloud_init</artifactId>
        <groupId>com.mote.cloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.mote.cloud</groupId>
    <artifactId>cloud_init_provider_payment8002</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud_init_provider_payment8001</name>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mote.cloud</groupId>
            <artifactId>cloud_init_common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

controller

@RestController
public class PaymentController {

    @GetMapping("/pay/get/{id}")
    public CommonResult get(@PathVariable("id") int id) {
        Payment payment = new Payment();
        payment.setId(8082).setSerial("i am 8082 provider");
        return new CommonResult(200, "查询成功", payment);
    }
}

yml

server:
  port: 8002

spring:
  application:
    name: cloud-payment-service

访问 

模块工程 cloud_init_consumer_order80  消费者80

yml(代码暂时先不写)

server:
  port: 80

spring:
  application:
    name: cloud-order-consumer

注册中心nacos接入

nacos下载启动

下载地址:https://github.com/alibaba/nacos/releases

windows下载zip,然后解压,免安装,点击bin/startup.cmd命令启动nacos

 访问nacos控制台,用户名和密码默认都是nacos

创建命名空间

 

 

 

 模块8001/8002提供者模块接入nacos

引入依赖

<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

模块8001/8002 yml配置

spring:
  application:
    name: cloud-payment-service
  cloud:
    nacos:
      discovery:
        namespace: cloud-dev
        server-addr: 127.0.0.1:8848
        group: group-test

模块8001/8002启动类添加注解 @EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class Application8002 {

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

}

启动模块8001/8002,访问nacos,察看实例

服务调用openfeign接入

模块consumer80引入openfeign依赖和nacos依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

模块consumer80 yml

spring:
  application:
    name: cloud-order-consumer
  cloud:
    nacos:
      discovery:
        namespace: cloud-dev
        server-addr: 127.0.0.1:8848
        group: group-test
        register-enabled: false #只发现,不注册

模块consumer80 定义PaymentFeignService(interface类型),里面的方法名称和参数保持和调用的接口一致

@Component
@FeignClient(value = "cloud-payment-service")
public interface PaymentFeignService {

    @GetMapping("/pay/get/{id}")
    CommonResult get(@PathVariable("id") int id);

}

模块consumer80 定义OrderController

@RestController
@Slf4j
public class OrderController {

    @Autowired
    private PaymentFeignService paymentFeignService;

    @GetMapping("/order/get/{id}")
    public CommonResult create(@PathVariable("id") int id) {
        return paymentFeignService.get(id);
    }

}

模块consumer80启动类新增@EnableFeignClients和@EnableDiscoveryClient注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application80 {

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

}

启动Consumer80,连续访问接口,观察负载,默认是轮询策略

服务网关gateway接入

新建网关模块 cloud_init_gateway_payment8003

pom

<?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>
        <artifactId>cloud_init</artifactId>
        <groupId>com.mote.cloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.mote.cloud</groupId>
    <artifactId>cloud_init_gateway_payment8003</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>

yml

server:
  port: 8003

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: group-test
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: payment_routh #id 随便取值,保持唯一
          uri: lb://cloud-payment-service #代理的服务名
          predicates:
            - Path=/gateway/pay/get/** #代理路径
          filters:
            - StripPrefix=1 #代理路径的过滤操作,网关真实访问路径/gateway/pay/get/**,转发到服务的路径是/pay/get/**

网关过滤器:用于鉴权、限流等

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class SafeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // TODO 鉴权和限流

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class Application8003 {

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

}

启动访问

 将模块consumer80项目中openfeign调用的服务改成网关服务

重启模块consumer80,访问

 配置中心nacos接入

已consumer80为例,接入nacos配置中心

添加依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

修改配置文件名称application.yml为bootstrap.yml(bootstrap优先级高于application),并添加内容如下

spring:
  profiles:
    active: dev
  application:
    name: cloud-order-consumer
  cloud:
    nacos:
      discovery:
        namespace: cloud-dev #命名空间
        server-addr: 127.0.0.1:8848
        group: group-test
        register-enabled: false #只发现,不注册
      config:
        namespace: cloud-dev  #命名空间
        server-addr: 127.0.0.1:8848
        file-extension: yaml #文件类型
        group: group-test

在 Nacos中,dataId的完整格式如下:

prefix−prefix−{spring-profile.active}.${file-extension}

  • prefix默认为spring.application.name的值,也可以通过配置项spring.cloud.nacos.config.prefix来配置。
  • spring.profile.active即为当前环境对应的 profile,详情可以参考 Spring Boot文档。注意:当spring.profile.active为空时,对应的连接符 - 也将不存在,datald 的拼接格式变成prefix.prefix.{file-extension}
  • file-exetension为配置内容的数据格式,可以通过配置项spring .cloud.nacos.config.file-extension来配置。目前只支持properties和yaml类型。
  • 通过Spring Cloud 原生注解@RefreshScope实现配置自动更新

 在nacos控制台新建配置文件

 写一个TestController用于配置测试

@RestController
@Slf4j
@RefreshScope  // 实时刷新配置
public class TestController {

    @Value("${test}")
    private String test;

    @GetMapping("/order/test")
    public String test() {
        return test;
    }

}

 启动,访问测试

服务限流、降级sentinel接入

下载启动sentinel

下载地址:https://github.com/alibaba/Sentinel/releases 

 下载jar包到本地,使用java -jar xxx运行,访问sentinel控制台,地址:127.0.0.1:8080,默认端口8080,用户名和密码默认sentinel

模块provider8001/8002改造(以8081为例,接入sentinel做限流)

引入pom

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

修改PaymentController

@RestController
public class PaymentController {

    @GetMapping("/pay/get/{id}")
    @SentinelResource(value = "pay-get", blockHandler = "blockHandler", fallback = "fallbackHandler")
    public CommonResult get(@PathVariable("id") int id) {
        // int i = 1/0;
        Payment payment = new Payment();
        payment.setId(8081).setSerial("i am 8081 provider");
        return new CommonResult(200, "查询成功", payment);
    }

    /**
     * 针对BlockException做处理,也就是触发了sentinel配置的策略后的兜底方法
     */
    public CommonResult blockHandler(int id, BlockException exception) {
        return new CommonResult(200, "blockHandler");
    }

    /**
     * 针对程序异常做处理,程序异常直接走这个方法
     */
    public CommonResult fallbackHandler(int id) {
        return new CommonResult(200, "fallbackHandler");
    }
}

yml

spring:
  application:
    name: cloud-payment-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: group-test
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080

查看sentinel控制台,观察服务是否注册,若没有,先访问/pay/get/{id}接口,再查看

配置流控规则

 浏览器访问接口测试,一秒内第3次往后的请求会被拒绝,直接进入兜底方法

配置sentinel配置持久化,因为sentinel配置只是暂时的,项目重启,配置好的策略就不见了,所以需要把策略持久化起来,解决方案是集成nacos,持久化到nacos中。

引入pom

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

yml

spring:
  application:
    name: cloud-payment-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: group-test
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-limit.json
            groupId: group-test
            data-type: json
            rule_type: flow

配置nacos

resource:资源名称
limitApp:来源应用
grade:阀值类型,0:线程数,1:QPS
count:单机阀值
strategy:流控模式,0:直接,1:关联,2:链路
controlBehavior:流控效果,0:快速失败,1:warmUp,2:排队等待
clusterMode:是否集群

重启模块provider8081观察sentinel或者访问接口,如果限流存在则持久化成功

服务调用openFeign配置sentinel

改造consumer80

pom添加sentinel依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置openfeign支持sentinel

feign:
  sentinel:
    enabled: true

配置兜底方法的两种方式

方式一:实现服务调用类,实现兜底方法,注解指定

public class PaymentServiceFallback implements PaymentFeignService {
    @Override
    public CommonResult get(int id) {
        return new CommonResult(201,"调用失败");
    }
}
@Component
@FeignClient(value = "cloud-gateway", fallback = PaymentServiceFallback.class)
public interface PaymentFeignService {

    @GetMapping("/gateway/pay/get/{id}")
    CommonResult get(@PathVariable("id") int id);

}

方式二:实现FallbackFactory,注解指定

public class PaymentServiceFallbackFactory implements FallbackFactory<PaymentFeignService> {
    @Override
    public PaymentFeignService create(Throwable throwable) {
        return new PaymentFeignService() {
            @Override
            public CommonResult get(int id) {
                return new CommonResult(201,"服务调用失败");
            }
        };
    }
}
@Component
@FeignClient(value = "cloud-gateway", fallbackFactory = PaymentServiceFallbackFactory.class)
public interface PaymentFeignService {

    @GetMapping("/gateway/pay/get/{id}")
    CommonResult get(@PathVariable("id") int id);

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值