大数跨境
0
0

开源 | 推荐几个非常实用的 Spring Cloud 实战项目

开源 | 推荐几个非常实用的 Spring Cloud 实战项目 终码一生
2021-07-24
0
导读:建议收藏!

点击上方“终码一生”,选择“加为星标

第一时间获取技术干货!



把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,这就是微服务架构的架构概念,通过将功能分解到各个离散的服务中以实现对解决方案的解耦。


关于微服务相关的学习资料不多,而 GitHub 上的开源项目可以作为你微服务之旅的第一站。本文推荐几个非常火的微服务项目,从入门到实战,这篇文章值得收藏。


 

1

不二之选

 

第一个推荐的项目是高赞教程:PiggyMetrics,这个开源项目是你开启微服务之旅的不二之选。


PiggyMetrics是一个很全面的微服务实践入门的实例集,它可以指导开发者使用Spring BootSpring CloudDocker搭建微服务架构。


该开源项目有一个典型的微服务实现案例 - 个人理财微服务系统。采用Spring Boot/Spring Cloud等技术栈,来实现微服务的开发、构建和治理,麻雀虽小五脏俱全。


在这个案例中,你可以全面地了解到微服务的注册发现、配置中心、熔断、路由、负载均衡、注解式Http客户端、认证鉴权和全链追踪等技术,同时还有日志、监控、度量指标等运维指标统计分析。



PiggyMetrics 被分解为三个核心微服务,它们都是可独立部署的应用程序。如果你具备了微服务的基础知识,没有实战经验,从这个项目开始吧。


地址:https://github.com/sqshq/piggymetrics




2

分布式电商项目


基于 Spring Cloud 的分布式电商项目,该项目使用分库设计方案,不同的模块依赖不同的数据库实例。后台登陆采用 Oauth 2.0 授权,支持密码登陆、授权码登陆、短信验证码登陆、注册中心与配置中心已使用 alibaba naco。另外,关注我们公号终码一生,回复“资料”,可以获取相关技术视频教程和最新面试资料。


目标打造顶级多模块,高可用,高扩展电商项目。


技术栈基于 Spring Boot、Spring Cloud、Spring Oauth2 和 Spring Cloud Netflix 等框架,可以借助该项目学习Spring Cloud 技术栈,作为练手项目。


地址:https://github.com/SiGuiyang/spring-cloud-shop





3

轻松阅读微服务项目


轻松阅读是一款图书阅读类 APP,基于 Spring Cloud 开发的微服务实战项目,涉及 SpringCloud-Gateway、Nacos、Hystrix、OpenFeign、Jwt、ElasticSearch 等技术栈的应用。



客户端:https://github.com/Zealon159/light-reading-cloud-client

api:https://github.com/Zealon159/light-reading-cloud


核心架构图如下:



4

SpringBlade 微服务开发平台


SpringBlade采用前后端分离的模式,前端基于 React、Ant Design、Vue、Element-UI。后端采用 Spring Cloud 全家桶,注册中心、配置中心选型 Nacos,简封装了多租户底层,用更少的代码换来拓展性更强的 SaaS 多租户系统。


地址:https://gitee.com/smallc/SpringBlade



5

Cloud-Platform


Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API 管理等多个模块,支持多业务系统并行开发,可以作为后端服务的开发脚手架。代码简洁,架构清晰,适合学习和直接项目中使用。另外,关注我们公号终码一生,回复“资料”,可以获取相关技术视频教程和最新面试资料。










一直觉得java原生API都是性能很高的,今天看一篇博客时,说到System.currentTimeMillis()的性能十分低下,觉得很奇怪,于是写了一些代码来尝试了一下


复制代码

public class CurrentTimeTest {

    private static final int COUNT = 100;

    public static void main(String[] args) throws Exception {

        long beginTime = System.nanoTime();

        for (int i = 0; i < COUNT; i++) {

            System.currentTimeMillis();

        }

        long elapsedTime = System.nanoTime() - beginTime;

        System.out.println("单线程100次   System.currentTimeMillis : " + elapsedTime + " ns");

        CountDownLatch startLatch = new CountDownLatch(1);

        CountDownLatch endLatch = new CountDownLatch(COUNT);

        for (int i = 0; i < COUNT; i++) {

            new Thread(() -> {

               try {

                   startLatch.await();

                   System.currentTimeMillis();

               } catch (InterruptedException e) {

                   e.printStackTrace();

               } finally {

                   endLatch.countDown();

               }

            }).start();

        }

        beginTime = System.nanoTime();

        startLatch.countDown();

        endLatch.await();

        elapsedTime = System.nanoTime() - beginTime;

        System.out.println("100线程并发下 System.currentTimeMillis : " + elapsedTime + " ns");

    }

}

复制代码

执行结果如下:




 


可见System.currentTimeMoillis一百次耗费的时间非常大,尤其是并发状态下比单线程高出一个量级,甚至极端情况比创建对象更耗费资源


查看HotSpot源码的hotspot/src/os/linux/vm/os_linux.cpp,有一个javaTimeMillis方法,这就是System.currentTimeMillis的native实现。


复制代码

jlong os::javaTimeMillis {

    timeval time;

    int status = gettimeofday(&time, NULL);

    assert(status != -1, "linux error");

    return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);

}

复制代码

对于这部分源码已经有国外大佬深入到了汇编的级别来探究,详情可以参见《The Slow currentTimeMillis》


简单来讲就是:

    1.调用gettimeofday需要从用户态切换到内核态;

    2.gettimeofday的表现受Linux系统的计时器(时钟源)影响,在HPET计时器下性能尤其差;

    3.系统只有一个全局时钟源,高并发或频繁访问会造成严重的争用。


