一:微服务

1.0:单体架构

MVC架构,分层开发,所有的功能都在一个系统里面

在这里插入图片描述

优点:
1:部署简单: 由于是完整的结构体,可以直接部署在一个服务器上即可。
2:技术单一: 项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发。
3:用人成本低: 单个程序员可以完成业务接口到数据库的整个流程。

缺点:
1:系统启动慢, 一个进程包含了所有的业务逻辑,涉及到的启动模块过多,导致系统的启动、重启时间周期过长;
2:系统错误隔离性差、可用性差,任何一个模块的错误均可能造成整个系统的宕机;
3:可伸缩性差:系统的扩容只能只对这个应用进行扩容,不能做到对某个功能点进行扩容;
4:线上问题修复周期长:任何一个线上问题修复需要对整个应用系统进行全面升级。
5. 跨语言程度差
6. 不利于安全管理,所有开发人员都拥有全量代码

结论:单体架构不适合互联网(访问量大、业务复杂)项目,只适合传统项目(政府、学校、外包)

1.1:微服务架构

译文:

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP 协议的RESTfulAPI )。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

解读微服务特点:

1:微服务是一种项目架构思想(风格)

2:微服务架构是一系列小服务的组合

3:任何一个微服务,都是一个独立的进程

4:轻量级通信(跨语言,跨平台)

5:服务粒度(围绕业务功能拆分)

6:去中心化管理(不依赖某一种语言)

1.2:微服务架构的优势

1、是每个微服务组件都是简单灵活的,能够独立部署。不再像以前一样,应用需要一个庞大的应用服务器来支撑。

2、可以由一个小团队负责更专注专业,相应的也就更高效可靠。

3、微服务之间是松耦合的,微服务内部是高内聚的,每个微服务很容易按需扩展。

4、微服务架构与语言工具无关,自由选择合适的语言和工具,高效的完成业务目标即可。

1.3:微服务架构的缺点(挑战)

1、依赖服务变更很难跟踪,其他团队的服务接口文档过期怎么办,依赖的服务没有准备好,如何验证我开发的功能。

2、微服务放大了分布式架构的系列问题,如分布式事务怎么处理,依赖服务不稳定怎么办?

3、运维复杂度陡增,如:部署物数量多、监控进程多导致整体运维复杂度提升。

1.4:SpringCloud与微服务关系

  • springcloud为微服务思想提供了完美的解决方案

  • springcloud是一些列框架的集合体(微服务全家桶、服务的注册与发现、分布式事务、服务降级、服务熔断、服务限流。。。。)

    一般我们说springcloud 其实指的是 springcloud-netflix,springcloud并不是造轮子,只是把netflix公司的组件做二次开发

  • springcloud基于springboot实现

1.5:SpringBoot和SpringCloud关系

  • SpringBoot专注于快速方便的开发单个个体微服务。

  • SpringCloud是关注全局的微服务协调、整理、治理的框架,它将SpringBoot开发的单体整合并管理起来。

  • SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系。

二:服务注册与发现

2.0:相关概念

分布式服务:一个完整的功能,拆分给不同的服务去实现,每个服务完成特定的功能。

服务集群:一个服务可以部署多个服务实例(进程),形成一个服务集群

负载均衡:在集群的环境下,采用相应的负载均衡策略,平均化服务的负载问题

2.1:什么是服务注册与发现

服务注册:将服务注册到注册中心,注册中心维护服务的元数据信息

服务发现:服务的调用者,可以从注册中心根据应用名获取服务列表,客户端做负载均衡。

在这里插入图片描述

2.2:注册中心对比

nacos:是阿里开源的,经过了阿里实践的

eureka:netflix公司的,现在不维护了,不开源了

在这里插入图片描述

2.3:who is using

在这里插入图片描述

三:nacos简介与安装

官网:https://nacos.io/zh-cn/docs/what-is-nacos.html

3.1:nacos功能与架构

