文章所有代码GtiHub:https://github.com/Tom-shushu/work-study 里面的gateway-server和server1项目

1、Docker 部署 Nacos

数据库准备

新建 "nacos_config" 数据库

在https://github.com/alibaba/nacos/blob/develop/distribution/conf/nacos-mysql.sql 获取最新的SQL脚本并执行(注意版本一定要对应),执行成功后如下图所示:

2、安装Nacos

a.下载镜像

docker pull nacos/nacos-server

b.新建 application.properties文件(注意鉴权那个一定要加-不然会出现权限绕过漏洞 CVE-2021-29441)前几天的护网行动可把人忙坏了!

### 开启鉴权
nacos.core.auth.enabled=true
### 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false
### 配置自定义身份识别的key(不可为空)和value(不可为空)
nacos.core.auth.server.identity.key=my-nacos
nacos.core.auth.server.identity.value=my-nacos server.contextPath=/nacos
server.servlet.contextPath=/nacos
server.port=8848 spring.datasource.platform=mysql
db.num=1
## 修改为自己的数据库连接和密码
db.url.0=jdbc:mysql://xxxxxxxxxxx.mysql.rds.aliyuncs.com:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=xxxxxxx
db.password=xxxxxxx nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
nacos.naming.distro.taskDispatchThreadCount=1
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true

c.直接启动

docker  run --name nacos-server -p 8848:8848 --privileged=true --restart=always -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /root/nacos/logs:/home/nacos/logs -v /root/application.properties:/home/nacos/conf/application.properties -d nacos/nacos-server

d.测试,注意打开8848安全组

浏览器输入: IP:8848/nacos 默认账号密码: nacos nacos

3、Nginx 代理 接口域名(没有域名的可以跳过)

域名有ssl证书的修改nginx.conf文件,网关我们使用8000端口,现在一次配好

# HTTPS server
server {
listen 443 ssl;
server_name api.zhouhong.icu; charset utf-8;
ssl_certificate /usr/local/nginx/ssl/8247790_api.zhouhong.icu.pem;
ssl_certificate_key /usr/local/nginx/ssl/8247790_api.zhouhong.icu.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
## Nacos
location /nacos {
proxy_pass http://127.0.0.1:8848;
}
## 网关
location / {
proxy_pass http://127.0.0.1:8000;
}
}

没有ssl安全证书的可以如下配置,网关我们使用8000端口,现在一次配好

    server {
listen 80;
server_name api.zhouhong.icu; ## Nacos
location /nacos {
proxy_pass http://127.0.0.1:8848;
}
## 网关
location / {
proxy_pass http://127.0.0.1:8000;
}
}

测试

浏览器输入: https://api.zhouhong.icu/nacos 或者 http://api.zhouhong.icu/nacos

