Nacos
一:微服务1.0:单体架构MVC架构,分层开发,所有的功能都在一个系统里面优点:1:部署简单: 由于是完整的结构体,可以直接部署在一个服务器上即可。2:技术单一: 项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发。3:用人成本低: 单个程序员可以完成业务接口到数据库的整个流程。缺点:1:系统启动慢, 一个进程包含了所有的业务逻辑,涉及到的启动模块过多,导致系统的启动、重启时间周期过长;2
一:微服务
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 Version | Spring Cloud Alibaba Version | Spring Boot Version |
---|---|---|
Hoxton.SR8 | 2.2.3.RELEASE | 2.3.2.RELEASE |
Greenwich.SR6 | 2.1.3.RELEASE | 2.1.13.RELEASE |
Hoxton.SR8 | 2.2.2.RELEASE | 2.3.2.RELEASE |
Hoxton.SR3 | 2.2.1.RELEASE | 2.2.5.RELEASE |
Hoxton.RELEASE | 2.2.0.RELEASE | 2.2.X.RELEASE |
Greenwich | 2.1.2.RELEASE | 2.1.X.RELEASE |
Finchley | 2.0.3.RELEASE | 2.0.X.RELEASE |
Edgware | 1.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(本类没有,父类有该方法)
略名 | 策略声明 | 策略描述 | 实现说明 |
---|---|---|---|
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据相应时间分配一个weight,x响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public 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实例1 | 192.168.234.131 | 8848 | |
nacos实例2 | 192.168.234.131 | 8858 | |
nacos实例3 | 192.168.234.131 | 8868 | |
nginx | 192.168.234.131 | 80 | 反向代理nacos3个实例 |
mysql | 192.168.234.131 | 3306 | 存储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
总结:
- Nacos注册中心,解决了服务的注册与发现
- Ribbon客户端负载均衡器,解决了服务集群的负载均衡
- OpenFeign声明式的HTTPClient,解决服务远程调用的问题
更多推荐
所有评论(0)