nacos架构:

在这里插入图片描述

nacos功能:

  • 名字服务 (Naming Service)

    命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息
    

  • 配置服务 (Configuration Service)

    动态配置服务让您能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。
    

3.2:nacos安装

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

  • 源码编译安装(不推荐)

    git clone https://github.com/alibaba/nacos.git
    cd nacos/
    mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  
    ls -al distribution/target/
    
    // change the $version to your actual path
    cd distribution/target/nacos-server-$version/nacos/bin
    
    
  • 解压安装(推荐)

第一步:解压

第二步:配置(conf>application.properties)


#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=123456

第三步:在mysql中创建nacos数据库

第四步:在nacos中建表(建表语句在conf>nacos-mysql.sql)

第五步:修改bin>startup.cmd

nacos-1.3.2之后默认使用的【集群方式】启动,需要手动改为standalone单机模式(编辑startup.cm文件)

在这里插入图片描述

双击bin>startup.cmd,启动成功

3.3:nacos工作原理

在这里插入图片描述

四:微服务入门案例

4.1:boot与cloud版本

springboot:提供了快速开发微服务的能力
springcloud提供了微服务治理的能力(服务注册与发现、服务降级、限流、熔断、网关、负载均衡、配置中心...),为微服务开发提供了全家桶服务

springboot的版本查看地址:https://spring.io/projects/spring-boot#learn

springcloud的版本查看地址:https://spring.io/projects/spring-cloud#overview

详细版本对应信息查看:https://start.spring.io/actuator/info

在这里插入图片描述

注意:
如果采用springboot和springcloud(springcloud netflix)那么使用以上版本对应就ok了,
但是如果要使用alibaba的组件(nacos、sentinel、RocketMQ、Seata)必须使用springcloud alibaba

4.2:SpringCloud-alibaba

Springcloud与springcloud-alibaba关系

◆ 我们通常说的SpringCloud,泛指Spring Cloud Netflix,也是springcloud第一代
◆ SpringCloud Alibaba是SpringCloud的子项目,是阿里巴巴结合自身微服务实践,
◆ SpringCloud Alibaba符合SpringCloud标准,依赖于springcloud

在这里插入图片描述

4.3:确定版本

确定方式:通过查看springcloud alibaba 官网确定

https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

Spring Cloud VersionSpring Cloud Alibaba VersionSpring Boot Version
Hoxton.SR82.2.3.RELEASE2.3.2.RELEASE
Greenwich.SR62.1.3.RELEASE2.1.13.RELEASE
Hoxton.SR82.2.2.RELEASE2.3.2.RELEASE
Hoxton.SR32.2.1.RELEASE2.2.5.RELEASE
Hoxton.RELEASE2.2.0.RELEASE2.2.X.RELEASE
Greenwich2.1.2.RELEASE2.1.X.RELEASE
Finchley2.0.3.RELEASE2.0.X.RELEASE
Edgware1.5.1.RELEASE(停止维护,建议升级)1.5.X.RELEASE

最终决定(版本号记忆):

springcloud-alibaba: 2.2.3.RELEASE

springcloud: Hoxton.SR8

springboot: 2.3.2.RELEASE

4.4:创建父工程

父工程锁定springboot、springcloud、springcloud-alibaba版本

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>2.2.3.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Hoxton.SR8</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.3.2.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>

4.5:服务提供者(wfx-goods)

nacos学习文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc

4.5.1: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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>wfx-parent</artifactId>
        <groupId>com.wfx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>wfx-goods</artifactId>

    <dependencies>
        <!-- 微服务是web工程,所以必须依赖web       -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--    端点监控,监控微服务的状态    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 服务注册与发现  -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

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



</project>

4.5.2:application.properties

server.port=8001
#微服务的服务名
spring.application.name=wfx-goods
#nacos server的地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#开启所有的端点监控
management.endpoints.web.exposure.include=*

4.5.3:启动类加注解