4、网关服务搭建(代码参考:https://github.com/Tom-shushu/work-study)

1.pom文件(只展示部分,详细信息请到github看代码~)

        <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<exclusions>
<exclusion>
<artifactId>fastjson</artifactId>
<groupId>com.alibaba</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<exclusions>
<exclusion>
<artifactId>fastjson</artifactId>
<groupId>com.alibaba</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>

2.配置文件 application.yml

#请求和响应GZIP压缩支持
feign:
httpclient:
enabled: false
okhttp:
enabled: true
compression:
request:
enabled: true
mime-types: text/xml,application/xml,application/json
min-request-size: 2048
response:
enabled: true spring:
cloud:
gateway:
enabled: true
discovery:
locator:
lowerCaseServiceId: true
enabled: true
## 配置下面这个默认会匹配以服务名为前缀的路由,就不需要在nacos里面配置路由了
filters:
- name: RewritePath
args:
regexp: "'/' + serviceId + '/(?<remaining>.*)'"
replacement: "'/' + serviceId + '/${remaining}'"
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin
globalcors:
add-to-simple-url-handler-mapping: true
corsConfigurations:
'[/**]':
allowed-origins: "*"
allowed-methods: "*"
allowed-headers: "*"
allow-credentials: true
httpclient:
response-timeout: 60000
connect-timeout: 60000
loadbalancer:
ribbon:
enabled: false
application:
name: gateway
sleuth:
enabled: false
http:
legacy:
enabled: true
main:
allow-bean-definition-overriding: true
codec:
max-in-memory-size: 20MB
management:
endpoints:
web:
exposure:
include: '*'
exclude: heapdump,dump,threaddump,configprops,env
security:
enabled: false gate:
ignore:
startWith: /auth/jwt,/auth/captcha ribbon:
eureka:
enabled: true
ReadTimeout: 60000
ConnectTimeout: 60000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: false hystrix:
threadpool:
default:
coreSize: 1000 ##并发执行的最大线程数,默认10
maxQueueSize: 1000 ##BlockingQueue的最大队列数
queueSizeRejectionThreshold: 500 ##即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000
timerDelayInMilliseconds: 10000

3.bootstrap.yml 配置文件

#服务配置
server:
port: 8000
max-http-header-size: 10240 spring:
application:
name: gateway
profiles:
active: @spring.active@
servlet:
multipart:
max-request-size: 100MB
max-file-size: 100MB logging:
file:
path: logs/
---
spring:
profiles: local
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 4d7c95f1-21d5-43ad-a420-5eebb2473751
file-extension: yml
username: nacos
password: nacos
discovery:
server-addr: https://api.zhouhong.icu
namespace: 4d7c95f1-21d5-43ad-a420-5eebb2473751
username: nacos
password: nacos
---
spring:
profiles: dev
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 07610e11-85ae-49cb-aa46-b8f0802543bd
file-extension: yml
username: nacos
password: nacos
discovery:
server-addr: https://api.zhouhong.icu
namespace: 07610e11-85ae-49cb-aa46-b8f0802543bd
username: nacos
password: nacos
---
spring:
profiles: prod
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 01940467-9f25-45e3-b9b8-1ad25c937544
file-extension: yml
extension-configs:
discovery:
server-addr: https://api.zhouhong.icu
namespace: 01940467-9f25-45e3-b9b8-1ad25c937544

4.网关配置类GatewayConfig

@Configuration
public class GatewayConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
} @Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
} public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new GateWayMappingJackson2HttpMessageConverter());
return new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return httpMessageConverters;
}
};
} public class GateWayMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
GateWayMappingJackson2HttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
setSupportedMediaTypes(mediaTypes);
}
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(
clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024)).build());
}
}

5.过滤器

package com.zhouhong.gatewayserver.core.filter;
/**
* 全局请求转换
**/
@Log4j2
@Component
public class RequestGlobalFilter implements GlobalFilter, Ordered { @Resource
ServerCodecConfigurer codecConfigurer;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (Objects.equals(exchange.getRequest().getMethod(), HttpMethod.POST)) {
// 表单传输
MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)) {
return returnMono(chain, exchange);
} ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
//放开不进行安全过滤的接口
boolean checkSign = true;
for (String notAuthResource : ReleaseConstant.NONE_SECURITY_URL_PATTERNS) {
AntPathMatcher antPathMatcher = new AntPathMatcher();
if (antPathMatcher.match(notAuthResource, path)) {
checkSign = false;
}
}
ServerRequest serverRequest = ServerRequest.create(exchange, codecConfigurer.getReaders());
Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
//因为约定了终端传参的格式,所以只考虑json的情况,如果是表单传参,请自行发挥
if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
JSONObject jsonObject = JSON.parseObject(body);
String newBody = null;
try {
// 如果是1.0版本的请求(body经过base64转码),要将body解码
if (jsonObject.containsKey("sign") || jsonObject.containsKey("object")) {
newBody = verifySignature(jsonObject.getString("object"));
} else {
newBody = body;
}
} catch (Exception e) {
return Mono.error(e);
}
log.info("请求:" + path + " " + body);
return Mono.just(newBody);
}
return Mono.just(body);
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove("Content-Length");
// 请求中添加TOKEN用户信息
addTokenInfo(headers, serverRequest);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
Mono mono = bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
ServerHttpRequest decorator = this.decorate(exchange, headers, outputMessage);
return returnMono(chain, exchange.mutate().request(decorator).build());
}));
return mono;
} else {
//GET 验签
return returnMono(chain, exchange);
}
} @Override
public int getOrder() {
return 1;
} private Mono<Void> returnMono(GatewayFilterChain chain, ServerWebExchange exchange) {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
}));
} private String verifySignature(String paramStr) {
return new String(Base64Utils.decodeFromString(paramStr));
} private ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, CachedBodyOutputMessage outputMessage) {
return new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(headers);
if (contentLength > 0L) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set("Transfer-Encoding", "chunked");
}
return httpHeaders;
} @Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
} private void addTokenInfo(HttpHeaders headers, ServerRequest request) {
return;
}
}
其他代码见github源码~