HPET计时器性能较差的原因是会将所有对时间戳的请求串行执行。TSC计时器性能较好,因为有专用的寄存器来保存时间戳。缺点是可能不稳定,因为它是纯硬件的计时器,频率可变(与处理器的CLK信号有关)。关于HPET和TSC的细节可以参见下面的链接,就不做过多讨论

https://en.wikipedia.org/wiki/HighPrecisionEventTimer

https://en.wikipedia.org/wiki/TimeStamp_Counter


那么如何避免这个问题?最常见的办法是用单个调度线程来按毫秒更新时间戳,相当于维护一个全局缓存。其他线程取时间戳时相当于从内存取,不会再造成时钟资源的争用,代价就是牺牲了一些精确度。具体代码如下。


复制代码

@Component

public class TimeServcie {

    private static long time;


    static {

        new Thread(new Runnable() {

            @Override

            public void run() {

                while (true) {

                    try {

                        Thread.sleep(5);

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    long cur = System.currentTimeMillis();

                    setTime(cur);

                }

            }

        }).start();

    }


    public static long getTime() {

        return time;

    }


    public static void setTime(long time) {

        TimeServcie.time = time;

    }

}

复制代码

关于Jvm调优Oracle官网有一份指导说明:


https://docs.oracle.com/middleware/11119/wls/PERFM/jvm_tuning.htm#i1146060






4Jvm调优实战

 


1、未设置JVM参数的情况



我现在有一个项目,默认情况下,没有设置任何Jvm参数。




下面我来启动看一下。




图片



看一下堆栈分配:




很明显默认的最大堆内存分配了8个G。很明显的不合理嘛。




图片


2、下面我们来设置下Jvm参数



例如要配置JVM这么一大段参数:




-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC



方式一:




如果你用的是IDEA等开发工具,来启动运行项目,那么要调试JDK就方便太多了。




只需要将参数值设置到VM options中即可。




图片



设置成功,我的GC日志和堆栈分配都已经OK了。




GC日志:




图片



堆栈分配:




图片



方式二:




适用于在项目部署后,在启动的时候,采用脚本或者命令行运行的时候设置。




先在项目路径下,给项目打包:




清理就项目




mvn clean


图片



打包新项目:




mvn package -Dmaven.test.skip=true



打包完成后进入可运行Jar包的路径下:




图片



执行启动设置Jvm参数的操作。




$ java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC newframe-1.0.0.jar



这个时候,你再看监控,你就会发现,已经是Ok的了。




堆栈都是按照启动时候,设置的Jvm参数启动的。




图片



关于这些设置的JVM参数是什么意思,请参考第二步中的oracle官方给出的调优文档。




我在这边简单说一下:




-XX:MetaspaceSize=128m (元空间默认大小)

-XX:MaxMetaspaceSize=128m (元空间最大大小)

-Xms1024m (堆最大大小)

-Xmx1024m (堆默认大小)

-Xmn256m (新生代大小)

-Xss256k (棧最大深度大小)

-XX:SurvivorRatio=8 (新生代分区比例 8:2)

-XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)

-XX:+PrintGCDetails (打印详细的GC日志)



知识点:




JDK8之后把-XX:PermSize 和-XX:MaxPermGen移除了,取而代之的是




-XX:MetaspaceSize=128m (元空间默认大小)

-XX:MaxMetaspaceSize=128m (元空间最大大小)



JDK 8开始把类的元数据放到本地化的堆内存(native heap)中,这一块区域就叫Metaspace,中文名叫元空间。




使用本地化的内存有什么好处呢?最直接的表现就是java.lang.OutOfMemoryError: PermGen 空间问题将不复存在,因为默认的类的元数据分配只受本地内存大小的限制,也就是说本地内存剩余多少,理论上Metaspace就可以有多大(貌似容量还与操作系统的虚拟内存有关?这里不太清楚),这解决了空间不足的问题。




不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。



 










核心技术采用Spring Boot 2.4.1、Spring Cloud (2020.0.0)以及Spring Cloud Alibaba 2.2.4 相关核心组件,采用Nacos注册和配置中心,集成流量卫兵Sentinel,前端采用vue-element-admin组件,Elastic Search自行集成。


地址:https://gitee.com/geek_qi/cloud-platform




6

互联网云快速开发框架


一款免费开源的 Java互联网云快速开发平台,微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中分布式、分布式事务、微服务,同时包含许多基础模块和监控、服务模块。


被评为 2018 年度最受欢迎中国开源软件项目。


地址:https://gitee.com/JeeHuangBingGui/jeeSpringCloud



好了,以上是今天推荐给大家的几个开源项目,如果有需要的话,可以自己去研究下哦!


PS:防止找不到本篇文章,可以收藏点赞,方便翻阅查找哦。 



END

 


终码一生
长按扫描二维码
关注我们 学习更多技术
微信号:zma_1314


往期推荐

SpringBoot 项目优化和 Jvm 调优

SQL查找是否"存在",别再 count 了!

Intellij IDEA 这些操作小技巧你用过吗?

Java 8 失宠?开发人员向 Java 11 转移...

Java8 中的 Stream 流那么强大,你知道它原理吗?

10 款 Java 后台管理系统项目,接私活必备!


【声明】内容源于网络
0
0
终码一生
开发者聚集地。分享Java相关开发技术(JVM,多线程,高并发,性能调优等),开源项目,常见开发问题和前沿科技资讯!
内容 1876
粉丝 0
终码一生 开发者聚集地。分享Java相关开发技术(JVM,多线程,高并发,性能调优等),开源项目,常见开发问题和前沿科技资讯!
总阅读1.3k
粉丝0
内容1.9k