package com.wfx;


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

@SpringBootApplication
@EnableDiscoveryClient//开启服务注册与发现
public class GoodsApplication {

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

}

4.5.4:查询商品接口

package com.wfx.web;

import com.wfx.goods.Goods;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/goods")
public class GoodsController {

    @GetMapping("findById")
    public Goods findById(String goodsId){

        return  new Goods(12,"华为meta10",1000);
    }

}

4.6:服务消费者

4.6.1: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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>wfx-parent</artifactId>
        <groupId>com.wfx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>wfx-order-service</artifactId>

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

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

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


    </dependencies>

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

4.6.2:application.properties

server.port=9001
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.application.name=wfx-order

4.6.3:启动类加注解

package com.wfx;

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.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * <p>title: com.wfx</p>
 * <p>Company: wendao</p>
 * author zhuximing
 * date 2020/10/26
 * description:
 */
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {

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

    //实例化 RestTemplate 实例
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){

        return new RestTemplate();
    }

}

4.6.4:保存订单接口

package com.wfx.web;

import com.wfx.goods.Goods;
import com.wfx.order.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>title: com.wfx.web</p>
 * <p>Company: wendao</p>
 * author zhuximing
 * date 2020/10/26
 * description:
 */
@RestController
@RequestMapping("/order")
public class OrderController {


    @Autowired
    private RestTemplate restTemplate;

    private String baseURL="http://wfx-goods:8001/";

    @PostMapping("save")
    public Map save(@RequestBody Order order){

        //1:获取商品信息(发送http请求)
        Goods goods = restTemplate.getForObject(baseURL + "goods/findById?goodsId=" + order.getGoodsId(), Goods.class);
        System.out.println(goods);

        //2:保存订单
        System.out.println("保存订单成功");

        return  new HashMap(){{
            put("msg","save order success");
            put("code",200);
        }};
    }


}

4.6.5:nacos领域模型

当业务系统越来越繁杂的时候,微服务会越来越多,可以进行分namespace、group进行管理

不同的group的微服务是相互隔离的

不同的namespace的微服务是相互隔离的

在这里插入图片描述

演示:服务发布的时候指定namespace和group

第一步:在nacos server控制台创建一个namespace

第二步:服务注册与发现,指定namespace和group

spring.cloud.nacos.discovery.namespace=3cadb64d-6b4c-4f84-b25f-ceb34c948951
spring.cloud.nacos.discovery.group=my-group

4.6.6:微服务集群演示

1:启动wfx-goods-service服务集群
#如果不指定端口,那么微服务启动时使用8001,如果指定端口,那么微服务就在指定端口启动
server.port=${port:8001}

8001
在这里插入图片描述

8002

在这里插入图片描述

2:演示负载均衡

默认就是轮询负载均衡

五:RestTemplate

5.1:什么是RestTemplate

1:RestTemplate是java模拟浏览器发送http请求的工具类
2:RestTemplate基于`Apache`的`HttpClient`实现。HttpClient使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是`RestTemplate`。
RestTemplate了解即可,在开发环境不会用,开发使用OpenFeign

5.2:ForObject

get请求

Map goods = restTemplate.getForObject(BaseURL+"findGoodsById?goodsId=12", Map.class);
System.out.println(goods.get("goodsName"));

post请求(发送的是json串)

Map goods = restTemplate.postForObject(BaseURL + "/save", new Goods("huawei", 99.99), Map.class);
System.out.println(goods.get("code"));

提示:

1:微服务之间数据传输格式统一为json
2:entity的空构造方法要提供
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods  {

      private String goodsName;
      private double price;

}

5.3:ForEntity

get请求

ResponseEntity<Goods> forEntity = restTemplate.getForEntity(BaseURL + "findGoodsById?goodsId=12", Goods.class);

System.out.println("http status:"+forEntity.getStatusCode());
System.out.println("http response body:"+forEntity.getBody());

post请求

