博客
关于我
SpringCloud Gateway系列--https
阅读量:516 次
发布时间:2019-03-07

本文共 9181 字,大约阅读时间需要 30 分钟。

Spring Boot 微服务架构配置与优化

一、注册中心配置示例

1.1 Eureka Server

server:
port: 7001
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
serviceUrl:
defaultZone: http://localhost:7001/eureka/

1.2 高可用配置

server:
port: 7001
# 高可用配置
groups:
- name: server
port: 7001
- name: server2
port: 7002
spring:
application:
name: server
eureka:
instance:
hostname: localhost
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/

二、项目依赖管理

2.1 pom.xml 核心配置

4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.12.RELEASE
./
com.example
eureka-server
0.0.1-SNAPSHOT
Demo project for Spring Boot
1.8
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.cloud
spring-cloud-dependencies
Greenwich.SR6
pom
import

三、产品服务配置

3.1 application.yml

server:
port: 9002
ssl:
enabled: true
key-alias: tomcat
key-store: classpath:keystore.p12
key-store-password: 222333
keyStoreType: PKCS12
spring:
application:
name: product
feign:
hystrix:
enabled: true

四、Gateway 配置

4.1 HTTPS 配置

server:
port: 6443
ssl:
enabled: true
key-alias: tomcat
key-store: classpath:keystore.p12
key-store-password: 222333
keyStoreType: PKCS12

4.2 HTTP 转 HTTPS 配置

server:
port: 6001
ssl:
enabled: true
key-alias: tomcat
key-store: classpath:keystore.p12
key-store-password: 222333
keyStoreType: PKCS12

4.3 高级配置

spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
httpclient:
ssl:
use-insecure-trust-manager: true

五、配置类实现

5.1 简洁方式

package com.example.demo.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.HttpHandler;
@Configuration
@ConditionalOnProperty(name = "https.server.ssl.enabled", havingValue = "true")
public class HttpsConfig {
@Bean
@ConfigurationProperties(prefix = "https.server")
public HttpsProperties httpsProperties() {
return new HttpsProperties();
}
@Bean(initMethod = "start", destroyMethod = "stop")
public WebServer httpWebServer(HttpHandler handler, HttpsProperties properties) {
NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory(properties.getPort());
factory.setSsl(properties.getSsl());
return factory.getWebServer(handler);
}
}

5.2 复杂配置

package com.example.demo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.server.reactive.HttpHandler;
import java.io.File;
import java.io.IOException;
@Configuration
@ConditionalOnProperty(name = "https.server.ssl.enabled", havingValue = "true")
public class HttpsConfig {
@Value("${https.server.port:6443}")
private int httpsPort;
@Value("${https.server.ssl.key-alias:'tomcat'}")
private String keyAlias;
@Value("${https.server.ssl.key-store:'classpath:keystore.p12'}")
private String keyStore;
@Value("${https.server.ssl.key-store-password:'222333'}")
private String keyStorePassword;
@Value("${https.server.ssl.keyStoreType:'PKCS12'}")
private String keyStoreType;
@Bean(initMethod = "start", destroyMethod = "stop")
public WebServer httpWebServer(HttpHandler handler) {
NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory(httpsPort);
File keyStoreFile;
try {
keyStoreFile = new ClassPathResource(keyStore).getFile();
} catch (IOException ex) {
throw new IllegalStateException("Can't access keystore: [" + keyStore + "] or truststore: [" + keyStore + "]", ex);
}
Ssl ssl = new Ssl();
ssl.setEnabled(true);
ssl.setKeyAlias(keyAlias);
ssl.setKeyStore(keyStoreFile.getAbsolutePath());
ssl.setKeyStorePassword(keyStorePassword);
ssl.setKeyStoreType(keyStoreType);
factory.setSsl(ssl);
return factory.getWebServer(handler);
}
}

六、 WebSocket 配置

6.1 WebSocket 服务器

