This article is shared by Xu Haifeng, the head of Worktile Product R&D Department
PingCode is an intelligent R&D management tool created by the Worktile team. It is a benchmark against foreign Jira. It is committed to the automation, data and intelligence of R&D management to help companies improve R&D efficiency. This product will be launched in Q2 of 2019 and will be launched in 2019. officially released at the end, when just released called Worktile R & D edition, 2020 August 31 formal independence for the PingCode , then as a new development tool, many people would be more concerned about SaaS products this underlying technical architecture what exactly is it? Today, I, a new generation of migrant workers who have been in Worktile for eight years, will give you a detailed explanation.
Technical Selection
Friends who are familiar with Worktile must know that as a startup company that has been alive for a long time, we have always used Node.js as the underlying server-side technology. Before 2019, we have used Node.js to develop for 6 years. the Node.js upgrade to the latest version from 0.x of 14.x (of course, now the official is already 17.x), from everywhere callback
era to the unified asynca
wait
, also witnessed the points Node.js Foundation With Hehe, Node.js has many advantages, but it also has many disadvantages, especially for medium and large enterprise applications. No type system is an eternal pain. Fortunately, we introduced TypeScript in 2018, which is simply for Node. js has added a flower to the cake. We are very fortunate to have fully switched to TypeScript in 2018. As a new product will be Node.js + TypeScript
2019, we have no suspense to continue ALL IN 061cbf97350bd0, and also add MongoDB
and Redis
, it is a perfect match.
There is no suspense about the selection of front-end technology. We are one of the few domestic companies that firmly follow Angular. The philosophy of Angular is also in line with our company's temperament. insists on long-termism and pursues the ultimate . What is difficult to attract people? Cultivating people is not a problem. If you want to know more about the , please see 161cbf97350bf9 Worktile Front-end Engineering Road .
The following picture basically covers the core technology stack of PingCode. The previous architecture was called MEAN
(representing MongoDB + Express + Angular + Node.js), I think it can be called MTAN
(representing MongoDB + TypeScript + Angular + Node.js).
Monolithic application to microservice architecture
Worktile has always been a single application in the past, and even after many years, the front and back ends are completely separated. Then the PingCode matrix product structure determines the most appropriate architecture model is the microservice architecture, and each sub-product is independently stored and developed independently. And independent deployment, PingCode's overall layered architecture diagram is as follows:
Our storage and service use ancient Greek mythological characters nomenclature, so you will see: chaos
, eros
, typhon
, atlas
and other ancient Greek characters.
The most difficult thing about microservices is how to split services. From a vertical perspective, we provide some basic services, namely:
- Atlas : File service, encapsulates AWS S3 related functions, including: upload, download, preview and other file-related functions, in a private deployment environment, seamlessly switch to MinIO
- Iris : Message service, mainly including message notification, Feed (real-time update notification) related functions, mainly using SocketIO and Redis
- Typhon : Account service, including general functions related to registration, login, member management, authorization, and verification
PingCode is a matrix structure model of sub-products, so we can easily divide micro-services according to sub-products. Of course, some sub-products will also have deep coupling, so the product form determines that we can choose a brainless The horizontal division type.
- Agile : agile development sub-product, providing Scrum and Kanban two agile development project templates
- Testhub : Test management sub-product, providing test cases, test plans, etc. and test-related function points
- Wiki : Knowledge base sub-product, enterprise-level knowledge base.
- etc...
We chose the microservice architecture in 2019 for the following two reasons:
- We have accumulated 6 years of technology in the past, and in 2018 we started to develop our own TypeScript underlying framework CHAOS.
- At the same time, with the growth of personnel, it is necessary to consider an architectural model that adapts to multiple teams and multiple organizations, and microservices are the only way to choose
Challenges posed by microservice architecture
After adopting the microservice architecture, the requirements for development and operation and maintenance will become higher. This is actually not a simple architecture upgrade, but an upgrade of the entire production and research capabilities. A single architecture is more appropriate in the early stage of a startup, so when choosing a microservice Ask yourself before the architecture: Are you ready?
So for development and operation and maintenance, what challenges do microservices bring?
Development challenges
Microservices mainly bring three major challenges to our development, namely:
So let’s take a look at the abstraction. Abstraction is a very important ability for developers. This ability determines whether we can grow into a qualified architect and whether we can do infrastructure-related work without the business. In the past, because the monolithic application was too much It is simple and does not require high abstract capabilities. After microservices, each service is independently stored and developed independently. As the complexity increases, the previous method of using a single shuttle in a single application is not applicable. For example: will create a team after successful registration. After the team is created, each sub-product needs to initialize business data (such as the sample project) .
Because the registration function is in the Typhon account service, the account service is a basic service that is called by other sub-products. In a single application, EventBus
, and other sub-modules can be subscribed for initialization, or even directly Call the initialization logic code of other modules, but each sub-service under the microservice is independent. Allowing the account service to call the RPC of each sub-product will cause dependency confusion. Eventually a message queue may be introduced, and each sub-product will add an initialized service subscription message Queue, then its very simple function becomes complicated, and the requirements of the microservice architecture for developers are also increased. Development needs to think from a higher perspective on how to abstract, how to communicate better between services, etc. Issues that do not need to be considered under the application.
Another thing is that each service is independent. It is necessary to extract the common basic class library and the SDK of each service. The extraction of the business basic class library requires the abstraction . If the business abstraction cannot be done well, then How to do the infrastructure. We abstracted a low-level framework
CHAOS
(equivalent to NestJS ) based on TypeScript, and abstracted the underlying business class libraries EROS
and PC-CORE
. The following figure is a schematic diagram of the dependencies and modules related to the basic library.
The second challenge is project, we have already mentioned above, the more base class libraries and services SDK, how these private libraries package management and distribution, and so some project-related problems have cropped up.
For the release of private class libraries, we first used a GitHub private repository as the class library package, and then implemented it in the business by configuring the dependent GitHub link, using the following:
To this end, a separate package distribution tool was developed and released to the git repository. If you are interested, you can view git-publish
"dependencies: {
"@worktile/chaos": "git+ssh://git@github.com:worktile/chaos-built.git#1.0.0",
}
Later, GitHub provided a private package for the storage. We directly used GitHub's private storage for package management, so that there was no need to create a separate built
storage to store the products after the class was built. Before, we had to allocate this built storage separately to developers. Permissions and so on. After adopting the GitHub private package, you only need to configure the developer to create a AccessToken
, so as long as you have the corresponding permission to access the warehouse, you can install or publish the warehouse private package.
For engineering, we also encountered a release
, version management,
branch management, etc. These are the problems that need to be solved one by one under the micro-service architecture model. There is no standard solution that is suitable for the team and meets the current What the team needs are good solutions, and engineering issues are also the only way for our team to go from a gang to a regular army. Therefore, for developers, in addition to writing business code, they may also need to write development tools, development specification documents, and so on.
The third challenge is collaboration. Each team is responsible for its own products or services. There will be dependencies and calls to services. So how do teams collaborate? We unified all basic libraries and SDKs in Kanban for project management. Everyone can submit issues and contribute code, which is transparent to everyone. Each basic library will have a person in charge who is mainly responsible for Code Review and classes. The planning of the library, of course, includes other aspects of collaboration. We use agile methods to iterate continuously and continuously improve.
The following figure is an example of the Kanban project for infrastructure:
The above are the three major challenges that microservice architecture poses to us. Perhaps the solution you might think of for problems such as abstraction and engineering is Monorepo, but Monorepo is not a silver bullet. It may be the best solution in the early stage, but with The large warehouse code and the increase in members will also encounter a series of problems, such as slow construction, long testing time, conflicts, etc. Monorepo problems, so we did it three years ago and only saw the benefits after three years In fact, this is also our confidence in PingCode products, but looking back, these challenges have not affected the speed of our product iteration, and compared with competing products, it is not weak or even stronger.
Operation and maintenance challenges
Microservices have led to an increase in services, more warehousing, and complex dependencies. For operation and maintenance, how to manage these services has become more difficult. We also introduced Jenkins in 2019 to implement CI and CD.
There are CI and CD, but it is basically difficult to move forward without testing. In the PingCode server, we will also force each API to have a test, and the test coverage of business code must be above 80%, and the basic class library must To be more than 90%, although the test coverage index does not completely represent the comprehensiveness of the test, at least the core logic will be covered. Secondly, there will be integration tests, persistence tests, and performance tests for business-coupled services. In fact, testing is not The direct challenges brought by microservices also require testing under monolithic applications.
Except for CI and CD, all services adopt Kubernetes for containerized deployment. Service monitoring and warning, ELB, logs, etc. and operation and maintenance related challenges will follow. Log storage adopts ElasticSearch, management and viewing adopts Kibana.
Single service architecture
Microservices will split all services, but for a single service, most of our sub-products have similar architectures. Except for common functions, they will be divided according to modules. Each module is roughly divided into three layers. : Facade layer (actually the API or Controller layer, this layer only contains routing definitions and parameter input and output, not business logic),
Service layer (domain layer, also business logic layer),
Repository layer (Including the addition, deletion, modification, and query operations for a single entity in the database, each Repository will have an Entity entity).
The following code snippet represents a ProjectEntity
and ProjectRepository
@collectionName("agile_projects")
@indexes<ProjectEntity>([
{
team: Direction.ascending,
}
])
export class ProjectEntity extends BusinessEntity {
public name?: string;
public name_pinyin?: string;
public description?: string;
public icon?: string;
public color?: string;
public identifier?: string;
public members?: PrincipalMember[];
@defaultValue(() => Visibility.private)
public visibility?: Visibility;
}
@injectable()
export class ProjectRepository extends DefaultBusinessRepository<ProjectEntity> {
constructor() {
super(ProjectEntity);
}
}
A Facade sample code is as follows:
@facade()
@middlewares(
typhonClient.passport.authMiddleware(),
typhonClient.application.applicationExpireMiddleware(ApplicationType.agile)
)
export class ProjectFacade extends FacadeBase {
@inject()
private projectService: ProjectService;
@post("/project", CreateProjectRequest)
@middlewares(projectPermission.authCreateProjectMiddleware())
public async createProject(request: CreateProjectRequest): Promise<Response<ProjectEntity, void>> {
const project = await this.projectService.createProject(request);
return new Response(project);
}
}
Regarding our underlying framework CHAOS, I will introduce more here. CHOAS provides a complete set of enterprise-level frameworks from application, routing, container to data access layer to meet our business needs, so for applications and routing, we are based on Koa. The second encapsulation on top of js, CHAOS shields Koa related APIs, so even if the underlying switch to Express or more advanced web frameworks is insensitive to users, the second is that Repository is also the second encapsulation of the mongodb module, except for this. Some of the core functions are completely self-developed, including:
- Container : Container, to help applications easily achieve dependency injection
- Rpc : Microservice RPC communication framework
- Reminder : Basic class library for timing tasks, responsible for providing task registration, execution, error handling, etc.
Other modules...
Micro front-end architecture
Like the micro-service architecture, we also introduced the micro-front-end in 2019. Because we did not find a suitable micro-front-end framework, we self-developed ngx-planet -a micro-front-end solution under the Angular framework that I think is the best to use plan. The following is a schematic diagram of the entire micro front-end architecture:
Portal
is the main application, also called the base application. It is responsible for the navigation, global data management, notification, search and other global functions on the left. The most important thing is to realize the registration, loading and destruction of sub-applications through ngx-planet at runtime.
Each application is divided into sub-products to build and provide a manifest.json
static resource files. The main application will load the corresponding scripts and styles based on this resource list.
Then the challenges of front-end development after adopting micro-front-end architecture are similar to those of micro-services. I also abstract ,
project and
collaboration.
The first one is the abstraction . We have already built an internal component library in 2018. After the micro front end in 2019, we also need to build a business component library. In fact, doing business components can test the developer’s abstraction ability the most. The component library You can refer to the design and API of the corresponding components of other component libraries, but there is no reference to the business component library. We often encounter a small partner who has worked hard to submit a PR for a business component library. As a result, a Code Review found that this has been supported Or there is a better solution than this, so we later formulated a specification. When you submit a new feature for a component library or business component, describe the specific scenarios and requirements, and then think about how you plan to design (including (API parameters, naming, structure, etc.) and then @ about everybody in the comments, so that everyone can brainstorm based on your plan and finally determine a plan that everyone feels is more complete.
In PingCode, apart from using the third-party highcharts as the report library, we basically have not introduced other third-party libraries. It is not how powerful our team is, but thanks to Angular's CDK , through CDK can easily develop business component library and component library, CDK let this team of 20 people less than the front-end impossible becomes
possible (of course, some of the components set price database will learn (the Chao) Angular Material and NG- and other excellent component libraries). Some people say that we are the company with the most wheels in China under the Angular framework, including:
- Angular micro front-end framework ngx-planet
- Angular Gantt chart component ngx-gantt
- Slate framework Angular view layer slate-angular
- Angular component documentation generation tool docgeni
- Simple and easy to use state management library @tethys/store
These are not KPI projects. They are the actual business problems we encountered in solving PingCode and Worktile. But the Angular community has no better solution. We are satisfied with ourselves and open source to give back to the community. We will continue to improve and iterate. For libraries that are already open source, open source itself is also a technical challenge for development, and doing an open source project is actually not easy. The solutions for these specific scenarios above are all manifestations of abstraction capabilities, and PingCode front-end developers are also improving their abstraction capabilities in the process of working on these open source projects.
The second challenge is engineering, and as micro-services, in the past there is no front-end micro Monorepo on direct, specific reasons for not going to say, but so far, to bring the front end of the core micro-engineering problems, we It’s all solved. The package was distributed using GitHub’s private package. Angular was very slow to compile the library at the beginning, which brought a lot of challenges to the business component library that was frequently packaged. With the upgrade of Angular, the current speed has risen significantly, and it will be approved later. GitHub's Actions can automatically send packages, which reduces manual repetitive operations. The improvement of local development efficiency has always been our concern. We have a test environment in which all services and front-end applications are deployed in this internally accessible test environment. The local development of the front-end can only start local services. Then you can access the local through the Portal of the test environment, and then the local Portal can also use the sub-applications of the test environment. Our solution is mainly for the development of a simple proxy configuration interface, which can directly intercept and proxy the front end in the micro front end. Resources, no need to start applications and install agent tools locally.
Regarding the collaboration, I want to say something that has nothing to do with the technical framework. I myself have always pursued the ultimate pursuit of code. I hope that my team is not just to complete the task, but to think about how to do the best, and the technology can be obtained. Better improvement, even if the ability is not up to now, but you must have a heart to pursue the ultimate, so I often see some inappropriate naming or bad design will be proposed, and at the same time, because the team grows, cross-team communication There will be less. In order to make the technology atmosphere of the whole team more positive, we will insist on bi-weekly technology sharing, daily learning, internal technology weekly, etc. to improve everyone's communication and sharing skills.
Angular front-end architecture
After adopting the micro front-end, the architecture of a single front-end becomes relatively simple. Each sub-product of PingCode divides the business according to the feature module. Each feature module will contain: pages
, stores
, components
, pipe
, services
and other functions, except for the feature module There will also be some global core
and shared
, where only the components and services of the current sub-product are stored, and the basic cross-sub-products are already in the business component library.
In addition to the specific area of the Wiki editor, the PingCode front-end is the most complex is data management (also called state management), because the form of the product determines that we have very high requirements for real-time data, ensuring that the data is not refreshed. Data can be updated in real time. Data updates will come from first loading, editing, and WebSocket. For Angular state management, please refer to the blog I wrote a few years ago. Does Angular really need state management? mainly based on a small state management library @tethys/store that we encapsulated to achieve the Service + Observable
combination. The structure diagram of multiple stores is:
The most worth mentioning in data management is the maintenance of reference data. The PingCode server API will only return atomic data. The front-end uses RxJS to aggregate data. @tethys/store 161cbf9735144c. I will write an article when I have time. To introduce in detail, the data format is shown in the figure below:
The above is my mystery of the technical architecture of PingCode products. I slackerly talked about a lot of topics that may have nothing to do with the technical architecture. I hope to bring some resonance and thinking to readers. This is also the mental journey of a small and medium-sized R&D team along the way. PingCode Technology The architecture may not be the best architecture, but from the current perspective, it is a more suitable architecture. We will maintain our original intention and continue to move forward to provide better management tools for R&D.
Finally, I recommend our intelligent R&D management tool PingCode to everyone.
About PingCode
PingCode is an intelligent R&D management tool created by the established domestic SaaS manufacturer Worktile. It has launched Agile (Agile Development), Testhub (Test Management), Wiki (Knowledge Base), Plan (Project Set), Goals (Goals) around the needs of enterprise R&D management. Management), Flow (automated management), Access (catalog management) seven sub-products and application market, to achieve the coverage of the whole process of R&D management such as projects, tasks, requirements, defects, iterative planning, testing, target management, and code hosting Open up many mainstream development tools such as tools, CI/CD pipeline, automated testing, etc.
Since its official release, there have been more than 13 well-known companies represented by Kugou Music, SenseTime, Dianbank Information, 51 Social Security, GDS, Golden Eagle Cartoon, UFIDA, Guoqi Intelligent Control, Wisdom Tooth Customer Service, and Yikuaibao. Many companies in the industry choose PingCode to implement R&D management.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。