ResponseEntity<Map> responseEntity = restTemplate.postForEntity(BaseURL + "/save", new Goods("huawei", 99.99), Map.class);

System.out.println("http status:"+responseEntity.getStatusCode());
System.out.println("http response body:"+responseEntity.getBody());

六:负载均衡器Ribbon

6.1:Ribbon简介

Ribbon是Netflix公司开源的一个负载均衡的项目,是一个"客户端"负载均衡器,运行在客户端上

客户端负载均衡

在这里插入图片描述

服务器端负载均衡

在这里插入图片描述

6.2:Ribbon在项目中怎么使用

第一步:pom依赖

springcloud alibaba 对Ribbon做了兼容

在这里插入图片描述

第二步:@LoadBalanced注解


@Bean
@LoadBalanced
public RestTemplate restTemplate(){

    return new RestTemplate();
}

6.3:Ribbon的工作流程

1:wfx-order-service,wfx-goods-service(2个实例),它们都会向注册中心注册服务

2:注册中心记录集群元数据信息,即应用名与ip:port映射

3:Ribbon拦截所有的请求,从请求信息中获取请求应用名

4:Ribbon根据应用名从nacos注册中心获取服务列表

5:ribbon从服务列表中通过相关均衡策略(Rules)获取具体某个实例

6:请求远程服务

6.4:Ribbon源码追踪

第一步:LB自动配置

LoadBalancerAutoConfiguration是Ribbon的自动配置类,在这个配置类里面配置了一个拦截器(LoadBalancerInterceptor),该拦截器会拦截所有请求,这就是Ribbon的入口

在这里插入图片描述

第二步:LB拦截器

LoadBalancerInterceptor拦截所有的请求,获取应用名

在这里插入图片描述

第三步:LB客户端(RibbonLoadBalancerClient)

LoadBalancerClient:接口

RibbonLoadBalancerClient:实现类

RibbonLoadBalancerClient.execute()

RibbonLoadBalancerClient.getServer(loadBalancer, hint)

DynamicServerListLoadBalancer.chooseServer(本类没有,父类有该方法)

ZoneAvoidanceRule.choose(本类没有,父类有该方法)

略名策略声明策略描述实现说明
BestAvailableRulepublic class BestAvailableRule extends ClientConfigEnabledRoundRobinRule选择一个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRulepublic class AvailabilityFilteringRule extends PredicateBasedRule过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRulepublic class WeightedResponseTimeRule extends RoundRobinRule根据相应时间分配一个weight,x响应时间越长,weight越小,被选中的可能性越低。一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。
RetryRulepublic class RetryRule extends AbstractLoadBalancerRule对选定的负载均衡策略机上重试机制。在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRulepublic class RoundRobinRule extends AbstractLoadBalancerRuleroundRobin方式轮询选择server轮询index,选择index对应位置的server
RandomRulepublic class RandomRule extends AbstractLoadBalancerRule随机选择一个server在index上随机,选择index对应位置的server
ZoneAvoidanceRule(默认)public class ZoneAvoidanceRule extends PredicateBasedRule复合判断server所在区域的性能和server的可用性选择server使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

6.5:切换Ribbon负载均衡策略

package com.wfx.rule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
//注意这个配置类必须放在@ComponentScan默认扫描的范围外
@Configuration
public class MyRule {

    @Bean
    public IRule getRule(){
        return  new RoundRobinRule();
    }

}

在这里插入图片描述

6.6:解释为什么nacos关掉还能继续访问

问题:服务消费者一旦成功调用一次,nacos server关闭后还能继续访问?

答:当消费者第一次访问成功后,会将服务列表在本地做缓存,只要服务提供者不宕机(ip端口不变),那么能一直调用

​ 但是实际生产(服务提供者宕机、服务提供者会增加实例、服务提供者ip和端口会发生变化)

定时(30s)更新nacos client本地缓存的源码