4、普通业务服务(服务名称:server1)

1.bootstrap.yml 配置文件

server:
port: 8080
max-http-header-size: 10240
spring:
jackson:
time-zone: GMT+8
main:
allow-bean-definition-overriding: true
profiles:
active: @spring.active@
application:
name: server1 logging:
file:
path: ./logs/ log:
path: ./logs/ ---
spring:
profiles: local
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 4d7c95f1-21d5-43ad-a420-5eebb2473751
file-extension: yml
username: nacos
password: nacos
discovery:
server-addr: https://api.zhouhong.icu
namespace: 4d7c95f1-21d5-43ad-a420-5eebb2473751
username: nacos
password: nacos
---
spring:
profiles: dev
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 07610e11-85ae-49cb-aa46-b8f0802543bd
file-extension: yml
username: nacos
password: nacos
discovery:
server-addr: https://api.zhouhong.icu
namespace: 07610e11-85ae-49cb-aa46-b8f0802543bd
username: nacos
password: nacos
---
spring:
profiles: prod
cloud:
nacos:
config:
server-addr: https://api.zhouhong.icu
namespace: 01940467-9f25-45e3-b9b8-1ad25c937544
file-extension: yml
extension-configs:
discovery:
server-addr: https://api.zhouhong.icu
namespace: 01940467-9f25-45e3-b9b8-1ad25c937544

这里只是为了测试简单写了两个controller方法

/**
* 服务名称和接口第一段字符匹配
* @return
*/
@PostMapping("/server1/test")
public String theSameServer() {
return "你好呀( ⊙ o ⊙ )!";
} /**
* 服务名称和接口第一段字符不匹配
* @return
*/
@PostMapping("/serverNotSame/test")
public String gettoken() {
return "你好呀( ⊙ o ⊙ )!";
}

5、综合测试

A.部署说明:

1.项目中我按照正常的公司开发形式,指定了 本地(local)、测试/开发(dev)、生产(prod)环境,搭建阔以按照自己的需求进行取舍;

2.本次测试我用测试环境进行演示、大家需要在nacos上建立与环境对应的命名空间(local、dev、prod),并且需要在网关和自己业务服务里面指定对应的环境和nacos配置;

3.之前说过nacos开启了用户鉴权,所以需要在discovery 和 config 下面配置登录时的用户名以及密码

4.本项目实现的是根据服务名称自动匹配接口前缀,至于根据nacos路由列表匹配大家可以自行百度。

B.部署

1.打包:需要选择对应的环境,我这里使用测试环境(dev)如图所示:

2.需要打包网关和业务服务两个服务,最终会得到 gateway.jar 和 server1.jar两个jar包,然后上传服务器

3.部署(我这里为了方便就不需要进行docker部署了)直接使用 java -jar XXX.jar 进行简单部署了

部署成功后在nocos控制台查看服务是否注册成功

如果服务列表为这个熊样,就说明部署成功,接下来就可以测试啦

4.接口测试

使用PostMan进行接口调用
A 调用和服务名称相匹配的那个接口 https://api.zhouhong.icu/server1/test

如图所示调用成功(因为yml里面那个配置,它会自动根据服务名称 server1 进行匹配)
B 调用与服务名称不匹配的那个接口

拦截成功

