赞
踩
linux:https://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.tar.gz
- 执行下载命令
- wget https://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.tar.gz
- 解压安装包
- tar -zxxvf nacos-server-2.0.4.tar.gz nacos/
(1)创建数据库nacos,执行conf目录下的nacos-mysql.sql脚本,初始化数据库
(2)进入conf目录编辑application.properties
(4)在bin目录下启动
./startup.sh -m standalone //standalone代表着单机模式运行,非集群模式
看到最后一行的successfully启动成功
(5)将nacos配置为系统服务
①添加文件nacos.service vim /lib/systemd/system/nacos.service 并且增加如下信息 (nacos路径替换成自己的路径即可)
- [Unit]
- Description=nacos
- After=network.target
-
- [Service]
- Type=forking
- ExecStart=/usr/nacos-server-1.1.3/nacos/bin/startup.sh -m standalone
- ExecReload=/usr/nacos-server-1.1.3/nacos/bin/shutdown.sh
- ExecStop=/usr/nacos-server-1.1.3/nacos/bin/shutdown.sh
- PrivateTmp=true
-
- [Install]
- WantedBy=multi-user.target
②编辑nacos/bin目录下的startup.sh, 修改JAVA_HOME的路径,注释其他三项
③执行以下命令
- 1. 重新加载所有service服务
- systemctl daemon-reload
- 2. 开机启动nacos.service
- systemctl enable nacos.service
- 3. 查看该service是否开机启用
- systemctl is-enabled nacos.service
- 4. 启动该服务
- systemctl start nacos.service
- 可能报错: Job for nacos.service failed because the control process exited with error code. See "systemctl status nacos.service" and "journalctl -xe" for details.
- 5. 查看该服务状态
- systemctl status nacos.service
初始账号密码:nacos/nacos.
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
- spring:
- application:
- name: sca-provider #服务注册的服务名 ,注意服务名的横线
- cloud:
- nacos:
- discovery:
- server-addr: localhost:8848 #向nacos控制台注册
客户端定时(5秒)向nacos发送请求(心跳包),中断15秒,nacos客户端显示不健康,30秒认为中断死亡
1、restTemplate远端调用
什么是restTemplate:传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。
在SpringCloud的项目中,我们使用了自动配置的OAuth2RestTemplate,RestTemplate,但是在使用这些restTemplate的时候,url必须是服务的名称,如果要调用真实的域名或者ip的url,会有错误
- @Bean
- public RestTemplate restTemplate(){ //基于此对象实现远端服务调用
- return new RestTemplate();
- }
- restTemplate实现远端调用,此方法是将该类交给spring管理
- @Autowired
- private RestTemplate restTemplate; // 实现远端调用服务
-
- restTemplate.getForObject(url, String.class);//参数一调用远端的url,参数二为该方法返回值类型的class对象
LoadBalancerClient: 是 SpringCloud 提供的一种负载均衡客户端,Ribbon 负载均衡组件内部也是集成了 LoadBalancerClient 来实现负载均衡。
- @Autowired
- private LoadBalancerClient loadBalancerClient; //此对象负责从nacos服务中发现和获取服务实例
-
- // /ˈbælənsə(r)/ /ˈklaɪənt/
- @GetMapping("/controller/doRestEcho02")
- public String doRestEcho02() {
- ServiceInstance serviceInstance = loadBalancerClient.choose("sca-provider");
- String url = String.format("http://%s:%s/provider/echo/%s",
- serviceInstance.getHost(),
- serviceInstance.getPort(), appName);
- //从nacos获取provider服务注册信息
-
- System.out.println("url :" + url);
- return restTemplate.getForObject(url, String.class);
- }
在restTemplate交给spring管理的方法上加上@loadBalancer,在该步骤请求发送时,底层对该请求拦截,然后底层执行choose等一系列方法,获取host和port进行请求拼接
- @Autowired
- private RestTemplate loadBalancedRestTemplate;
-
- @GetMapping("/controller/doRestEcho03")
- public String oRestEcho03() {
- String serviceId = "sca-provider";
- String url = String.format("http://%s/provider/echo/%s", serviceId, appName);
- return loadBalancedRestTemplate.getForObject(url, String.class);//在该步骤请求发送时,底层对该请求拦截,
- // 然后执行方法二的choose等一系列方法,获取host和port进行请求拼接
-
- }
什么是OpenFeign
OpenFeign是一种声明式、模板化的HTTP客户端(仅在Application Client中使用)(称OpenFeign作用:声明式服务调用)。声明式调用是指,就像调用本地方法一样调用远程方法,无需感知操作远程http请求。学习完OpenFeign后可以不使用RestTemplate进行调用。
(1)添加依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
(2)在启动类上添加@EnableFeignClients,作用类似于@MapperScan
(3)service层创建接口
- @Autowired
- private RemoteProviderService remoteProviderService;
-
- @GetMapping("/controller/doFeignEcho/{msg}")
- public String doFeignEcho(@PathVariable String msg) {
- return remoteProviderService.echoMassage(msg);
- }
Nacos中的负载均衡底层是通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务实例中获取一个实例为消费方法提供服务。
随机策略 轮询策略 重试策略 最低并发策略 可用过滤策略 响应时间加权重策略 区域权重策略
配置中心的作用:动态管理发布配置,无需重启服务配置经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则等。
(1)添加服务配置依赖
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
- </dependency>
(2)将项目中application.yml的名字修改为bootstrap.yml(启动优先级最高),并添加配置中心配置
- cloud:
- nacos:
- discovery: #配置服务注册中心地址
- server-addr: 127.0.0.1:8848
- config: #配置服务配置中心地址
- server-addr: 127.0.0.1:8848
- file-extension: yml
Nacos中的命名空间一般用于配置隔离,这种命名空间的定义一般会按照环 境(开发,生 产等环境)进行设计和实现.我们默认创建的配置都存储到了 public命名空间
更换命名空间:
在xml文件config下新增namespace: (命名空间的id)
当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于 服务做分组配置, 例如,一个服务在不同时间节点(节假日,活动等)切换 不同的配置
更换分组:
在xml文件config下新增group: 分组名称
在xml文件config下新增
- shared-configs[0]: #该命名空间下共享配置的引用,共享配置不止一个,使用下标依次引用。
-
- data-id: app-public.yml #该命名空间下共享配置的 Data id的值
-
- refresh: true #支持配置中心共享配置改变,动态刷新该共享配置。 默认fales
-
- #group: DEFAULT_GROUP #该命名空间下分组名称。#DEFAULT_GROUP,作为共享配置,创建时默认分组
- 名。
写一个Controller试试看,这里代码中需要加上 @RefreshScope 注解,注解作用就是当nacos中的配置文件更新的时候,同步更新到代码中!
- @RestController
- @RequestMapping("/TestController")
- @RefreshScope
- public class TestController {
-
- @Value("${pattern.envSharedValue}")
- private String myName;
-
- @GetMapping("/test1")
- public String test1() {
- return myName;
- }
- }
作用:分布式系统的流量防卫兵
下载网址:https://github.com/alibaba/Sentinel/releases
知识补充:限流算法
计数器、令牌桶、漏斗算法,滑动窗口算法
Sentinel 默认的限流算法是滑动窗口算法
(1)添加依赖
- <dependency>
-
- <groupId>com.alibaba.cloud</groupId>
-
- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
-
- </dependency>
(2)配置bootstrap.yml
- spring:
- cloud:
- sentinel:
- transport:
- dashboard: localhost:8180 # 指定sentinel控制台地址。
(3)找到目录执行运行命令
java-Dserver.port=8180-Dcsp.sentinel.dashboard.server=localhost:8180-Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
- -Dserver.port=8180
-
- -Dcsp.sentinel.dashboard.server=localhost:8180
-
- -Dproject.name=sentinel-dashboard
-
- -jar
-
- D:\javaXM\sentinel-1.8.1\sentinel-dashboard-1.8.1.jar
QPS(代表每秒请求次数)单机阈值(设置请求次数)为1,代表每秒请求不超过1次,超过做限流处理,处理方式直接调用失败。
直接,关联和链路
Sentinel的限流效果:快速失败,预热,排队等待
- /**
- @SentinelResource使用此注解描述的方法,在此方法被访问时,会sentinel的簇点链路中显示,此注解中指定的
- 名字就是资源名。此注解中的blockHandlerClass用于指定,出现限流异常时的异常处理类,blockHandler属性
- 用于指定异常处理类中的方法(此方法的返回类型,参数要与 @SentinelResource注解描述的方法参数一致,可
- 以BlockException异常类型参数,而且方法必须是静态.)fallbackClass 用于指定业务异常处理类,fallback
- 用于指向业务处理类中的异常处理方法(此方法的返回类型,参数要与@SentinelResource注解描述的方法参
- 数一致,可以加Throwable异常类型参数)
- */
-
- @SentinelResource(value="doGetResource",
- blockHandlerClass = ResourceBlockHandler.class,
- blockHandler = "call",
- fallback = "call",
- fallbackClass = ResourceFallbackHandler.class)
-
- public String doGetResource(){
-
- return "do get resource";
-
- }
说明:流控模式为链路模式时,Sentinel Web过滤器默认聚合所有URL的入口为sentinel_spring_web_context,在application.yml添加如下语句来关闭URL PATH聚合,入口名就不为默认
- sentinel:
-
- web-context-unify: false
作用:对调用链路中不稳定的资源进行熔断降级
①慢调用比例:请求数超过3时,平均响应时间超过200毫秒的有30%,则对请求进行熔断,熔断时长为10秒钟,10秒以后恢复正常。
②异常比例
③异常数
系统提供了默认的异常处理机制,如果默认处理机制不满足我们需求,我们可以自己进行定义
实现方式:定义方式上可以直接或间接实现BlockExceptionHandler接口,并将对象交给spring管理。
- @Slf4j
-
- @Component
-
- public class ServiceBlockExceptionHandler implements BlockExceptionHandler {
-
- @Override
-
- public void handle(HttpServletRequest request,
- HttpServletResponse response,
- BlockException e) throws Exception {
-
- //设置响应数据编码
-
- response.setCharacterEncoding("utf-8");
-
- //告诉客户端响应数据的类型,以及客户端显示内容的编码
-
- response.setContentType("text/html;charset=utf-8");
-
- //向客户端响应一个json格式的字符串
-
- //String str="{\"status\":429,\"message\":\"访问太频繁了\"}";
-
- Map<String,Object> map=new HashMap<>();
-
- map.put("status", 429);
-
- map.put("message","访问太频繁了");
-
- //将map集合变为json格式的字符串
-
- String jsonStr=new ObjectMapper().writeValueAsString(map);
-
- PrintWriter out = response.getWriter();
-
- out.print(jsonStr);
-
- out.flush();
-
- out.close();
-
- }
-
- }
作用:对经常使用的数据做配置
- @GetMapping("/sentinel/findById")
-
- @SentinelResource("resource")
-
- public String doFindById(@RequestParam("id") Integer id){
-
- return "resource id is "+id;
-
- }
资源名:@SentinelResource注解的值
参数索引:@SentinelResource注解的方法参数下标,0代表第一个参数,1代表第二个参数。
单机阈值以及统计窗口时长表示在此窗口时间超过阈值就限流。
参数例外项:表示参数为5时阈值为100,其它参数值阈值为1.
作用:监控服务器的状态,保证服务器正常的运行
Sentinel的常用系统规则:
RT,QPS,CPU,线程,Load-linux,unix
作用:根据黑白名单规则,限制请求是否通过,只有请求来源位于不在黑名单或则在白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过。
①定义请求解析器:
用于对请求进行解析(RequestOriginParser接口的实现类),并返回解析结果,sentinel底层在
拦截到用户请求以后,会对请求数据基于此对象进行解析,判定是否符合黑白名单规则
- @Component
-
- public class DefaultRequestOriginParser implements RequestOriginParser {
-
- @Override
-
- public String parseOrigin(HttpServletRequest request) {
-
- String origin = request.getParameter("origin");//这里的参数名会与请求中的参数名一致
-
- return origin;
-
- }
-
- }
②定义流控规则
资源名:即限流规则的作用对象
流控应用:对应的黑名单/白名单中设置的规则值,多个值用逗号隔开.
③执行资源访问
①定义请求解析器:
- @Component
-
- public class DefaultRequestOriginParser implements RequestOriginParser {
-
- //解析请求源数据
-
- @Override
-
- public String parseOrigin(HttpServletRequest request) {
-
- //获取访问请求中的ip地址,基于ip地址进行黑白名单设计(例如在流控应用栏写ip地址)
-
- String ip= request.getRemoteAddr();
-
- System.out.println("ip="+ip);
-
- return ip;
-
- }//授权规则中的黑白名单的值,来自此方法的返回值
-
- }
②定义流控规则
作用:一个各种服务访问的入口,在项目中简化前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度
特点:
(1)性能强劲:是第一代网关Zuul的1.6倍。
(2)依赖Netty与WebFlux(Spring5.0),不是传统的Servlet编程模型 (Spring MVC就是基于此模型实现),学习成本高。
(3)需要Spring Boot 2.0及以上的版本,才支持
(1)导入依赖:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
-
- <artifactId>spring-cloud-starter-gateway</artifactI
- </dependency>
(2)application.yml(假如已有则无须创建)中添加相关配置,设定uri实现负载均衡
- gateway: #和nacos同一级
-
- routes: #配置网关路由规则
-
- - id: route01 #路由id,自己指定一个唯一值即可
-
- uri: lb://sca-provider
-
- #uri: http://localhost:8082/ #网关帮我们转发的url(url是uri 的子集,uri是统一资源标
- 识符)
-
- predicates: #断言(谓此):匹配请求规则
-
- - Path=/nacos/provider/echo/**
- - Before=2021-01-30T00:00:00.000+08:00
- - Method=GET
- #请求路径定义,此路径对应uri中的资源,**代表传入的参数
- filters: #网关过滤器,用于对谓词中的内容进行判断分析以及处理
- - StripPrefix=1 #转发之前去掉path中第一层路径
Predicate(断言)又称谓词,用于条件判断,只有断言结果都为真,才会真正的执行路由
(1)基于Datetime类型的断言工厂,此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory:判断请求日期是否晚于指定日 期
BeforeRoutePredicateFactory:判断请求日期是否早于指定 日期
BetweenRoutePredicateFactory:判断请求日期是否在指定 时间段内
例:-After=2020-12-31T23:59:59.789+08:00[Asia/Shanghai]:判断请求日期是否晚于指定日期
(2)基于header的断言工厂HeaderRoutePredicateFactory,判断请求Header是否具有给定名称且值与正则表达式匹配
例:-Header=X-Request-Id, \d+
(3)基于Method请求方法的断言工厂,MethodRoutePredicateFactory
接收一个参数,判断请求类型是否跟指定的类型匹配
例:-Method=GET
(4)基于Query请求参数的断言工厂,QueryRoutePredicateFactory
接收两个参数,请求param和正则表达式, 判断请求参数是否具 有给定名称且值与正则表达式匹配.
例:-Query=pageSize,\d+
(1)添加依赖
- <dependency>
-
- <groupId>com.alibaba.cloud</groupId>
-
- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
-
- </dependency>
-
-
-
- <dependency>
-
- <groupId>com.alibaba.cloud</groupId>
-
- <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
-
- </dependency>
(2)添加Sentinel 控制台地址
- sentinel:
-
- transport:
-
- dashboard: localhost:8180 #Sentinel 控制台地址
-
- eager: true #取消Sentinel控制台懒加载,即项目启动即连接
(3)添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下:-Dcsp.sentinel.app.type=1
作用:自定义API分组,是一种更细粒度的限流规则定义,它允许我们利用sentinel提供的API,将请求路径进行分组,然后在组上设置限流规则
第一步:新建API分组
第二步:新建分组流控规则
第三步:定制流控网关返回值
- @Configuration
-
- public class GatewayConfig {
-
- public GatewayConfig(){
-
- GatewayCallbackManager.setBlockHandler( new BlockRequestHandler() {
-
- @Override
-
- public Mono<ServerResponse> handleRequest(
- ServerWebExchangeserverWebExchange,
- Throwable throwable) {
-
- Map<String,Object> map=new HashMap<>();
-
- map.put("state",429);
-
- map.put("message","two many request");
-
- String jsonStr=JSON.toJSONString(map);
-
- return ServerResponse.ok().body(Mono.just(jsonStr),String.class);
-
- }
-
- });
-
- }
-
- }
- 1、设置拦截条件,返回true放行,返回false表示拦截
- /*MVC中的拦截器对象*/
- @Slf4j
- public class TimeAccessInterceptor implements HandlerInterceptor {
-
- /*此方法在执行目标controller方法之前执行,返回值为true表示放行该请求*/
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-
- LocalTime now= LocalTime.now();//JDK8中的时间对象(推荐使用)
- int hour=now.getHour();//获取当前时间对应小时
- //System.out.println("hour="+hour);
- log.info("hour {}",hour);
- /*在规定时间范围内(6点到22点)允许访问,将请求放行*/
- if(hour<=6||hour>=22)
- throw new RuntimeException("请在6~10点进行访问");
- return true;
- }
- }
- 被限流时定制返回错误信息
-
- @Configuration
-
- public class GatewayConfig {
-
- public GatewayConfig(){
-
- GatewayCallbackManager.setBlockHandler( new BlockRequestHandler(){
-
- @Override
-
- public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
-
- Map<String,Object> map=new HashMap<>();
-
- map.put("state",429);
-
- map.put("message","two many request");
-
- String jsonStr=JSON.toJSONString(map);
-
- return ServerResponse.ok().body(Mono.just(jsonStr),String.class);
-
- }
-
- });
-
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。