DynamicServerListLoadBalancer.updateListOfServers
//从nacos server获取最新的实例列表
NacosServerList.getServers

七:nacos集群搭建

在实际生产环境中,必须保证Nacos高可用,否则一旦Nacos宕机,整个平台都会无法运行

7.1:nacos集群架构

在这里插入图片描述

7.2:nacos集群搭建

1:nacos推荐搭建在linux服务器

2:伪集群,1台服务器搭建多个nacos实例,通过不同端口区分

3:真集群,nacos实例搭建在不同的服务器里面(生产推荐的)

7.2.1:集群规划

服务名ip端口备注
nacos实例1192.168.234.1318848
nacos实例2192.168.234.1318858
nacos实例3192.168.234.1318868
nginx192.168.234.13180反向代理nacos3个实例
mysql192.168.234.1313306存储nacos数据

7.2.2:详细步骤

第一步:上传nacos包到linux服务器并解压

tar -zxvf nacos-server-1.3.2.tar.gz -C /export/server/

第二步:修改nacos连接数据库信息和服务ip

cd /export/server/nacos/conf/
vim application.properties
### Specify local server's IP:
nacos.inetutils.ip-address=192.168.234.131

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://192.168.234.131:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=Admin123!

第三步:修改/export/server/nacos/bin/startup.sh 的JAVA_OPT

虚拟机内存调大到2G

原设置:
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
修改后:
JAVA_OPT="${JAVA_OPT} -server -Xms300m -Xmx300m -Xmn100m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=160m"

第四步:配置/export/server/nacos/conf/cluster.conf配置文件

修改集群配置文件的文件名

cp cluster.conf.example cluster.conf

192.168.234.122:8848
192.168.234.122:8858
192.168.234.122:8868

第五步:复制三份,同时修改监听端口

[root@zhuxm01 server]# cp nacos/   nacos8848 -r
[root@zhuxm01 server]# cp nacos/   nacos8858 -r
[root@zhuxm01 server]# cp nacos/   nacos8868 -r

第六步:分别启动nacos实例

创建nacos-cluster-startup.sh

sh /export/server/nacos8848/bin/startup.sh
sh /export/server/nacos8858/bin/startup.sh
sh /export/server/nacos8868/bin/startup.sh
echo "nacos-cluster-starting !!!!!"

第七步:修改服务(提供者、生产者)注册地址

建议使用springboot多环境切换

spring.cloud.nacos.discovery.server-addr=192.168.234.122:8848,192.168.234.122:8858,192.168.234.122:8868

第八步:配置nginx反向代理(可选)

upstream  nacos-cluster {
       server    192.168.234.122:8848;
       server    192.168.234.122:8858;
       server    192.168.234.122:8868;
     }

server {
        listen       80;
        server_name  www.nacos.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
           proxy_pass http://nacos-cluster/;
        }
}

八:Spring Cloud OpenFeign

作为Spring Cloud的子项目之一,Spring Cloud OpenFeign 是一种声明式、模板化的 HTTP 客户端,在 Spring Cloud 中使用 OpenFeign,可以做到使用 HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。同时OpenFeign通过集成Ribbon实现客户端的负载均衡

8.1:演示案例说明

wfx-order为服务消费者

wfx-jifen为服务提供者

功能1:添加订单,生成一条积分记录

功能2:修改订单,修改积分记录

功能3:删除订单,删除积分记录

功能4:查询订单,获取积分记录

8.2:新建积分微服务

8.2.1:pom依赖

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

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

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

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

8.2.2:application.properties

server.port=8003
spring.application.name=wfx-jifen
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
management.endpoints.web.exposure.include=*

8.2.3:启动类

@SpringBootApplication
@EnableDiscoveryClient
public class JifenApplication {

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

}

8.2.4:暴露接口

package com.wfx.web;

import com.wfx.jifen.Jifen;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("/jifen")
public class JifenController {

