- 项目路径
- 必要环境
- 软件&版本&插件
- 项目结构
- 模块说明
- 服务启动顺序
- 具体实现
- 关键服务pom
- 父pom
- common pom
- gateway pom
- config pom
- eureka pom
- 实现EUREKA注册中心
- 启动类
- 配置文件(eureka服务不使用配置中心服务)
- 启动EUREKA服务
- 实现CONFIG配置中心
- 启动类
- 配置文件
- 启动CONFIG服务
- 实现GATEWAY网关服务
- 启动类
- GATEWAY配置类
- GATEWAY配置文件
- 启动GATEWAY服务
- 分别启动FALLBACK、MAINTAIN、WEBSOCKET服务
- 这三个服务没啥特别,配置文件和GATEWAY一样,读取对应的配置文件就好
- 调用GATEWAY对应路由规则的MAINTAIN服务提供的接口测试
- 最后启动ADMIN服务
- 启动类
- 访问 127.0.0.1:8887 测试
- OpenFeign示例
- WEBSOCKET服务接口
- MAINTAIN调用WEBSOCKET接口
- 总结
项目路径
GitHub路径:https://github.com/wuyue930912/cloud-pet-hub.git
Coding路径:https://e.coding.net/pethub/hub/pet-hub.git
必要环境
软件&版本&插件
项目结构
模块说明
服务启动顺序
具体实现
关键服务pom
父pom
4.0.0 com.pet PETHUB1.0-SNAPSHOT pom pethub-hub-master master https://pethub-maven.pkg.coding.net/repository/hub/master/ cloud-fallback cloud-gateway cloud-maintain cloud-eureka cloud-websocket cloud-admin cloud-config common 8 org.springframework.boot spring-boot-starter-parent2.2.1.RELEASE org.springframework.cloud spring-cloud-dependenciesHoxton.SR1 pom import org.springframework.boot spring-boot-starter-actuatororg.projectlombok lombok1.18.20 org.springframework.boot spring-boot-starter-testtest org.jsoup jsoup1.14.3 commons-lang commons-lang2.6 org.slf4j slf4j-log4j121.7.32 org.jboss.logging jboss-logging3.3.0.Final com.fasterxml classmate1.3.3 org.mapstruct mapstruct1.4.2.Final org.mapstruct mapstruct-processor1.4.2.Final cn.hutool hutool-crypto5.7.15 cn.hutool hutool-core5.7.15 org.apache.shiro shiro-spring1.7.1 com.alibaba fastjson1.2.78 io.springfox springfox-boot-starter3.0.0 com.google.guava guava15.0 org.springframework.boot spring-boot-starter-validationdev true dev release release
common pom
PETHUB com.pet 1.0-SNAPSHOT 4.0.0 common8 8 org.springframework.boot spring-boot-starter-weborg.hibernate hibernate-validator5.4.1.Final javax.validation validation-api1.1.0.Final org.mariadb.jdbc mariadb-java-client2.7.3 com.alibaba druid1.2.8 org.springframework.boot spring-boot-starter-data-jdbcorg.springframework.boot spring-boot-starter-data-jpaorg.springframework.cloud spring-cloud-starter-netflix-eureka-clientcom.sun.jersey jersey-clientcom.sun.jersey jersey-corecom.sun.jersey.contribs jersey-apache-client4org.springframework.cloud spring-cloud-starter-openfeign
gateway pom
PETHUB com.pet 1.0-SNAPSHOT 4.0.0 cloud-gateway8 8 org.springframework.cloud spring-cloud-starter-openfeignorg.springframework.cloud spring-cloud-starter-gatewayorg.springframework.cloud spring-cloud-starter-netflix-ribbonorg.springframework.cloud spring-cloud-starter-netflix-hystrixorg.springframework.cloud spring-cloud-config-clientorg.springframework.cloud spring-cloud-starter-netflix-eureka-clientcom.sun.jersey jersey-clientcom.sun.jersey jersey-corecom.sun.jersey.contribs jersey-apache-client4de.codecentric spring-boot-admin-starter-client2.2.4 src/main/resources true application.yml application-dev.yml application-prod.yml src/main/resources true application.yml application-${profileActive}.yml org.springframework.boot spring-boot-maven-plugin
config pom
PETHUB com.pet 1.0-SNAPSHOT 4.0.0 cloud-config8 8 com.pet common1.0-SNAPSHOT org.springframework.cloud spring-cloud-config-serverde.codecentric spring-boot-admin-starter-client2.2.4 src/main/resources true application.yml application-dev.yml application-prod.yml src/main/resources true application.yml application-${profileActive}.yml org.springframework.boot spring-boot-maven-plugin
eureka pom
PETHUB com.pet 1.0-SNAPSHOT 4.0.0 cloud-eureka8 8 org.springframework.cloud spring-cloud-starter-netflix-eureka-serverde.codecentric spring-boot-admin-starter-client2.2.4 org.springframework.boot spring-boot-starter-securitysrc/main/resources true application.yml application-dev.yml application-prod.yml src/main/resources true application.yml application-${profileActive}.yml org.springframework.boot spring-boot-maven-plugin
实现EUREKA注册中心
启动类
package com.pet; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @SpringBootApplication @EnableEurekaServer @Slf4j public class EurekaStarter { public static void main(String[] args) { SpringApplication.run(EurekaStarter.class, args); log.info("start running eureka server : 【{}】", "http://127.0.0.1:8888"); } @EnableWebSecurity static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().ignoringAntMatchers("/eureka/**"); super.configure(http); } } }
配置文件(eureka服务不使用配置中心服务)
server: port: 8888 logging: file: path: D:\LOG eureka: instance: hostname: 127.0.0.1 client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka server: eviction-interval-timer-in-ms: 6000 wait-time-in-ms-when-sync-empty: 6000 enable-self-preservation: true management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS spring: application: name: eureka security: user: name: eureka password: 设置EUREKA登录密码 roles: SUPERUSER jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
启动EUREKA服务
启动成功访问 ip:8888端口出现下面页面说明配置成功。
启动类
package com.pet; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient @EnableConfigServer @Slf4j public class ConfigStarter { public static void main(String[] args) { SpringApplication.run(ConfigStarter.class, args); log.info("start running config server"); } }
配置文件
server: port: 8887 max-http-header-size: 20480 servlet: session: timeout: PT30M logging: file: path: D:\LOG management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://EUREKA账号:EUREKA密码@127.0.0.1:8888/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1 instance-id: 127.0.0.1:${spring.application.name}:${server.port} feign: hystrix: enabled: true spring: cloud: config: server: git: uri: https://e.coding.net/pethub/hub/pet-hub.git ## git路径 username: git用户名 password: git密码 search-paths: base/script/config/application-* ## 配置文件存放具体路径 default-label: master ## 指定分支 application: name: config jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 datasource: url: jdbc:mariadb://127.0.0.1:3306/pet_hub?characterEncoding=utf-8&useSSL=false&useTimezone=true&serverTimezone=GMT%2B8 driver-class-name: org.mariadb.jdbc.Driver username: root password: 数据库密码 type: com.alibaba.druid.pool.DruidDataSource initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECt 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true jpa: database-platform: org.hibernate.dialect.MySQL5InnoDBDialect database: MYSQL show-sql: true open-in-view: false servlet: multipart: enabled: true max-file-size: 10MB max-request-size: 10MB # REDIS 配置 redis: database: 0 host: 127.0.0.1 port: 6379 password: timeout: 6000 jedis: pool: max-active: 8 max-wait: -1 max-idle: 10 min-idle: 2
启动CONFIG服务
启动成功后,通过postman调用 127.0.0.1:8887/{服务名}/{版本号}接口,查看是否成功(第一次调用可能会比较慢,泡壶茶水儿,等一会儿~ )。
出现下面响应,说明配置成功。
启动类
package com.pet; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication @Slf4j public class GatewayStarter { public static void main(String[] args) { SpringApplication.run(GatewayStarter.class, args); log.info("start running gateway server : 【{}】", "http://127.0.0.1"); } }
GATEWAY配置类
package com.pet.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; @Configuration public class GatewayConfig { @Bean @LoadBalanced public RestTemplate restTemplate(ClientHttpRequestFactory factory) { RestTemplate restTemplate = new RestTemplate(factory); // 支持中文编码 restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout(5000);// 单位为ms httpRequestFactory.setConnectTimeout(5000);// 单位为ms return httpRequestFactory; } }
GATEWAY配置文件
后面的服务通过CONFIG配置中心读取配置文件!此时配置文件名为bootstrap.yml!
application.yml中啥也没有!
bootstrap.yml
server: port: 80 spring: application: name: gateway cloud: config: uri: http://localhost:8887 label: master name: gateway profile: dev discovery: enabled: true service-id: config fail-fast: true eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://EUREKA用户名:EUREKA密码@127.0.0.1:8888/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1 instance-id: 127.0.0.1:${spring.application.name}:${server.port}
真正读取的配置文件:
server: port: 80 logging: file: path: D:\LOG eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://EUREKA账号:EUREKA密码@127.0.0.1:8888/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1 instance-id: 127.0.0.1:${spring.application.name}:${server.port} management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS spring: application: name: gateway jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 cloud: gateway: routes: # maintain服务路由 - id: maintain uri: lb://maintain predicates: - Path=/maintain/** filters: - StripPrefix=1 - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback/error # websocket服务路由 - id: websocket uri: lb://websocket predicates: - Path=/websocket/** filters: - StripPrefix=1 - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback/error1 # fallback服务路由 - id: fallback uri: lb://fallback predicates: - Path=/fallback/** # eureka服务路由 - id: eureka uri: http://127.0.0.1:8888 predicates: - Path=/eureka/** filters: - StripPrefix=1 # admin服务路由 - id: admin uri: lb://admin predicates: - Path=/admin/** filters: - StripPrefix=1 feign: hystrix: enabled: true hystrix: command: default: execution: isolation: thread: # 全局熔断器5s超时 timeoutInMilliseconds: 5000
启动GATEWAY服务
这里gateway用了80端口,因为里面配置了一个指向EUREKA的路由,所以此时可以通过访问 127.0.0.1/eureka 来测试是否成功(测试后可以删除EUREKA路由,没啥用)
出现下面页面,说明配置成功。
分别启动FALLBACK、MAINTAIN、WEBSOCKET服务
这三个服务没啥特别,配置文件和GATEWAY一样,读取对应的配置文件就好
也可以启动多个实例,启动多实例方法(先修改好git上的配置文件的端口!然后再配置IDEA!):
调用GATEWAY对应路由规则的MAINTAIN服务提供的接口测试
路由规则:
FALLBACK服务提供的接口:
package com.pet.controller; import com.pet.config.ServiceException; import com.pet.constant.ErrorMsgConstant; import com.pet.vo.ResponseResultVO; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController @RequestMapping("/fallback") public class FallBackController { @RequestMapping("/error") public ResponseEntity> fallback() { log.error(ErrorMsgConstant.MAINTAIN_ERROR); throw new ServiceException(ErrorMsgConstant.MAINTAIN_ERROR); } @RequestMapping("/error1") public ResponseEntity > fallback1() { log.error(ErrorMsgConstant.WEBSOCKET_ERROR); throw new ServiceException(ErrorMsgConstant.WEBSOCKET_ERROR); } }
测试成功情况:
kill掉MATINTAIN服务,测试服务熔断:
forward到fallback服务的接口,说明配置成功:
最后启动ADMIN服务
启动类
package com.pet; import de.codecentric.boot.admin.server.config.EnableAdminServer; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableDiscoveryClient @EnableAdminServer @Slf4j public class AdminStarter { public static void main(String[] args) { SpringApplication.run(AdminStarter.class, args); log.info("start running admin server"); } }访问 127.0.0.1:8887 测试
出现下面页面,说明配置成功,具体作用大家自己探索把~
OpenFeign示例
WEBSOCKET服务接口
调用此方法可以推送websocket消息到页面。
package com.pet.controller; import com.pet.constant.RoomsConstant; import com.pet.event.entity.LogToDbEventEntity; import com.pet.servers.SystemInfoServer; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class PushLogController { private final SystemInfoServer systemInfoServer; @PostMapping("/pushLog") public void pushLogToWeb(@RequestBody LogToDbEventEntity log) { systemInfoServer.sendMsg(RoomsConstant.SYSTEM_INFO, log.toString()); } }MAINTAIN调用WEBSOCKET接口
package com.pet.service.manager; import com.pet.event.entity.LogToDbEventEntity; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient(value = "websocket") public interface PushLogService { @PostMapping(value = "/pushLog", consumes = "application/json") void pushDateToWeb(@RequestBody LogToDbEventEntity log); }
MAINTAIN服务切面代码,在所用使用了@LogController注解的方法,调用WEBSOCKET服务,推送消息。
package com.pet.config.aop; import com.pet.annotation.LogController; import com.pet.config.ServiceException; import com.pet.constant.ErrorMsgConstant; import com.pet.constant.HttpConstant; import com.pet.event.entity.LogToDbEventEntity; import com.pet.po.SysUser; import com.pet.service.manager.PushLogService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.Date; import java.util.Objects; @RequiredArgsConstructor @Aspect @Component @Slf4j public class PushLogAspect { private final PushLogService pushLogService; @Pointcut("@annotation(com.pet.annotation.LogController)") public void pushPoint() { } @Before(value = "pushPoint() && @annotation(logController)", argNames = "joinPoint, logController") public void beforeController(JoinPoint joinPoint, LogController logController) { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); HttpSession session = request.getSession(); SysUser user = (SysUser) session.getAttribute(HttpConstant.SESSION_USER); String realMethodName = joinPoint.getSignature().getName(); String requestIp = getIp(request); try { pushLogService.pushDateToWeb(LogToDbEventEntity.builder() .date(new Date()) .userName(Objects.isNull(user) ? "system" : user.getUserName()) .method(logController.method()) .logLevel(logController.logLevel()) .description(logController.description()) .realMethod(realMethodName) .ip(requestIp) .build()); } catch (Exception e) { throw new ServiceException(ErrorMsgConstant.WEBSOCKET_ERROR); } } public static String getIp(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-AuthenticationIp"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-AuthenticationIp"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } }
总结
大佬们如果clone下来可以用的话,给个免费的star吧~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)