package com.example.product.util;
import lombok.extern.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
@ServerEndpoint(value = "/ws/{token}")
public class WebSocketServer {
private static Map
clientMap = new ConcurrentHashMap<>();
private String token;
private Session session;
@OnOpen
public void onOpen(@PathParam("token") String token, Session session) {
this.token = token;
this.session = session;
addOnlineCount();
clientMap.put(token, this);
log.info("New connection joined! Token: {}, Session ID: {}, Current connections: {}", token, session.getId(), onlineCount);
}
@OnClose
public void onClose() {
subOnlineCount();
clientMap.remove(token);
log.info("One connection closed. Current connections: {}", onlineCount);
}
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("Received message from client: {}", message);
sendMsgToAll(message);
}
@OnError
public void onError(Session session, Throwable error) {
log.info("Error occurred!");
error.printStackTrace();
}
public void sendMessage(String token, String message) throws IOException {
if (!StringUtils.isEmpty(token) && clientMap.containsKey(token)) {
clientMap.get(token).send(message);
log.info("Successfully sent a message: {}", message);
} else {
log.error("User '{}' is not online!", token);
}
}
public void send(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void sendMsgToAll(String message) throws IOException {
for (WebSocketServer item : clientMap.values()) {
item.session.getBasicRemote().sendText(message);
}
log.info("Successfully sent message to all: {}", onlineCount);
}
public static synchronized int getOnlineCount() {
return WebSocketServer.onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}

6.2 WebSocket 配置类

package com.example.product.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

七、常见问题与解决方案

7.1 SSL 证书读取错误

错误日志示例:

Caused by: java.io.FileNotFoundException: class path resource [keystore.p12] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/gateway-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/keystore.p12ClassPathResource

解决方法:

  • 打包时将 keystore.p12 放在 resources 目录下。
  • 使用 Maven 资源过滤器配置,确保 keystore.p12 被正确读取。

7.2 HTTPS 配置失败

错误信息示例:

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown

解决方法:

  • 确保 keystore.p12 的证书和私钥正确。
  • 重新启动服务,刷新 SSL 上下文。
  • 检查域名和端口配置是否正确。
  • 八、技术总结

  • HTTPS 配置:确保 keystore 文件路径正确,证书和私钥配置无误。
  • HTTP 转 HTTPS:通过代码实现 URL 重定向,可使用 Netty 进行转发。
  • WebSocket 配置:支持 WebSocket 和 WSS 连接,需配置 SSL 以支持安全通信。
  • 通过以上配置和优化,可以有效提升微服务架构的安全性和性能,同时确保各服务之间的通信顺畅。

    转载地址:http://wntjz.baihongyu.com/

    你可能感兴趣的文章
    Netty常见组件二
    查看>>
    netty底层源码探究:启动流程;EventLoop中的selector、线程、任务队列;监听处理accept、read事件流程;
    查看>>
    Netty心跳检测机制
    查看>>
    Netty核心模块组件
    查看>>
    Netty框架内的宝藏:ByteBuf
    查看>>
    Netty框架的服务端开发中创建EventLoopGroup对象时线程数量源码解析
    查看>>
    Netty源码—2.Reactor线程模型一
    查看>>
    Netty源码—3.Reactor线程模型三
    查看>>
    Netty源码—4.客户端接入流程一
    查看>>
    Netty源码—4.客户端接入流程二
    查看>>
    Netty源码—5.Pipeline和Handler一
    查看>>
    Netty源码—5.Pipeline和Handler二
    查看>>
    Netty源码—6.ByteBuf原理一
    查看>>
    Netty源码—6.ByteBuf原理二
    查看>>
    Netty源码—7.ByteBuf原理三
    查看>>
    Netty源码—7.ByteBuf原理四
    查看>>
    Netty源码—8.编解码原理一
    查看>>
    Netty源码—8.编解码原理二
    查看>>
    Netty源码解读
    查看>>
    Netty的Socket编程详解-搭建服务端与客户端并进行数据传输
    查看>>