    @PostMapping(value = "/save")
    public Map save(@RequestBody Jifen jifen) {

        System.out.println("调用了积分保存接口");
        System.out.println(jifen);
        return new HashMap(){{
            put("isSuccess",true);
            put("msg","save success");
        }};

    }
 
    @PostMapping(value = "/update")
    public Map update(@RequestBody Jifen jifen) {

        System.out.println(jifen);
        return new HashMap(){{
            put("isSuccess",true);
            put("msg","update success");
        }};
 
    }
 
 
 
    @GetMapping(value = "/delete")
    public Map deleteById(Integer jifenId) {
        System.out.println("删除id为"+jifenId+"的积分信息");
        return new HashMap(){{
            put("isSuccess",true);
            put("msg","delete success");
        }};

    }
 
 
 
 
    @GetMapping(value = "/{jifenId}")
    public Jifen findJifenById(@PathVariable Integer jifenId) {
        System.out.println("已经查询到"+jifenId+"积分数据");
        return new Jifen(jifenId, 12,jifenId+"号积分");
    }
 
 
    @GetMapping(value = "/search")
    public Jifen search(Integer uid,String type) {
        System.out.println("uid:"+uid+"type:"+type);
        return new Jifen(uid, 12,type);
    }
 
    @PostMapping(value = "/searchByEntity")
    public List<Jifen> searchMap(@RequestBody  Jifen jifen) {
 
        System.out.println(jifen);
 
        List<Jifen> jifens = new ArrayList<Jifen>();
        jifens.add(new Jifen(110,12,"下单积分"));
        jifens.add(new Jifen(111,18,"支付积分"));
        return  jifens;
    }
 
}

8.3:wfx-order集成openfeign

8.3.1:openfeign依赖

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

在这里插入图片描述

8.3.2:接口声明-保存积分

http接口的声明

@Component
@FeignClient("wfx-jifen")
public interface IJifenBiz {
    @PostMapping(value = "/jifen/save")
    public Map save(@RequestBody Jifen jifen) ;
}

8.3.3:接口远程调用-保存积分

 @Autowired
    private IJifenBiz iJifenBiz;
    @PostMapping("save")
    public ResultVo save(@RequestBody Order order){

        //保存订单
        System.out.println("保存订单成功");
        //保存积分
        Jifen jifen = new Jifen(order.getUid(),12,"下单积分");
        iJifenBiz.save(jifen);
        return new ResultVo(true,"save success");
    }

8.3.4:postman测试

8.4.1:接口声明-修改积分

@PostMapping(value = "/jifen/update")
public Map update(@RequestBody Jifen jifen);

8.4.2:接口远程调用-修改积分

@PostMapping("update")
public ResultVo update(@RequestBody Order order){

    //修改订单
    System.out.println("修改订单成功");
    //修改积分
    Jifen jifen = new Jifen(order.getUid(),12,"修改积分");
    iJifenBiz.update(jifen);
    return new ResultVo(true,"save success");
}

8.4.3:postman测试

8.5.1:接口声明-删除积分

@GetMapping(value = "/jifen/delete")
public Map deleteById(@RequestParam("jifenId") String jifenid) ;

8.5.2:接口调用-删除积分

 @GetMapping("delete")
    public ResultVo delete(String orderNum){

        //删除订单
        System.out.println("删除订单成功");
        //删除订单的积分
        iJifenBiz.deleteById("188");
        return new ResultVo(true,"save success");
    }

8.5.3:post测试

8.6.1:接口声明-根据id获取积分

@GetMapping(value = "/jifen/{jifenId}")
public Jifen findJifenById(@PathVariable("jifenId") Integer jifenId);

8.6.2:接口调用-根据id获取积分

@GetMapping("findByOrderNum")
public ResultVo findByOrderNum(String orderNum){
    //获取订单
    System.out.println("获取订单");
    //获取订单的积分
    Jifen jifen = iJifenBiz.findJifenById(123);
    System.out.println("远程获取到积分信息"+jifen);
    return new ResultVo(true,"save success");
}