Nacos + Gateway网关搭建微服务的更多相关文章

  1. 使用 Node.js 搭建微服务网关

    目录 Node.js 是什么 安装 node.js Node.js 入门 Node.js 应用场景 npm 镜像 使用 Node.js 搭建微服务网关 什么是微服务架构 使用 Node.js 实现反向 ...

  2. spring cloud+dotnet core搭建微服务架构:Api网关(三)

    前言 国庆假期,一直没有时间更新. 根据群里面的同学的提问,强烈推荐大家先熟悉下spring cloud.文章下面有纯洁大神的spring cloud系列. 上一章最后说了,因为服务是不对外暴露的,所 ...

  3. spring cloud+.net core搭建微服务架构:Api网关(三)

    前言 国庆假期,一直没有时间更新. 根据群里面的同学的提问,强烈推荐大家先熟悉下spring cloud.文章下面有纯洁大神的spring cloud系列. 上一章最后说了,因为服务是不对外暴露的,所 ...

  4. Spring Cloud Alibaba+Nacos搭建微服务架构

    1. Spring Cloud Alibaba 简介    Spring Cloud Alibaba是阿里巴巴为分布式应用提供的一站式解决方案,能够更方便快捷地搭建分布式平台,nacos拥有着替换eu ...

  5. 【译文】用Spring Cloud和Docker搭建微服务平台

    by Kenny Bastani Sunday, July 12, 2015 转自:http://www.kennybastani.com/2015/07/spring-cloud-docker-mi ...

  6. Spring Cloud和Docker搭建微服务平台

    用Spring Cloud和Docker搭建微服务平台 This blog series will introduce you to some of the foundational concepts ...

  7. 一个C#开发者学习SpringCloud搭建微服务的心路历程

    前言 Spring Cloud很火,很多文章都有介绍如何使用,但对于我这种初学者,我需要从创建项目开始学起,所以这些文章对于我的启蒙,帮助不大,所以只好自己写一篇文章,用于备忘. SpringClou ...

  8. 手把手教你使用spring cloud+dotnet core搭建微服务架构:服务治理(-)

    背景 公司去年开始使用dotnet core开发项目.公司的总体架构采用的是微服务,那时候由于对微服务的理解并不是太深,加上各种组件的不成熟,只是把项目的各个功能通过业务层面拆分,然后通过nginx代 ...

  9. spring cloud+dotnet core搭建微服务架构:服务发现(二)

    前言 上篇文章实际上只讲了服务治理中的服务注册,服务与服务之间如何调用呢?传统的方式,服务A调用服务B,那么服务A访问的是服务B的负载均衡地址,通过负载均衡来指向到服务B的真实地址,上篇文章已经说了这 ...

  10. spring cloud+dotnet core搭建微服务架构:配置中心(四)

    前言 我们项目中有很多需要配置的地方,最常见的就是各种服务URL地址,这些地址针对不同的运行环境还不一样,不管和打包还是部署都麻烦,需要非常的小心.一般配置都是存储到配置文件里面,不管多小的配置变动, ...

随机推荐

  1. SQL server 树形递归查询

    1,原始查询 原始表格查询: select * from dbo.T_DeptInfo; 原始表格查询结果: 2,递归查询 -- with 一个临时表(括号里包括的是你要查询的列名) with tem ...

  2. kubeadm搭建单master多node节点的k8s集群(3)

    一.实验环境准备 K8s集群角色 IP 主机名 安装的组件 配置 控制节点 192.168.1.10 master apiserver.controller-manager.scheduler.etc ...

  3. DNS(4) -- dns功能实现-配置正向解析和反向解析以及DNS递归查询示例

    目录 1 DNS配置示例 1.1 DNS解析类型 1.2 配置正向解析 1.3 配置反向解析 1.4 DNS递归查询 1.4.1 开启递归查询 1.4.2 关闭递归查询 1 DNS配置示例 1.1 D ...

  4. three.js教程4-Group层级模型

    1.组对象Group.层级模型-形成树状结构 //创建两个网格模型mesh1.mesh2 const geometry = new THREE.BoxGeometry(20, 20, 20); con ...

  5. C语言:对fgets进行封装

    因为fgets在赋值完字符后,在最后会加一个\n换行符,所以为了能够把数组当成字符串,就必须把\n改成\0 代码: #include<stdio.h> #include<stdlib ...

  6. k8s快捷命令

    查看node使用率: for i in `kubectl get nodes|awk '{print $1}'|sed '1d'`;do  echo "=========>" ...

  7. mongodb的replication与shard分片结合使用详解

    部署脚本 #!/bin/bash #复制集配置 IP='10.0.0.12' #主机ip NA='rs3' #复制集名称 if [ "$1" = "reset" ...

  8. YiShaAdmin:一款基于.NET Core Web + Bootstrap的企业级快速开发框架

    前言 今天大姚给大家分享一款基于.NET Core Web + Bootstrap的企业级快速后台开发框架.权限管理系统,代码简单易懂.界面简洁美观(基于MIT License开源,免费可商用):Yi ...

  9. 我对IdentityServer4的初步了解

    官网:https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html 官网例子:h ...

  10. vue-element-admin 运行踩坑笔记

      npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm E ...