8.6.3:post测试

8.7.1:声明接口-查询积分

@GetMapping(value = "/jifen/search")
public Jifen search(@RequestParam("uid") Integer uid,@RequestParam("type") String type);

8.7.2:调用接口-查询积分

@GetMapping("findByOrderNum1")
public ResultVo findByOrderNum1(String orderNum){
    //获取订单
    System.out.println("获取订单");
    //获取订单的积分
    Jifen jifen = iJifenBiz.search(123,"关注获取积分");
    System.out.println("远程获取到积分信息"+jifen);
    return new ResultVo(true,"save success");
}

8.7.3:postman测试

8.8.1:声明接口-查询积分

@PostMapping(value = "/jifen/searchByEntity")
public List<Jifen> searchByEntity(@RequestBody  Jifen jifen);

8.8.2:调用接口-查询积分

@GetMapping("findByOrderNum2")
public ResultVo findByOrderNum2(String orderNum){
    //获取订单
    System.out.println("获取订单");
    //获取订单的积分
    List<Jifen> jifens = iJifenBiz.searchByEntity(new Jifen(88, 56, "下单积分"));

    for (Jifen jifen : jifens) {
        System.out.println("远程获取到积分信息"+jifen);
    }

    return new ResultVo(true,"save success");
}

8.7.4:postman测试

8.4:OpenFeign超时控制

Feign 的[负载均衡底层用的就是 Ribbon

在application.properties中添加如下配置,超过5秒没连接上报连接超时,如果超过5秒没有响应,报请求超时

#全局配置
# 请求连接的超时时间 默认的时间为 1 秒
ribbon.ConnectTimeout=5000
# 请求处理的超时时间  默认的时间为 1 秒
ribbon.ReadTimeout=5000

ln(“远程获取到积分信息”+jifen);
return new ResultVo(true,“save success”);
}




### 8.6.3:post测试





### 8.7.1:声明接口-查询积分

```java
@GetMapping(value = "/jifen/search")
public Jifen search(@RequestParam("uid") Integer uid,@RequestParam("type") String type);

8.7.2:调用接口-查询积分

@GetMapping("findByOrderNum1")
public ResultVo findByOrderNum1(String orderNum){
    //获取订单
    System.out.println("获取订单");
    //获取订单的积分
    Jifen jifen = iJifenBiz.search(123,"关注获取积分");
    System.out.println("远程获取到积分信息"+jifen);
    return new ResultVo(true,"save success");
}

8.7.3:postman测试

8.8.1:声明接口-查询积分

@PostMapping(value = "/jifen/searchByEntity")
public List<Jifen> searchByEntity(@RequestBody  Jifen jifen);

8.8.2:调用接口-查询积分

@GetMapping("findByOrderNum2")
public ResultVo findByOrderNum2(String orderNum){
    //获取订单
    System.out.println("获取订单");
    //获取订单的积分
    List<Jifen> jifens = iJifenBiz.searchByEntity(new Jifen(88, 56, "下单积分"));

    for (Jifen jifen : jifens) {
        System.out.println("远程获取到积分信息"+jifen);
    }

    return new ResultVo(true,"save success");
}

8.7.4:postman测试

8.4:OpenFeign超时控制

Feign 的[负载均衡底层用的就是 Ribbon

在application.properties中添加如下配置,超过5秒没连接上报连接超时,如果超过5秒没有响应,报请求超时

#全局配置
# 请求连接的超时时间 默认的时间为 1 秒
ribbon.ConnectTimeout=5000
# 请求处理的超时时间  默认的时间为 1 秒
ribbon.ReadTimeout=5000

总结:

  1. Nacos注册中心,解决了服务的注册与发现
  2. Ribbon客户端负载均衡器,解决了服务集群的负载均衡
  3. OpenFeign声明式的HTTPClient,解决服务远程调用的问题
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